* [PATCH net-next 20/21] net: dsa: mv88e6xxx: factorize tag protocol
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
6131 is the only driver to set the tag protocol to DSA_TAG_PROTO_DSA.
Since it works fine with DSA_TAG_PROTO_EDSA, change its value, like all
other mv88e6xxx drivers.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/Kconfig | 2 +-
drivers/net/dsa/mv88e6131.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 4aaadce..7e01dce 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -17,7 +17,7 @@ config NET_DSA_MV88E6131
tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
depends on NET_DSA
select NET_DSA_MV88E6XXX
- select NET_DSA_TAG_DSA
+ select NET_DSA_TAG_EDSA
---help---
This enables support for the Marvell 88E6085/6095/6095F/6131
ethernet switch chips.
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 22952be..bbad199 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -59,7 +59,7 @@ static const char *mv88e6131_drv_probe(struct device *dsa_dev,
}
struct dsa_switch_driver mv88e6131_switch_driver = {
- .tag_protocol = DSA_TAG_PROTO_DSA,
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6131_drv_probe,
.setup = mv88e6xxx_setup,
.set_addr = mv88e6xxx_set_addr,
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 19/21] net: dsa: mv88e6xxx: factorize switch setup
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Provide a shared mv88e6xxx_setup function to the drivers.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 16 +----------
drivers/net/dsa/mv88e6131.c | 16 +----------
drivers/net/dsa/mv88e6171.c | 16 +----------
drivers/net/dsa/mv88e6352.c | 16 +----------
drivers/net/dsa/mv88e6xxx.c | 69 ++++++++++++++++++++++-----------------------
drivers/net/dsa/mv88e6xxx.h | 3 +-
6 files changed, 38 insertions(+), 98 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 8f3a7c5..2bc407b 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -51,24 +51,10 @@ static const char *mv88e6123_drv_probe(struct device *dsa_dev,
ARRAY_SIZE(mv88e6123_table));
}
-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(ps);
- if (ret < 0)
- return ret;
-
- return mv88e6xxx_setup_ports(ds);
-}
-
struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6123_drv_probe,
- .setup = mv88e6123_setup,
+ .setup = mv88e6xxx_setup,
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index da28327..22952be 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -58,24 +58,10 @@ static const char *mv88e6131_drv_probe(struct device *dsa_dev,
ARRAY_SIZE(mv88e6131_table));
}
-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(ps);
- if (ret < 0)
- return ret;
-
- return mv88e6xxx_setup_ports(ds);
-}
-
struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA,
.probe = mv88e6131_drv_probe,
- .setup = mv88e6131_setup,
+ .setup = mv88e6xxx_setup,
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 83678ad..4bf517a 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -58,24 +58,10 @@ static const char *mv88e6171_drv_probe(struct device *dsa_dev,
ARRAY_SIZE(mv88e6171_table));
}
-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(ps);
- if (ret < 0)
- return ret;
-
- return mv88e6xxx_setup_ports(ds);
-}
-
struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6171_drv_probe,
- .setup = mv88e6171_setup,
+ .setup = mv88e6xxx_setup,
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 81810dd..d65a90d 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -77,24 +77,10 @@ static const char *mv88e6352_drv_probe(struct device *dsa_dev,
ARRAY_SIZE(mv88e6352_table));
}
-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(ps);
- if (ret < 0)
- return ret;
-
- return mv88e6xxx_setup_ports(ds);
-}
-
struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6352_drv_probe,
- .setup = mv88e6352_setup,
+ .setup = mv88e6xxx_setup,
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 261ca9a..328349b 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2632,14 +2632,12 @@ static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
return ret;
}
-static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
+static int _mv88e6xxx_setup_port(struct mv88e6xxx_priv_state *ps, int port)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct dsa_switch *ds = ps->ds;
int ret;
u16 reg;
- mutex_lock(&ps->smi_mutex);
-
if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) ||
@@ -2668,7 +2666,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_PCS_CTRL, reg);
if (ret)
- goto abort;
+ return ret;
}
/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
@@ -2732,7 +2730,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_CONTROL, reg);
if (ret)
- goto abort;
+ return ret;
}
/* If this port is connected to a SerDes, make sure the SerDes is not
@@ -2741,14 +2739,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
if (mv88e6xxx_6352_family(ps)) {
ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS);
if (ret < 0)
- goto abort;
+ return ret;
ret &= PORT_STATUS_CMODE_MASK;
if ((ret == PORT_STATUS_CMODE_100BASE_X) ||
(ret == PORT_STATUS_CMODE_1000BASE_X) ||
(ret == PORT_STATUS_CMODE_SGMII)) {
ret = mv88e6xxx_power_on_serdes(ps);
if (ret < 0)
- goto abort;
+ return ret;
}
}
@@ -2785,7 +2783,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_CONTROL_2, reg);
if (ret)
- goto abort;
+ return ret;
}
/* Port Association Vector: when learning source addresses
@@ -2800,13 +2798,13 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg);
if (ret)
- goto abort;
+ return ret;
/* Egress rate control 2: disable egress rate control. */
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL_2,
0x0000);
if (ret)
- goto abort;
+ return ret;
if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
@@ -2818,7 +2816,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_PAUSE_CTRL, 0x0000);
if (ret)
- goto abort;
+ return ret;
/* Port ATU control: disable limiting the number of
* address database entries that this port is allowed
@@ -2832,7 +2830,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_PRI_OVERRIDE, 0x0000);
if (ret)
- goto abort;
+ return ret;
/* Port Ethertype: use the Ethertype DSA Ethertype
* value.
@@ -2840,14 +2838,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_ETH_TYPE, ETH_P_EDSA);
if (ret)
- goto abort;
+ return ret;
/* Tag Remap: use an identity 802.1p prio -> switch
* prio mapping.
*/
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_TAG_REGMAP_0123, 0x3210);
if (ret)
- goto abort;
+ return ret;
/* Tag Remap 2: use an identity 802.1p prio -> switch
* prio mapping.
@@ -2855,7 +2853,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_TAG_REGMAP_4567, 0x7654);
if (ret)
- goto abort;
+ return ret;
}
if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
@@ -2866,7 +2864,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port),
PORT_RATE_CONTROL, 0x0001);
if (ret)
- goto abort;
+ return ret;
}
/* Port Control 1: disable trunking, disable sending
@@ -2874,7 +2872,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
*/
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000);
if (ret)
- goto abort;
+ return ret;
/* Port based VLAN map: give each port the same default address
* database, and allow bidirectional communication between the
@@ -2882,33 +2880,20 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
*/
ret = _mv88e6xxx_port_fid_set(ps, port, 0);
if (ret)
- goto abort;
+ return ret;
ret = _mv88e6xxx_port_based_vlan_map(ps, port);
if (ret)
- goto abort;
+ return ret;
/* Default VLAN ID and priority: don't set a default VLAN
* ID, and set the default packet priority to zero.
*/
ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN,
0x0000);
-abort:
- mutex_unlock(&ps->smi_mutex);
- return ret;
-}
-
-int mv88e6xxx_setup_ports(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
- int i;
+ if (ret)
+ return ret;
- for (i = 0; i < ps->info->num_ports; i++) {
- ret = mv88e6xxx_setup_port(ds, i);
- if (ret < 0)
- return ret;
- }
return 0;
}
@@ -3123,9 +3108,13 @@ static int _mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
return err;
}
-int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
+int mv88e6xxx_setup(struct dsa_switch *ds)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int err;
+ int i;
+
+ ps->ds = ds;
mutex_init(&ps->smi_mutex);
@@ -3144,6 +3133,14 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
goto unlock;
err = _mv88e6xxx_setup_global(ps);
+ if (err)
+ goto unlock;
+
+ for (i = 0; i < ps->info->num_ports; i++) {
+ err = _mv88e6xxx_setup_port(ps, i);
+ if (err)
+ goto unlock;
+ }
unlock:
mutex_unlock(&ps->smi_mutex);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 555903f..c2801ff 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -598,8 +598,7 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
const struct mv88e6xxx_info *table,
unsigned int num);
-int mv88e6xxx_setup_ports(struct dsa_switch *ds);
-int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps);
+int mv88e6xxx_setup(struct dsa_switch *ds);
int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
int reg, u16 val);
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 18/21] net: dsa: mv88e6xxx: factorize frames priorities
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
6131 is the only driver to setup the priority of IGMP/MLD snoop frames
and ARP frames to the highest setting. Drop such change until we figure
out a common configuration for all switch models.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6131.c | 18 ------------------
1 file changed, 18 deletions(-)
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index b6ca07b..da28327 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -58,20 +58,6 @@ static const char *mv88e6131_drv_probe(struct device *dsa_dev,
ARRAY_SIZE(mv88e6131_table));
}
-static int mv88e6131_setup_global(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
- /* Force the priority of IGMP/MLD snoop frames and ARP frames
- * to the highest setting.
- */
- return mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
- GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP |
- 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT |
- GLOBAL2_PRIO_OVERRIDE_FORCE_ARP |
- 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT);
-}
-
static int mv88e6131_setup(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -83,10 +69,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ret = mv88e6131_setup_global(ds);
- if (ret < 0)
- return ret;
-
return mv88e6xxx_setup_ports(ds);
}
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 16/21] net: dsa: mv88e6xxx: factorize GLOBAL_MONITOR_CONTROL setup
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
All switch drivers configure the GLOBAL_MONITOR_CONTROL register with
slightly changes.
Assume the setup of the upstream port, and configure it as the port to
which ingress and egress and ARP monitor frames are to be sent.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 14 --------------
drivers/net/dsa/mv88e6131.c | 13 -------------
drivers/net/dsa/mv88e6171.c | 15 ---------------
drivers/net/dsa/mv88e6352.c | 14 --------------
drivers/net/dsa/mv88e6xxx.c | 12 ++++++++++++
5 files changed, 12 insertions(+), 56 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 1cd30ac..5df06d8 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -54,20 +54,6 @@ static const char *mv88e6123_drv_probe(struct device *dsa_dev,
static int mv88e6123_setup_global(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u32 upstream_port = dsa_upstream_port(ds);
- int ret;
- u32 reg;
-
- /* Configure the upstream port, and configure the upstream
- * port as the port to which ingress and egress monitor frames
- * are to be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
- if (ret)
- return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 1c3b245..c8e3974 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -61,20 +61,7 @@ static const char *mv88e6131_drv_probe(struct device *dsa_dev,
static int mv88e6131_setup_global(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u32 upstream_port = dsa_upstream_port(ds);
int ret;
- u32 reg;
-
- /* Disable ARP mirroring, and configure the upstream port as
- * the port to which ingress and egress monitor frames are to
- * be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- GLOBAL_MONITOR_CONTROL_ARP_DISABLED;
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
- if (ret)
- return ret;
/* Disable cascade port functionality unless this device
* is used in a cascade configuration, and set the switch's
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 6c8554c..a848aef 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -61,21 +61,6 @@ static const char *mv88e6171_drv_probe(struct device *dsa_dev,
static int mv88e6171_setup_global(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u32 upstream_port = dsa_upstream_port(ds);
- int ret;
- u32 reg;
-
- /* Configure the upstream port, and configure the upstream
- * port as the port to which ingress and egress monitor frames
- * are to be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT;
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
- if (ret)
- return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index a27616c..e098870 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -80,20 +80,6 @@ static const char *mv88e6352_drv_probe(struct device *dsa_dev,
static int mv88e6352_setup_global(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- u32 upstream_port = dsa_upstream_port(ds);
- int ret;
- u32 reg;
-
- /* Configure the upstream port, and configure the upstream
- * port as the port to which ingress and egress monitor frames
- * are to be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
- if (ret)
- return ret;
/* Disable remote management for now, and set the switch's
* DSA device number.
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index b0245e7..2d89829 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2914,6 +2914,8 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
static int _mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
{
+ struct dsa_switch *ds = ps->ds;
+ u32 upstream_port = dsa_upstream_port(ds);
u16 reg;
int err;
int i;
@@ -2938,6 +2940,16 @@ static int _mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
return err;
}
+ /* Configure the upstream port, and configure it as the port to which
+ * ingress and egress and ARP monitor frames are to be sent.
+ */
+ reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+ upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
+ upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
+ err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+ if (err)
+ return err;
+
/* Set the default address aging time to 5 minutes, and
* enable address learn messages to be sent to all message
* ports.
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 15/21] net: dsa: mv88e6xxx: factorize VLAN Ethertype
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
The 6131 switch models have a Core Tag Type register. Add a
MV88E6XXX_FLAG_CORE_TAG_TYPE flag and set the VLAN Ethertype to 0x8100
in the shared setup code if it is present.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6131.c | 5 -----
drivers/net/dsa/mv88e6xxx.c | 8 ++++++++
drivers/net/dsa/mv88e6xxx.h | 10 ++++++++++
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index d05fc79..1c3b245 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -65,11 +65,6 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- /* Set the VLAN ethertype to 0x8100. */
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
- if (ret)
- return ret;
-
/* Disable ARP mirroring, and configure the upstream port as
* the port to which ingress and egress monitor frames are to
* be sent.
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 1572719..b0245e7 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2930,6 +2930,14 @@ static int _mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
if (err)
return err;
+ /* Set the VLAN ethertype to 0x8100. */
+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_CORE_TAG_TYPE)) {
+ err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE,
+ 0x8100);
+ if (err)
+ return err;
+ }
+
/* Set the default address aging time to 5 minutes, and
* enable address learn messages to be sent to all message
* ports.
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 62f6fc9..555903f 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -365,6 +365,12 @@ enum mv88e6xxx_cap {
*/
MV88E6XXX_CAP_EEPROM,
+ /* Core Tag Type.
+ * Used with Double Tagged frames and ports in UseCoreTag mode.
+ * See GLOBAL_CORE_TAG_TYPE.
+ */
+ MV88E6XXX_CAP_CORE_TAG_TYPE,
+
/* Port State Filtering for 802.1D Spanning Tree.
* See PORT_CONTROL_STATE_* values in the PORT_CONTROL register.
*/
@@ -411,6 +417,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_ATU BIT(MV88E6XXX_CAP_ATU)
#define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE)
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
+#define MV88E6XXX_FLAG_CORE_TAG_TYPE BIT(MV88E6XXX_CAP_CORE_TAG_TYPE)
#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_PPU_ACTIVE BIT(MV88E6XXX_CAP_PPU_ACTIVE)
@@ -423,12 +430,14 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6095 \
(MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_CORE_TAG_TYPE | \
MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VLANTABLE | \
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6097 \
(MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_CORE_TAG_TYPE | \
MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VLANTABLE | \
MV88E6XXX_FLAG_VTU)
@@ -439,6 +448,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6185 \
(MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_CORE_TAG_TYPE | \
MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VLANTABLE | \
MV88E6XXX_FLAG_VTU)
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 14/21] net: dsa: mv88e6xxx: factorize GLOBAL_CONTROL setup
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
All switch models configure the GLOBAL_CONTROL register with slightly
differences.
Discarding packets with excessive collisions
(GLOBAL_CONTROL_DISCARD_EXCESS) is specific to 6352 and similar
switches, and setting a maximum frame size
(GLOBAL_CONTROL_MAX_FRAME_1632) is specific to 6185 and similar
switches.
As we are centralizing the chips setup, skip these settings and don't
discard any frames yet, until we found out that such discarding by the
hardware is necessary.
Assume a common setup to enable the PHY Polling Unit if present, don't
discard any packets, and mask all interrupt sources.
Tested on 88E6352 and 88E6185.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 8 --------
drivers/net/dsa/mv88e6131.c | 11 -----------
drivers/net/dsa/mv88e6171.c | 9 ---------
drivers/net/dsa/mv88e6352.c | 9 ---------
drivers/net/dsa/mv88e6xxx.c | 13 +++++++++++++
5 files changed, 13 insertions(+), 37 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index d74695a..1cd30ac 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -58,14 +58,6 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- /* Disable the PHY polling unit (since there won't be any
- * external PHYs to poll), don't discard packets with
- * excessive collisions, and mask all interrupt sources.
- */
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
- if (ret)
- return ret;
-
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
* are to be sent.
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index e22ca7b..d05fc79 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -65,17 +65,6 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- /* Enable the PHY polling unit, don't discard packets with
- * excessive collisions, use a weighted fair queueing scheme
- * to arbitrate between packet queues, set the maximum frame
- * size to 1632, and mask all interrupt sources.
- */
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
- GLOBAL_CONTROL_PPU_ENABLE |
- GLOBAL_CONTROL_MAX_FRAME_1632);
- if (ret)
- return ret;
-
/* Set the VLAN ethertype to 0x8100. */
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
if (ret)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 4bbf2e1..6c8554c 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -65,15 +65,6 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- /* Discard packets with excessive collisions, mask all
- * interrupt sources, enable PPU.
- */
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
- GLOBAL_CONTROL_PPU_ENABLE |
- GLOBAL_CONTROL_DISCARD_EXCESS);
- if (ret)
- return ret;
-
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
* are to be sent.
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 3e0be87..a27616c 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -84,15 +84,6 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- /* Discard packets with excessive collisions,
- * mask all interrupt sources, enable PPU (bit 14, undocumented).
- */
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
- GLOBAL_CONTROL_PPU_ENABLE |
- GLOBAL_CONTROL_DISCARD_EXCESS);
- if (ret)
- return ret;
-
/* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames
* are to be sent.
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 92f4b00..1572719 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2914,9 +2914,22 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
static int _mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
{
+ u16 reg;
int err;
int i;
+ /* Enable the PHY Polling Unit if present, don't discard any packets,
+ * and mask all interrupt sources.
+ */
+ reg = 0;
+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU) ||
+ mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE))
+ reg |= GLOBAL_CONTROL_PPU_ENABLE;
+
+ err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, reg);
+ if (err)
+ return err;
+
/* Set the default address aging time to 5 minutes, and
* enable address learn messages to be sent to all message
* ports.
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 13/21] net: dsa: mv88e6xxx: factorize global setup
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Every driver is calling mv88e6xxx_setup_global after
mv88e6xxx_setup_common. Call the former in the latter.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 4 --
drivers/net/dsa/mv88e6131.c | 4 --
drivers/net/dsa/mv88e6171.c | 4 --
drivers/net/dsa/mv88e6352.c | 4 --
drivers/net/dsa/mv88e6xxx.c | 109 +++++++++++++++++++++++---------------------
drivers/net/dsa/mv88e6xxx.h | 1 -
6 files changed, 56 insertions(+), 70 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index fadec7a..d74695a 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -58,10 +58,6 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- ret = mv88e6xxx_setup_global(ds);
- if (ret)
- return ret;
-
/* Disable the PHY polling unit (since there won't be any
* external PHYs to poll), don't discard packets with
* excessive collisions, and mask all interrupt sources.
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 25ed823..e22ca7b 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -65,10 +65,6 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- ret = mv88e6xxx_setup_global(ds);
- if (ret)
- return ret;
-
/* Enable the PHY polling unit, don't discard packets with
* excessive collisions, use a weighted fair queueing scheme
* to arbitrate between packet queues, set the maximum frame
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index caaa4b6..4bbf2e1 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -65,10 +65,6 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- ret = mv88e6xxx_setup_global(ds);
- if (ret)
- return ret;
-
/* Discard packets with excessive collisions, mask all
* interrupt sources, enable PPU.
*/
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 470789a..3e0be87 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -84,10 +84,6 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
int ret;
u32 reg;
- ret = mv88e6xxx_setup_global(ds);
- if (ret)
- return ret;
-
/* Discard packets with excessive collisions,
* mask all interrupt sources, enable PPU (bit 14, undocumented).
*/
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index b744ed5..92f4b00 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2912,36 +2912,11 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
return 0;
}
-int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
+static int _mv88e6xxx_setup_global(struct mv88e6xxx_priv_state *ps)
{
int err;
-
- mutex_init(&ps->smi_mutex);
-
- INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
- mutex_init(&ps->eeprom_mutex);
-
- if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
- mv88e6xxx_ppu_state_init(ps);
-
- mutex_lock(&ps->smi_mutex);
-
- err = _mv88e6xxx_switch_reset(ps);
-
- mutex_unlock(&ps->smi_mutex);
-
- return err;
-}
-
-int mv88e6xxx_setup_global(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int err;
int i;
- mutex_lock(&ps->smi_mutex);
/* Set the default address aging time to 5 minutes, and
* enable address learn messages to be sent to all message
* ports.
@@ -2949,45 +2924,45 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL,
0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
if (err)
- goto unlock;
+ return err;
/* Configure the IP ToS mapping registers. */
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
if (err)
- goto unlock;
+ return err;
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
if (err)
- goto unlock;
+ return err;
/* Configure the IEEE 802.1p priority mapping register. */
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
if (err)
- goto unlock;
+ return err;
/* Send all frames with destination addresses matching
* 01:80:c2:00:00:0x to the CPU port.
*/
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
if (err)
- goto unlock;
+ return err;
/* Ignore removed tag data on doubly tagged packets, disable
* flow control messages, force flow control priority to the
@@ -2998,15 +2973,15 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
if (err)
- goto unlock;
+ return err;
/* Program the DSA routing table. */
for (i = 0; i < 32; i++) {
int nexthop = 0x1f;
- if (ds->pd->rtable &&
- i != ds->index && i < ds->dst->pd->nr_chips)
- nexthop = ds->pd->rtable[i] & 0x1f;
+ if (ps->ds->pd->rtable &&
+ i != ps->ds->index && i < ps->ds->dst->pd->nr_chips)
+ nexthop = ps->ds->pd->rtable[i] & 0x1f;
err = _mv88e6xxx_reg_write(
ps, REG_GLOBAL2,
@@ -3014,7 +2989,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
GLOBAL2_DEVICE_MAPPING_UPDATE |
(i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop);
if (err)
- goto unlock;
+ return err;
}
/* Clear all trunk masks. */
@@ -3024,7 +2999,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
(i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
((1 << ps->info->num_ports) - 1));
if (err)
- goto unlock;
+ return err;
}
/* Clear all trunk mappings. */
@@ -3035,7 +3010,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
GLOBAL2_TRUNK_MAPPING_UPDATE |
(i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
if (err)
- goto unlock;
+ return err;
}
if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
@@ -3047,7 +3022,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
GLOBAL2_MGMT_EN_2X, 0xffff);
if (err)
- goto unlock;
+ return err;
/* Initialise cross-chip port VLAN table to reset
* defaults.
@@ -3055,7 +3030,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2,
GLOBAL2_PVT_ADDR, 0x9000);
if (err)
- goto unlock;
+ return err;
/* Clear the priority override table. */
for (i = 0; i < 16; i++) {
@@ -3063,7 +3038,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
GLOBAL2_PRIO_OVERRIDE,
0x8000 | (i << 8));
if (err)
- goto unlock;
+ return err;
}
}
@@ -3080,7 +3055,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
GLOBAL2_INGRESS_OP,
0x9000 | (i << 8));
if (err)
- goto unlock;
+ return err;
}
}
@@ -3088,20 +3063,48 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP,
GLOBAL_STATS_OP_FLUSH_ALL);
if (err)
- goto unlock;
+ return err;
/* Wait for the flush to complete. */
err = _mv88e6xxx_stats_wait(ps);
- if (err < 0)
- goto unlock;
+ if (err)
+ return err;
/* Clear all ATU entries */
err = _mv88e6xxx_atu_flush(ps, 0, true);
- if (err < 0)
- goto unlock;
+ if (err)
+ return err;
/* Clear all the VTU and STU entries */
err = _mv88e6xxx_vtu_stu_flush(ps);
+ if (err < 0)
+ return err;
+
+ return err;
+}
+
+int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
+{
+ int err;
+
+ mutex_init(&ps->smi_mutex);
+
+ INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
+
+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
+ mutex_init(&ps->eeprom_mutex);
+
+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
+ mv88e6xxx_ppu_state_init(ps);
+
+ mutex_lock(&ps->smi_mutex);
+
+ err = _mv88e6xxx_switch_reset(ps);
+ if (err)
+ goto unlock;
+
+ err = _mv88e6xxx_setup_global(ps);
+
unlock:
mutex_unlock(&ps->smi_mutex);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index efd6ebd..62f6fc9 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -590,7 +590,6 @@ const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps);
-int mv88e6xxx_setup_global(struct dsa_switch *ds);
int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
int reg, u16 val);
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 12/21] net: dsa: mv88e6xxx: factorize switch reset
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add a MV88E6XXX_FLAG_PPU_ACTIVE flag to describe how to reset the
switch, and merge the reset call to the common setup code.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 4 --
drivers/net/dsa/mv88e6131.c | 4 --
drivers/net/dsa/mv88e6171.c | 4 --
drivers/net/dsa/mv88e6352.c | 4 --
drivers/net/dsa/mv88e6xxx.c | 137 +++++++++++++++++++++++---------------------
drivers/net/dsa/mv88e6xxx.h | 6 +-
6 files changed, 76 insertions(+), 83 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 45cce4f..fadec7a 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -99,10 +99,6 @@ static int mv88e6123_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ret = mv88e6xxx_switch_reset(ps, false);
- if (ret < 0)
- return ret;
-
ret = mv88e6123_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 5d25244..25ed823 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -132,10 +132,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ret = mv88e6xxx_switch_reset(ps, false);
- if (ret < 0)
- return ret;
-
ret = mv88e6131_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index a98e7d3..caaa4b6 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -108,10 +108,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ret = mv88e6xxx_switch_reset(ps, true);
- if (ret < 0)
- return ret;
-
ret = mv88e6171_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index d03c14a..470789a 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -125,10 +125,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- ret = mv88e6xxx_switch_reset(ps, true);
- if (ret < 0)
- return ret;
-
ret = mv88e6352_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index dbbda4e..b744ed5 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2551,6 +2551,68 @@ restore_page_0:
return ret;
}
+static int _mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps)
+{
+ bool ppu_active = mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE);
+ u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
+ struct gpio_desc *gpiod = ps->ds->pd->reset;
+ unsigned long timeout;
+ int ret;
+ int i;
+
+ /* Set all ports to the disabled state. */
+ for (i = 0; i < ps->info->num_ports; i++) {
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
+ ret & 0xfffc);
+ if (ret)
+ return ret;
+ }
+
+ /* Wait for transmit queues to drain. */
+ usleep_range(2000, 4000);
+
+ /* If there is a gpio connected to the reset pin, toggle it */
+ if (gpiod) {
+ gpiod_set_value_cansleep(gpiod, 1);
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(gpiod, 0);
+ usleep_range(10000, 20000);
+ }
+
+ /* Reset the switch. Keep the PPU active if requested. The PPU
+ * needs to be active to support indirect phy register access
+ * through global registers 0x18 and 0x19.
+ */
+ if (ppu_active)
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
+ else
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
+ if (ret)
+ return ret;
+
+ /* Wait up to one second for reset to complete. */
+ timeout = jiffies + 1 * HZ;
+ while (time_before(jiffies, timeout)) {
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if ((ret & is_reset) == is_reset)
+ break;
+ usleep_range(1000, 2000);
+ }
+ if (time_after(jiffies, timeout))
+ ret = -ETIMEDOUT;
+ else
+ ret = 0;
+
+ return ret;
+}
+
static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
{
int ret;
@@ -2852,6 +2914,8 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
{
+ int err;
+
mutex_init(&ps->smi_mutex);
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
@@ -2862,7 +2926,13 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
mv88e6xxx_ppu_state_init(ps);
- return 0;
+ mutex_lock(&ps->smi_mutex);
+
+ err = _mv88e6xxx_switch_reset(ps);
+
+ mutex_unlock(&ps->smi_mutex);
+
+ return err;
}
int mv88e6xxx_setup_global(struct dsa_switch *ds)
@@ -3038,71 +3108,6 @@ unlock:
return err;
}
-int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active)
-{
- u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
- struct gpio_desc *gpiod = ps->ds->pd->reset;
- unsigned long timeout;
- int ret;
- int i;
-
- mutex_lock(&ps->smi_mutex);
-
- /* Set all ports to the disabled state. */
- for (i = 0; i < ps->info->num_ports; i++) {
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
- if (ret < 0)
- goto unlock;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
- ret & 0xfffc);
- if (ret)
- goto unlock;
- }
-
- /* Wait for transmit queues to drain. */
- usleep_range(2000, 4000);
-
- /* If there is a gpio connected to the reset pin, toggle it */
- if (gpiod) {
- gpiod_set_value_cansleep(gpiod, 1);
- usleep_range(10000, 20000);
- gpiod_set_value_cansleep(gpiod, 0);
- usleep_range(10000, 20000);
- }
-
- /* Reset the switch. Keep the PPU active if requested. The PPU
- * needs to be active to support indirect phy register access
- * through global registers 0x18 and 0x19.
- */
- if (ppu_active)
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
- else
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
- if (ret)
- goto unlock;
-
- /* Wait up to one second for reset to complete. */
- timeout = jiffies + 1 * HZ;
- while (time_before(jiffies, timeout)) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
- if (ret < 0)
- goto unlock;
-
- if ((ret & is_reset) == is_reset)
- break;
- usleep_range(1000, 2000);
- }
- if (time_after(jiffies, timeout))
- ret = -ETIMEDOUT;
- else
- ret = 0;
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 192292f..efd6ebd 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -374,6 +374,7 @@ enum mv88e6xxx_cap {
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/
MV88E6XXX_CAP_PPU,
+ MV88E6XXX_CAP_PPU_ACTIVE,
/* SMI PHY Command and Data registers.
* This requires an indirect access to PHY registers through
@@ -412,6 +413,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
+#define MV88E6XXX_FLAG_PPU_ACTIVE BIT(MV88E6XXX_CAP_PPU_ACTIVE)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
#define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
@@ -446,6 +448,7 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_PORTSTATE | \
+ MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
@@ -456,6 +459,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6351 \
(MV88E6XXX_FLAG_ATU | \
MV88E6XXX_FLAG_PORTSTATE | \
+ MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
@@ -467,6 +471,7 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_PORTSTATE | \
+ MV88E6XXX_FLAG_PPU_ACTIVE | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
@@ -578,7 +583,6 @@ static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
return (ps->info->flags & flags) == flags;
}
-int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active);
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv,
const struct mv88e6xxx_info *table,
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 11/21] net: dsa: mv88e6xxx: factorize ATU access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add a MV88E6XXX_FLAG_ATU flag to identify switch models with an Address
Translation Unit.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 4 ++++
drivers/net/dsa/mv88e6xxx.c | 14 ++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 24 ++++++++++++++++++------
3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index da5aa9c..45cce4f 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -141,6 +141,10 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.port_vlan_add = mv88e6xxx_port_vlan_add,
.port_vlan_del = mv88e6xxx_port_vlan_del,
.port_vlan_dump = mv88e6xxx_port_vlan_dump,
+ .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
+ .port_fdb_add = mv88e6xxx_port_fdb_add,
+ .port_fdb_del = mv88e6xxx_port_fdb_del,
+ .port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
MODULE_ALIAS("platform:mv88e6123");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 7994486..dbbda4e 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2267,6 +2267,11 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb,
struct switchdev_trans *trans)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
+ return -EOPNOTSUPP;
+
/* We don't need any dynamic resource from the kernel (yet),
* so skip the prepare phase.
*/
@@ -2282,6 +2287,9 @@ void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
GLOBAL_ATU_DATA_STATE_UC_STATIC;
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
+ return;
+
mutex_lock(&ps->smi_mutex);
if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))
netdev_err(ds->ports[port], "failed to load MAC address\n");
@@ -2294,6 +2302,9 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,
GLOBAL_ATU_DATA_STATE_UNUSED);
@@ -2399,6 +2410,9 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
u16 fid;
int err;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
/* Dump port's default Filtering Information Database (VLAN ID 0) */
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 4f21206..192292f 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -351,6 +351,11 @@ enum mv88e6xxx_family {
};
enum mv88e6xxx_cap {
+ /* Address Translation Unit.
+ * The ATU is used to lookup and learn MAC addresses. See GLOBAL_ATU_OP.
+ */
+ MV88E6XXX_CAP_ATU,
+
/* Energy Efficient Ethernet.
*/
MV88E6XXX_CAP_EEE,
@@ -402,6 +407,7 @@ enum mv88e6xxx_cap {
};
/* Bitmask of capabilities */
+#define MV88E6XXX_FLAG_ATU BIT(MV88E6XXX_CAP_ATU)
#define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE)
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
@@ -414,12 +420,14 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_VTU BIT(MV88E6XXX_CAP_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6095 \
- (MV88E6XXX_FLAG_PPU | \
+ (MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VLANTABLE | \
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6097 \
- (MV88E6XXX_FLAG_PPU | \
+ (MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VLANTABLE | \
MV88E6XXX_FLAG_VTU)
@@ -428,12 +436,14 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_TEMP)
#define MV88E6XXX_FLAGS_FAMILY_6185 \
- (MV88E6XXX_FLAG_PPU | \
+ (MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_PPU | \
MV88E6XXX_FLAG_VLANTABLE | \
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6320 \
- (MV88E6XXX_FLAG_EEE | \
+ (MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_PORTSTATE | \
MV88E6XXX_FLAG_SMI_PHY | \
@@ -444,7 +454,8 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
- (MV88E6XXX_FLAG_PORTSTATE | \
+ (MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_PORTSTATE | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
@@ -452,7 +463,8 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
- (MV88E6XXX_FLAG_EEE | \
+ (MV88E6XXX_FLAG_ATU | \
+ MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_PORTSTATE | \
MV88E6XXX_FLAG_SMI_PHY | \
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 10/21] net: dsa: mv88e6xxx: factorize VTU access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add a MV88E6XXX_FLAG_VTU flag to indentify switch models with a VLAN
Table Unit.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 5 +++++
drivers/net/dsa/mv88e6xxx.c | 16 ++++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 24 ++++++++++++++++++------
3 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 81cd4a9..da5aa9c 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -136,6 +136,11 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.port_bridge_join = mv88e6xxx_port_bridge_join,
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
.port_stp_state_set = mv88e6xxx_port_stp_state_set,
+ .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
+ .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
+ .port_vlan_add = mv88e6xxx_port_vlan_add,
+ .port_vlan_del = mv88e6xxx_port_vlan_del,
+ .port_vlan_dump = mv88e6xxx_port_vlan_dump,
};
MODULE_ALIAS("platform:mv88e6123");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 492cb24..7994486 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1588,6 +1588,9 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
u16 pvid;
int err;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
@@ -2011,6 +2014,9 @@ int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
PORT_CONTROL_2_8021Q_DISABLED;
int ret;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);
@@ -2044,8 +2050,12 @@ int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans)
{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int err;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
+ return -EOPNOTSUPP;
+
/* If the requested port doesn't belong to the same bridge as the VLAN
* members, do not support it (yet) and fallback to software VLAN.
*/
@@ -2086,6 +2096,9 @@ void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
u16 vid;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
+ return;
+
mutex_lock(&ps->smi_mutex);
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
@@ -2143,6 +2156,9 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
u16 pvid, vid;
int err = 0;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index d15e0b3..4f21206 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -394,6 +394,11 @@ enum mv88e6xxx_cap {
* the output (or egress) ports to which it is allowed to send frames.
*/
MV88E6XXX_CAP_VLANTABLE,
+
+ /* VLAN Table Unit.
+ * The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP.
+ */
+ MV88E6XXX_CAP_VTU,
};
/* Bitmask of capabilities */
@@ -406,14 +411,17 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
#define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT)
#define MV88E6XXX_FLAG_VLANTABLE BIT(MV88E6XXX_CAP_VLANTABLE)
+#define MV88E6XXX_FLAG_VTU BIT(MV88E6XXX_CAP_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6095 \
(MV88E6XXX_FLAG_PPU | \
- MV88E6XXX_FLAG_VLANTABLE)
+ MV88E6XXX_FLAG_VLANTABLE | \
+ MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6097 \
(MV88E6XXX_FLAG_PPU | \
- MV88E6XXX_FLAG_VLANTABLE)
+ MV88E6XXX_FLAG_VLANTABLE | \
+ MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6165 \
(MV88E6XXX_FLAG_SWITCH_MAC | \
@@ -421,7 +429,8 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6185 \
(MV88E6XXX_FLAG_PPU | \
- MV88E6XXX_FLAG_VLANTABLE)
+ MV88E6XXX_FLAG_VLANTABLE | \
+ MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6320 \
(MV88E6XXX_FLAG_EEE | \
@@ -431,14 +440,16 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \
- MV88E6XXX_FLAG_VLANTABLE)
+ MV88E6XXX_FLAG_VLANTABLE | \
+ MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
(MV88E6XXX_FLAG_PORTSTATE | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_VLANTABLE)
+ MV88E6XXX_FLAG_VLANTABLE | \
+ MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
(MV88E6XXX_FLAG_EEE | \
@@ -448,7 +459,8 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT | \
- MV88E6XXX_FLAG_VLANTABLE)
+ MV88E6XXX_FLAG_VLANTABLE | \
+ MV88E6XXX_FLAG_VTU)
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 09/21] net: dsa: mv88e6xxx: factorize bridge support
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add MV88E6XXX_FLAG_PORTSTATE and MV88E6XXX_FLAG_VLANTABLE flags to
identify switch models with required 802.1D operations.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 3 +++
drivers/net/dsa/mv88e6131.c | 1 +
drivers/net/dsa/mv88e6xxx.c | 9 +++++++++
drivers/net/dsa/mv88e6xxx.h | 38 ++++++++++++++++++++++++++++++--------
4 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 1ad7bcd..81cd4a9 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -133,6 +133,9 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.set_eeprom = mv88e6xxx_set_eeprom,
.get_regs_len = mv88e6xxx_get_regs_len,
.get_regs = mv88e6xxx_get_regs,
+ .port_bridge_join = mv88e6xxx_port_bridge_join,
+ .port_bridge_leave = mv88e6xxx_port_bridge_leave,
+ .port_stp_state_set = mv88e6xxx_port_stp_state_set,
};
MODULE_ALIAS("platform:mv88e6123");
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 3fb06af..5d25244 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -168,6 +168,7 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.adjust_link = mv88e6xxx_adjust_link,
.port_bridge_join = mv88e6xxx_port_bridge_join,
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
+ .port_stp_state_set = mv88e6xxx_port_stp_state_set,
.port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
.port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
.port_vlan_add = mv88e6xxx_port_vlan_add,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 7a4ab4b..492cb24 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1361,6 +1361,9 @@ void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int stp_state;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_PORTSTATE))
+ return;
+
switch (state) {
case BR_STATE_DISABLED:
stp_state = PORT_CONTROL_STATE_DISABLED;
@@ -2422,6 +2425,9 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int i, err = 0;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
/* Assign the bridge and remap each port's VLANTable */
@@ -2446,6 +2452,9 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
struct net_device *bridge = ps->ports[port].bridge_dev;
int i;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
+ return;
+
mutex_lock(&ps->smi_mutex);
/* Unassign the bridge and remap each port's VLANTable */
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index b99e090..d15e0b3 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -360,6 +360,11 @@ enum mv88e6xxx_cap {
*/
MV88E6XXX_CAP_EEPROM,
+ /* Port State Filtering for 802.1D Spanning Tree.
+ * See PORT_CONTROL_STATE_* values in the PORT_CONTROL register.
+ */
+ MV88E6XXX_CAP_PORTSTATE,
+
/* PHY Polling Unit.
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/
@@ -383,50 +388,67 @@ enum mv88e6xxx_cap {
*/
MV88E6XXX_CAP_TEMP,
MV88E6XXX_CAP_TEMP_LIMIT,
+
+ /* In-chip Port Based VLANs.
+ * Each port VLANTable register (see PORT_BASE_VLAN) is used to restrict
+ * the output (or egress) ports to which it is allowed to send frames.
+ */
+ MV88E6XXX_CAP_VLANTABLE,
};
/* Bitmask of capabilities */
#define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE)
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
+#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
#define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
#define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT)
+#define MV88E6XXX_FLAG_VLANTABLE BIT(MV88E6XXX_CAP_VLANTABLE)
#define MV88E6XXX_FLAGS_FAMILY_6095 \
- MV88E6XXX_FLAG_PPU
+ (MV88E6XXX_FLAG_PPU | \
+ MV88E6XXX_FLAG_VLANTABLE)
#define MV88E6XXX_FLAGS_FAMILY_6097 \
- MV88E6XXX_FLAG_PPU
+ (MV88E6XXX_FLAG_PPU | \
+ MV88E6XXX_FLAG_VLANTABLE)
#define MV88E6XXX_FLAGS_FAMILY_6165 \
(MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP)
#define MV88E6XXX_FLAGS_FAMILY_6185 \
- MV88E6XXX_FLAG_PPU
+ (MV88E6XXX_FLAG_PPU | \
+ MV88E6XXX_FLAG_VLANTABLE)
#define MV88E6XXX_FLAGS_FAMILY_6320 \
(MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_EEPROM | \
+ MV88E6XXX_FLAG_PORTSTATE | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT)
+ MV88E6XXX_FLAG_TEMP_LIMIT | \
+ MV88E6XXX_FLAG_VLANTABLE)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
- (MV88E6XXX_FLAG_SMI_PHY | \
+ (MV88E6XXX_FLAG_PORTSTATE | \
+ MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
- MV88E6XXX_FLAG_TEMP)
+ MV88E6XXX_FLAG_TEMP | \
+ MV88E6XXX_FLAG_VLANTABLE)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
(MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_EEPROM | \
- MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_PORTSTATE | \
+ MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT)
+ MV88E6XXX_FLAG_TEMP_LIMIT | \
+ MV88E6XXX_FLAG_VLANTABLE)
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 08/21] net: dsa: mv88e6xxx: factorize registers access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Only 6131 was not supporting the port registers access yet. Assume such
support and use the unlock access routines in the meantime.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6131.c | 2 ++
drivers/net/dsa/mv88e6xxx.c | 6 +++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 432d3c4..3fb06af 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -157,6 +157,8 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.get_sset_count = mv88e6xxx_get_sset_count,
.get_eeprom = mv88e6xxx_get_eeprom,
.set_eeprom = mv88e6xxx_set_eeprom,
+ .get_regs_len = mv88e6xxx_get_regs_len,
+ .get_regs = mv88e6xxx_get_regs,
#ifdef CONFIG_NET_DSA_HWMON
.get_temp = mv88e6xxx_get_temp,
.get_temp_limit = mv88e6xxx_get_temp_limit,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index f76cdc9..7a4ab4b 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -787,13 +787,17 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
memset(p, 0xff, 32 * sizeof(u16));
+ mutex_lock(&ps->smi_mutex);
+
for (i = 0; i < 32; i++) {
int ret;
- ret = mv88e6xxx_reg_read(ps, REG_PORT(port), i);
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), i);
if (ret >= 0)
p[i] = ret;
}
+
+ mutex_unlock(&ps->smi_mutex);
}
static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset,
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 07/21] net: dsa: mv88e6xxx: factorize EEE access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add a MV88E6XXX_FLAG_EEE flag to describe switch models featuring Energy
Efficient Ethernet. Use it to conditionally support such access in the
common code.
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/mv88e6xxx.c | 6 ++++++
drivers/net/dsa/mv88e6xxx.h | 11 +++++++++--
5 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index c349fb7..1ad7bcd 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -117,6 +117,8 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
+ .set_eee = mv88e6xxx_set_eee,
+ .get_eee = mv88e6xxx_get_eee,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 1e040c6..432d3c4 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -150,6 +150,8 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
+ .set_eee = mv88e6xxx_set_eee,
+ .get_eee = mv88e6xxx_get_eee,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index f9b20e0..a98e7d3 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -126,6 +126,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
+ .set_eee = mv88e6xxx_set_eee,
+ .get_eee = mv88e6xxx_get_eee,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 10cc277..f76cdc9 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1097,6 +1097,9 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int reg;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
reg = _mv88e6xxx_phy_read_indirect(ps, port, 16);
@@ -1125,6 +1128,9 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
int reg;
int ret;
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
+ return -EOPNOTSUPP;
+
mutex_lock(&ps->smi_mutex);
ret = _mv88e6xxx_phy_read_indirect(ps, port, 16);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 517e95f..b99e090 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -351,6 +351,10 @@ enum mv88e6xxx_family {
};
enum mv88e6xxx_cap {
+ /* Energy Efficient Ethernet.
+ */
+ MV88E6XXX_CAP_EEE,
+
/* EEPROM Command and Data registers.
* See GLOBAL2_EEPROM_OP and GLOBAL2_EEPROM_DATA.
*/
@@ -382,6 +386,7 @@ enum mv88e6xxx_cap {
};
/* Bitmask of capabilities */
+#define MV88E6XXX_FLAG_EEE BIT(MV88E6XXX_CAP_EEE)
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
@@ -403,7 +408,8 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_PPU
#define MV88E6XXX_FLAGS_FAMILY_6320 \
- (MV88E6XXX_FLAG_EEPROM | \
+ (MV88E6XXX_FLAG_EEE | \
+ MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
@@ -415,7 +421,8 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_TEMP)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
- (MV88E6XXX_FLAG_EEPROM | \
+ (MV88E6XXX_FLAG_EEE | \
+ MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_SMI_PHY | \
MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 06/21] net: dsa: mv88e6xxx: factorize MAC address setting
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Some switch models have a dedicated register for Switch MAC/WoF/WoL.
This register, when present, is used to indirectly set the switch MAC
address, instead of a direct write to 3 global registers.
Identify this feature and share a common mv88e6xxx_set_addr function.
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 +-
drivers/net/dsa/mv88e6xxx.c | 14 ++++++++++++--
drivers/net/dsa/mv88e6xxx.h | 17 ++++++++++++++---
6 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index e234bdb..c349fb7 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -114,7 +114,7 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6123_drv_probe,
.setup = mv88e6123_setup,
- .set_addr = mv88e6xxx_set_addr_indirect,
+ .set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 089f9c0..1e040c6 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -147,7 +147,7 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA,
.probe = mv88e6131_drv_probe,
.setup = mv88e6131_setup,
- .set_addr = mv88e6xxx_set_addr_direct,
+ .set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 588b486..f9b20e0 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -123,7 +123,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6171_drv_probe,
.setup = mv88e6171_setup,
- .set_addr = mv88e6xxx_set_addr_indirect,
+ .set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 3bb271e..d03c14a 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -140,7 +140,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6352_drv_probe,
.setup = mv88e6352_setup,
- .set_addr = mv88e6xxx_set_addr_indirect,
+ .set_addr = mv88e6xxx_set_addr,
.phy_read = mv88e6xxx_phy_read,
.phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index c010bb9..10cc277 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -173,7 +173,7 @@ int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
return ret;
}
-int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
+static int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int err;
@@ -192,7 +192,7 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
(addr[4] << 8) | addr[5]);
}
-int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
+static int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
@@ -225,6 +225,16 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
return 0;
}
+int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SWITCH_MAC))
+ return mv88e6xxx_set_addr_indirect(ds, addr);
+ else
+ return mv88e6xxx_set_addr_direct(ds, addr);
+}
+
static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr,
int regnum)
{
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 9ddb6d0..517e95f 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -367,6 +367,13 @@ enum mv88e6xxx_cap {
*/
MV88E6XXX_CAP_SMI_PHY,
+ /* Switch MAC/WoL/WoF register.
+ * This requires an indirect access to set the switch MAC address
+ * through GLOBAL2_SWITCH_MAC, otherwise GLOBAL_MAC_01, GLOBAL_MAC_23,
+ * and GLOBAL_MAC_45 are used with a direct access.
+ */
+ MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF,
+
/* Internal temperature sensor.
* Available from any enabled port's PHY register 26, page 6.
*/
@@ -378,6 +385,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
+#define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
#define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT)
@@ -388,7 +396,8 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_PPU
#define MV88E6XXX_FLAGS_FAMILY_6165 \
- MV88E6XXX_FLAG_TEMP
+ (MV88E6XXX_FLAG_SWITCH_MAC | \
+ MV88E6XXX_FLAG_TEMP)
#define MV88E6XXX_FLAGS_FAMILY_6185 \
MV88E6XXX_FLAG_PPU
@@ -396,16 +405,19 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6320 \
(MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
(MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
(MV88E6XXX_FLAG_EEPROM | \
MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_SWITCH_MAC | \
MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_TEMP_LIMIT)
@@ -525,8 +537,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds);
int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg);
int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
int reg, u16 val);
-int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
-int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
+int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 05/21] net: dsa: mv88e6xxx: factorize temperature access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add MV88E6XXX_FLAG_TEMP and MV88E6XXX_FLAG_TEMP_LIMIT flags to describe
switch models featuring a temperature access. Use them to centralize the
access to the temperature feature.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 3 +++
drivers/net/dsa/mv88e6131.c | 6 ++++++
drivers/net/dsa/mv88e6171.c | 3 +++
drivers/net/dsa/mv88e6xxx.c | 9 ++++++---
drivers/net/dsa/mv88e6xxx.h | 22 ++++++++++++++++++----
5 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 8330a8e..e234bdb 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -123,6 +123,9 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.adjust_link = mv88e6xxx_adjust_link,
#ifdef CONFIG_NET_DSA_HWMON
.get_temp = mv88e6xxx_get_temp,
+ .get_temp_limit = mv88e6xxx_get_temp_limit,
+ .set_temp_limit = mv88e6xxx_set_temp_limit,
+ .get_temp_alarm = mv88e6xxx_get_temp_alarm,
#endif
.get_eeprom = mv88e6xxx_get_eeprom,
.set_eeprom = mv88e6xxx_set_eeprom,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index ab8c507..089f9c0 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -155,6 +155,12 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.get_sset_count = mv88e6xxx_get_sset_count,
.get_eeprom = mv88e6xxx_get_eeprom,
.set_eeprom = mv88e6xxx_set_eeprom,
+#ifdef CONFIG_NET_DSA_HWMON
+ .get_temp = mv88e6xxx_get_temp,
+ .get_temp_limit = mv88e6xxx_get_temp_limit,
+ .set_temp_limit = mv88e6xxx_set_temp_limit,
+ .get_temp_alarm = mv88e6xxx_get_temp_alarm,
+#endif
.adjust_link = mv88e6xxx_adjust_link,
.port_bridge_join = mv88e6xxx_port_bridge_join,
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index a7afbaa..588b486 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -132,6 +132,9 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.adjust_link = mv88e6xxx_adjust_link,
#ifdef CONFIG_NET_DSA_HWMON
.get_temp = mv88e6xxx_get_temp,
+ .get_temp_limit = mv88e6xxx_get_temp_limit,
+ .set_temp_limit = mv88e6xxx_set_temp_limit,
+ .get_temp_alarm = mv88e6xxx_get_temp_alarm,
#endif
.get_eeprom = mv88e6xxx_get_eeprom,
.set_eeprom = mv88e6xxx_set_eeprom,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 921fe87..c010bb9 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3191,6 +3191,9 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP))
+ return -EOPNOTSUPP;
+
if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps))
return mv88e63xx_get_temp(ds, temp);
@@ -3203,7 +3206,7 @@ int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
- if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
return -EOPNOTSUPP;
*temp = 0;
@@ -3223,7 +3226,7 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
- if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
return -EOPNOTSUPP;
ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26);
@@ -3240,7 +3243,7 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
int phy = mv88e6xxx_6320_family(ps) ? 3 : 0;
int ret;
- if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps))
+ if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_TEMP_LIMIT))
return -EOPNOTSUPP;
*alarm = false;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 0181f67..9ddb6d0 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -366,12 +366,20 @@ enum mv88e6xxx_cap {
* GLOBAL2_SMI_OP, otherwise direct access to PHY registers is done.
*/
MV88E6XXX_CAP_SMI_PHY,
+
+ /* Internal temperature sensor.
+ * Available from any enabled port's PHY register 26, page 6.
+ */
+ MV88E6XXX_CAP_TEMP,
+ MV88E6XXX_CAP_TEMP_LIMIT,
};
/* Bitmask of capabilities */
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
+#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
+#define MV88E6XXX_FLAG_TEMP_LIMIT BIT(MV88E6XXX_CAP_TEMP_LIMIT)
#define MV88E6XXX_FLAGS_FAMILY_6095 \
MV88E6XXX_FLAG_PPU
@@ -379,21 +387,27 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6097 \
MV88E6XXX_FLAG_PPU
-#define MV88E6XXX_FLAGS_FAMILY_6165 0
+#define MV88E6XXX_FLAGS_FAMILY_6165 \
+ MV88E6XXX_FLAG_TEMP
#define MV88E6XXX_FLAGS_FAMILY_6185 \
MV88E6XXX_FLAG_PPU
#define MV88E6XXX_FLAGS_FAMILY_6320 \
(MV88E6XXX_FLAG_EEPROM | \
- MV88E6XXX_FLAG_SMI_PHY)
+ MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_TEMP | \
+ MV88E6XXX_FLAG_TEMP_LIMIT)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
- MV88E6XXX_FLAG_SMI_PHY
+ (MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_TEMP)
#define MV88E6XXX_FLAGS_FAMILY_6352 \
(MV88E6XXX_FLAG_EEPROM | \
- MV88E6XXX_FLAG_SMI_PHY)
+ MV88E6XXX_FLAG_SMI_PHY | \
+ MV88E6XXX_FLAG_TEMP | \
+ MV88E6XXX_FLAG_TEMP_LIMIT)
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 04/21] net: dsa: mv88e6xxx: factorize EEPROM access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add a MV88E6XXX_FLAG_EEPROM flag to describe switch models featuring an
EEPROM and distribute the EEPROM access routines to all models.
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 | 207 +------------------------------------------
drivers/net/dsa/mv88e6xxx.c | 208 +++++++++++++++++++++++++++++++++++++++++++-
drivers/net/dsa/mv88e6xxx.h | 18 +++-
6 files changed, 228 insertions(+), 211 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index ab5885b..8330a8e 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -124,6 +124,8 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
#ifdef CONFIG_NET_DSA_HWMON
.get_temp = mv88e6xxx_get_temp,
#endif
+ .get_eeprom = mv88e6xxx_get_eeprom,
+ .set_eeprom = mv88e6xxx_set_eeprom,
.get_regs_len = mv88e6xxx_get_regs_len,
.get_regs = mv88e6xxx_get_regs,
};
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 9d21d69..ab8c507 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -153,6 +153,8 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
+ .get_eeprom = mv88e6xxx_get_eeprom,
+ .set_eeprom = mv88e6xxx_set_eeprom,
.adjust_link = mv88e6xxx_adjust_link,
.port_bridge_join = mv88e6xxx_port_bridge_join,
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index b190647..a7afbaa 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -133,6 +133,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
#ifdef CONFIG_NET_DSA_HWMON
.get_temp = mv88e6xxx_get_temp,
#endif
+ .get_eeprom = mv88e6xxx_get_eeprom,
+ .set_eeprom = mv88e6xxx_set_eeprom,
.get_regs_len = mv88e6xxx_get_regs_len,
.get_regs = mv88e6xxx_get_regs,
.port_bridge_join = mv88e6xxx_port_bridge_join,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 6fa7c02..3bb271e 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -125,8 +125,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;
- mutex_init(&ps->eeprom_mutex);
-
ret = mv88e6xxx_switch_reset(ps, true);
if (ret < 0)
return ret;
@@ -138,207 +136,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
return mv88e6xxx_setup_ports(ds);
}
-static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- mutex_lock(&ps->eeprom_mutex);
-
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
- GLOBAL2_EEPROM_OP_READ |
- (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_eeprom_busy_wait(ds);
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
-error:
- mutex_unlock(&ps->eeprom_mutex);
- return ret;
-}
-
-static int mv88e6352_get_eeprom(struct dsa_switch *ds,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- int offset;
- int len;
- int ret;
-
- offset = eeprom->offset;
- len = eeprom->len;
- eeprom->len = 0;
-
- eeprom->magic = 0xc3ec4951;
-
- ret = mv88e6xxx_eeprom_load_wait(ds);
- if (ret < 0)
- return ret;
-
- if (offset & 1) {
- int word;
-
- word = mv88e6352_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- *data++ = (word >> 8) & 0xff;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- while (len >= 2) {
- int word;
-
- word = mv88e6352_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- *data++ = word & 0xff;
- *data++ = (word >> 8) & 0xff;
-
- offset += 2;
- len -= 2;
- eeprom->len += 2;
- }
-
- if (len) {
- int word;
-
- word = mv88e6352_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- *data++ = word & 0xff;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- return 0;
-}
-
-static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
- if (ret < 0)
- return ret;
-
- if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
- return -EROFS;
-
- return 0;
-}
-
-static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr,
- u16 data)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- mutex_lock(&ps->eeprom_mutex);
-
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
- GLOBAL2_EEPROM_OP_WRITE |
- (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_eeprom_busy_wait(ds);
-error:
- mutex_unlock(&ps->eeprom_mutex);
- return ret;
-}
-
-static int mv88e6352_set_eeprom(struct dsa_switch *ds,
- struct ethtool_eeprom *eeprom, u8 *data)
-{
- int offset;
- int ret;
- int len;
-
- if (eeprom->magic != 0xc3ec4951)
- return -EINVAL;
-
- ret = mv88e6352_eeprom_is_readonly(ds);
- if (ret)
- return ret;
-
- offset = eeprom->offset;
- len = eeprom->len;
- eeprom->len = 0;
-
- ret = mv88e6xxx_eeprom_load_wait(ds);
- if (ret < 0)
- return ret;
-
- if (offset & 1) {
- int word;
-
- word = mv88e6352_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- word = (*data++ << 8) | (word & 0xff);
-
- ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
- if (ret < 0)
- return ret;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- while (len >= 2) {
- int word;
-
- word = *data++;
- word |= *data++ << 8;
-
- ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
- if (ret < 0)
- return ret;
-
- offset += 2;
- len -= 2;
- eeprom->len += 2;
- }
-
- if (len) {
- int word;
-
- word = mv88e6352_read_eeprom_word(ds, offset >> 1);
- if (word < 0)
- return word;
-
- word = (word & 0xff00) | *data++;
-
- ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
- if (ret < 0)
- return ret;
-
- offset++;
- len--;
- eeprom->len++;
- }
-
- return 0;
-}
-
struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
.probe = mv88e6352_drv_probe,
@@ -358,8 +155,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.set_temp_limit = mv88e6xxx_set_temp_limit,
.get_temp_alarm = mv88e6xxx_get_temp_alarm,
#endif
- .get_eeprom = mv88e6352_get_eeprom,
- .set_eeprom = mv88e6352_set_eeprom,
+ .get_eeprom = mv88e6xxx_get_eeprom,
+ .set_eeprom = mv88e6xxx_set_eeprom,
.get_regs_len = mv88e6xxx_get_regs_len,
.get_regs = mv88e6xxx_get_regs,
.port_bridge_join = mv88e6xxx_port_bridge_join,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 2c8c5e1..921fe87 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -823,7 +823,7 @@ static int _mv88e6xxx_phy_wait(struct mv88e6xxx_priv_state *ps)
GLOBAL2_SMI_OP_BUSY);
}
-int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
+static int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -831,7 +831,7 @@ int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
GLOBAL2_EEPROM_OP_LOAD);
}
-int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
+static int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -839,6 +839,207 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
GLOBAL2_EEPROM_OP_BUSY);
}
+static int mv88e6xxx_read_eeprom_word(struct dsa_switch *ds, int addr)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int ret;
+
+ mutex_lock(&ps->eeprom_mutex);
+
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
+ GLOBAL2_EEPROM_OP_READ |
+ (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
+ if (ret < 0)
+ goto error;
+
+ ret = mv88e6xxx_eeprom_busy_wait(ds);
+ if (ret < 0)
+ goto error;
+
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
+error:
+ mutex_unlock(&ps->eeprom_mutex);
+ return ret;
+}
+
+int mv88e6xxx_get_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ int offset;
+ int len;
+ int ret;
+
+ offset = eeprom->offset;
+ len = eeprom->len;
+ eeprom->len = 0;
+
+ eeprom->magic = 0xc3ec4951;
+
+ ret = mv88e6xxx_eeprom_load_wait(ds);
+ if (ret < 0)
+ return ret;
+
+ if (offset & 1) {
+ int word;
+
+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
+ if (word < 0)
+ return word;
+
+ *data++ = (word >> 8) & 0xff;
+
+ offset++;
+ len--;
+ eeprom->len++;
+ }
+
+ while (len >= 2) {
+ int word;
+
+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
+ if (word < 0)
+ return word;
+
+ *data++ = word & 0xff;
+ *data++ = (word >> 8) & 0xff;
+
+ offset += 2;
+ len -= 2;
+ eeprom->len += 2;
+ }
+
+ if (len) {
+ int word;
+
+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
+ if (word < 0)
+ return word;
+
+ *data++ = word & 0xff;
+
+ offset++;
+ len--;
+ eeprom->len++;
+ }
+
+ return 0;
+}
+
+static int mv88e6xxx_eeprom_is_readonly(struct dsa_switch *ds)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int ret;
+
+ ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
+ if (ret < 0)
+ return ret;
+
+ if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
+ return -EROFS;
+
+ return 0;
+}
+
+static int mv88e6xxx_write_eeprom_word(struct dsa_switch *ds, int addr,
+ u16 data)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int ret;
+
+ mutex_lock(&ps->eeprom_mutex);
+
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
+ if (ret < 0)
+ goto error;
+
+ ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
+ GLOBAL2_EEPROM_OP_WRITE |
+ (addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
+ if (ret < 0)
+ goto error;
+
+ ret = mv88e6xxx_eeprom_busy_wait(ds);
+error:
+ mutex_unlock(&ps->eeprom_mutex);
+ return ret;
+}
+
+int mv88e6xxx_set_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ int offset;
+ int ret;
+ int len;
+
+ if (eeprom->magic != 0xc3ec4951)
+ return -EINVAL;
+
+ ret = mv88e6xxx_eeprom_is_readonly(ds);
+ if (ret)
+ return ret;
+
+ offset = eeprom->offset;
+ len = eeprom->len;
+ eeprom->len = 0;
+
+ ret = mv88e6xxx_eeprom_load_wait(ds);
+ if (ret < 0)
+ return ret;
+
+ if (offset & 1) {
+ int word;
+
+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
+ if (word < 0)
+ return word;
+
+ word = (*data++ << 8) | (word & 0xff);
+
+ ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
+ if (ret < 0)
+ return ret;
+
+ offset++;
+ len--;
+ eeprom->len++;
+ }
+
+ while (len >= 2) {
+ int word;
+
+ word = *data++;
+ word |= *data++ << 8;
+
+ ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
+ if (ret < 0)
+ return ret;
+
+ offset += 2;
+ len -= 2;
+ eeprom->len += 2;
+ }
+
+ if (len) {
+ int word;
+
+ word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
+ if (word < 0)
+ return word;
+
+ word = (word & 0xff00) | *data++;
+
+ ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
+ if (ret < 0)
+ return ret;
+
+ offset++;
+ len--;
+ eeprom->len++;
+ }
+
+ return 0;
+}
+
static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
{
return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,
@@ -2596,6 +2797,9 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
+ if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
+ mutex_init(&ps->eeprom_mutex);
+
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
mv88e6xxx_ppu_state_init(ps);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5972571..0181f67 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -351,6 +351,11 @@ enum mv88e6xxx_family {
};
enum mv88e6xxx_cap {
+ /* EEPROM Command and Data registers.
+ * See GLOBAL2_EEPROM_OP and GLOBAL2_EEPROM_DATA.
+ */
+ MV88E6XXX_CAP_EEPROM,
+
/* PHY Polling Unit.
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/
@@ -364,6 +369,7 @@ enum mv88e6xxx_cap {
};
/* Bitmask of capabilities */
+#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
@@ -379,13 +385,15 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_PPU
#define MV88E6XXX_FLAGS_FAMILY_6320 \
- MV88E6XXX_FLAG_SMI_PHY
+ (MV88E6XXX_FLAG_EEPROM | \
+ MV88E6XXX_FLAG_SMI_PHY)
#define MV88E6XXX_FLAGS_FAMILY_6351 \
MV88E6XXX_FLAG_SMI_PHY
#define MV88E6XXX_FLAGS_FAMILY_6352 \
- MV88E6XXX_FLAG_SMI_PHY
+ (MV88E6XXX_FLAG_EEPROM | \
+ MV88E6XXX_FLAG_SMI_PHY)
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
@@ -521,8 +529,10 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp);
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
-int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
-int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
+int mv88e6xxx_get_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
+ u8 *data);
+int mv88e6xxx_set_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
+ u8 *data);
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e);
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 03/21] net: dsa: mv88e6xxx: factorize PHY indirect access
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Some switch has dedicated SMI PHY Command and Data registers, used to
indirectly access the PHYs, instead of direct access.
Identify these switch models and make mv88e6xxx_phy_{read,write} generic
enough to support every models.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6171.c | 4 ++--
drivers/net/dsa/mv88e6352.c | 4 ++--
drivers/net/dsa/mv88e6xxx.c | 37 ++++---------------------------------
drivers/net/dsa/mv88e6xxx.h | 22 +++++++++++++---------
4 files changed, 21 insertions(+), 46 deletions(-)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index e64cbee..b190647 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -124,8 +124,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.probe = mv88e6171_drv_probe,
.setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
- .phy_read = mv88e6xxx_phy_read_indirect,
- .phy_write = mv88e6xxx_phy_write_indirect,
+ .phy_read = mv88e6xxx_phy_read,
+ .phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index c61f0f4..6fa7c02 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -344,8 +344,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.probe = mv88e6352_drv_probe,
.setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
- .phy_read = mv88e6xxx_phy_read_indirect,
- .phy_write = mv88e6xxx_phy_write_indirect,
+ .phy_read = mv88e6xxx_phy_read,
+ .phy_write = mv88e6xxx_phy_write,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index a28b46c..2c8c5e1 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2887,6 +2887,8 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
ret = mv88e6xxx_phy_read_ppu(ps, addr, regnum);
+ else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
+ ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
else
ret = _mv88e6xxx_phy_read(ps, addr, regnum);
@@ -2908,6 +2910,8 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
ret = mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
+ else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
+ ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
else
ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
@@ -2915,39 +2919,6 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
return ret;
}
-int
-mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ps, port);
- int ret;
-
- if (addr < 0)
- return 0xffff;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
- mutex_unlock(&ps->smi_mutex);
- return ret;
-}
-
-int
-mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
- u16 val)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int addr = mv88e6xxx_port_to_phy_addr(ps, port);
- int ret;
-
- if (addr < 0)
- return addr;
-
- mutex_lock(&ps->smi_mutex);
- ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
- mutex_unlock(&ps->smi_mutex);
- return ret;
-}
-
#ifdef CONFIG_NET_DSA_HWMON
static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 52ca24e..5972571 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -355,10 +355,17 @@ enum mv88e6xxx_cap {
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/
MV88E6XXX_CAP_PPU,
+
+ /* SMI PHY Command and Data registers.
+ * This requires an indirect access to PHY registers through
+ * GLOBAL2_SMI_OP, otherwise direct access to PHY registers is done.
+ */
+ MV88E6XXX_CAP_SMI_PHY,
};
/* Bitmask of capabilities */
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
+#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
#define MV88E6XXX_FLAGS_FAMILY_6095 \
MV88E6XXX_FLAG_PPU
@@ -371,11 +378,14 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6185 \
MV88E6XXX_FLAG_PPU
-#define MV88E6XXX_FLAGS_FAMILY_6320 0
+#define MV88E6XXX_FLAGS_FAMILY_6320 \
+ MV88E6XXX_FLAG_SMI_PHY
-#define MV88E6XXX_FLAGS_FAMILY_6351 0
+#define MV88E6XXX_FLAGS_FAMILY_6351 \
+ MV88E6XXX_FLAG_SMI_PHY
-#define MV88E6XXX_FLAGS_FAMILY_6352 0
+#define MV88E6XXX_FLAGS_FAMILY_6352 \
+ MV88E6XXX_FLAG_SMI_PHY
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
@@ -497,9 +507,6 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
-int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum);
-int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
- u16 val);
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data);
@@ -516,9 +523,6 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
-int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
-int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
- u16 val);
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e);
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 01/21] net: dsa: mv88e6xxx: add flags to info
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <1462571843-14397-1-git-send-email-vivien.didelot@savoirfairelinux.com>
Add a flags bitmap to the info structure in order to identify features
supported or not by the different switch models.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6123.c | 3 +++
drivers/net/dsa/mv88e6131.c | 4 ++++
drivers/net/dsa/mv88e6171.c | 4 ++++
drivers/net/dsa/mv88e6352.c | 6 ++++++
drivers/net/dsa/mv88e6xxx.h | 21 +++++++++++++++++++++
5 files changed, 38 insertions(+)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 5535a42..ab5885b 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -24,18 +24,21 @@ static const struct mv88e6xxx_info mv88e6123_table[] = {
.name = "Marvell 88E6123",
.num_databases = 4096,
.num_ports = 3,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6165,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6161,
.family = MV88E6XXX_FAMILY_6165,
.name = "Marvell 88E6161",
.num_databases = 4096,
.num_ports = 6,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6165,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6165,
.family = MV88E6XXX_FAMILY_6165,
.name = "Marvell 88E6165",
.num_databases = 4096,
.num_ports = 6,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6165,
}
};
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 357ab79..d477320 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -24,24 +24,28 @@ static const struct mv88e6xxx_info mv88e6131_table[] = {
.name = "Marvell 88E6095/88E6095F",
.num_databases = 256,
.num_ports = 11,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6095,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
.family = MV88E6XXX_FAMILY_6097,
.name = "Marvell 88E6085",
.num_databases = 4096,
.num_ports = 10,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6097,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
.family = MV88E6XXX_FAMILY_6185,
.name = "Marvell 88E6131",
.num_databases = 256,
.num_ports = 8,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6185,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
.family = MV88E6XXX_FAMILY_6185,
.name = "Marvell 88E6185",
.num_databases = 256,
.num_ports = 10,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6185,
}
};
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index f75164d..e64cbee 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -24,24 +24,28 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
.name = "Marvell 88E6171",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
.family = MV88E6XXX_FAMILY_6351,
.name = "Marvell 88E6175",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
.family = MV88E6XXX_FAMILY_6351,
.name = "Marvell 88E6350",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
.family = MV88E6XXX_FAMILY_6351,
.name = "Marvell 88E6351",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6351,
}
};
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index c622a1d..c61f0f4 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -29,36 +29,42 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
.name = "Marvell 88E6320",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6320,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
.family = MV88E6XXX_FAMILY_6320,
.name = "Marvell 88E6321",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6320,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
.family = MV88E6XXX_FAMILY_6352,
.name = "Marvell 88E6172",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
.family = MV88E6XXX_FAMILY_6352,
.name = "Marvell 88E6176",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
.family = MV88E6XXX_FAMILY_6352,
.name = "Marvell 88E6240",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
}, {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
.family = MV88E6XXX_FAMILY_6352,
.name = "Marvell 88E6352",
.num_databases = 4096,
.num_ports = 7,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6352,
}
};
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 4f455d2..c67b72a 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -350,12 +350,27 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
};
+#define MV88E6XXX_FLAGS_FAMILY_6095 0
+
+#define MV88E6XXX_FLAGS_FAMILY_6097 0
+
+#define MV88E6XXX_FLAGS_FAMILY_6165 0
+
+#define MV88E6XXX_FLAGS_FAMILY_6185 0
+
+#define MV88E6XXX_FLAGS_FAMILY_6320 0
+
+#define MV88E6XXX_FLAGS_FAMILY_6351 0
+
+#define MV88E6XXX_FLAGS_FAMILY_6352 0
+
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
u16 prod_num;
const char *name;
unsigned int num_databases;
unsigned int num_ports;
+ unsigned long flags;
};
struct mv88e6xxx_atu_entry {
@@ -449,6 +464,12 @@ struct mv88e6xxx_hw_stat {
enum stat_type type;
};
+static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
+ unsigned long flags)
+{
+ return (ps->info->flags & flags) == flags;
+}
+
int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active);
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv,
--
2.8.2
^ permalink raw reply related
* [PATCH net-next 00/21] net: dsa: mv88e6xxx: turn into monolithic driver
From: Vivien Didelot @ 2016-05-06 21:57 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
This patchset merges all mv88e6* drivers supported by the shared
mv88e6xxx code into a single mv88e6xxx DSA switch driver.
Some flags are added to describe the capabilities of a switch model,
such as the presence of a PPU, EEPROM, some old or new registers, etc.
First these flags are used to conditionally support the same set of
functions in every driver, then specific driver files are removed in
favor of the common mv88e6xxx driver.
Only the merge of driver specific setup code assumes a few differences.
If these differences such as frames priorities are really needed for
some models, they can easily be brought back in a future patch.
Some inconsistencies might show up, such as the need for
MV88E6XXX_FLAG_PPU and MV88E6XXX_FLAG_PPU_ACTIVE flags. But this
patchset does not aim to fix them yet. A future patch can do that if
they end up being unwanted.
The patchset has been tested on interconnected 88E6352 and 88E6185.
Changes RFC -> v1:
- introduce flags in a separate patch
- do not refactor anything yet
- do not add new functions prefixed with _
- drop packet discarding and mentioned tested platforms
- factorize family flags
- update text for NET_DSA_MV88E6XXX Kconfig entry
Vivien Didelot (21):
net: dsa: mv88e6xxx: add flags to info
net: dsa: mv88e6xxx: factorize PHY access with PPU
net: dsa: mv88e6xxx: factorize PHY indirect access
net: dsa: mv88e6xxx: factorize EEPROM access
net: dsa: mv88e6xxx: factorize temperature access
net: dsa: mv88e6xxx: factorize MAC address setting
net: dsa: mv88e6xxx: factorize EEE access
net: dsa: mv88e6xxx: factorize registers access
net: dsa: mv88e6xxx: factorize bridge support
net: dsa: mv88e6xxx: factorize VTU access
net: dsa: mv88e6xxx: factorize ATU access
net: dsa: mv88e6xxx: factorize switch reset
net: dsa: mv88e6xxx: factorize global setup
net: dsa: mv88e6xxx: factorize GLOBAL_CONTROL setup
net: dsa: mv88e6xxx: factorize VLAN Ethertype
net: dsa: mv88e6xxx: factorize GLOBAL_MONITOR_CONTROL setup
net: dsa: mv88e6xxx: factorize GLOBAL_CONTROL_2 setup
net: dsa: mv88e6xxx: factorize frames priorities
net: dsa: mv88e6xxx: factorize switch setup
net: dsa: mv88e6xxx: factorize tag protocol
net: dsa: mv88e6xxx: factorize the switch driver
arch/arm/configs/multi_v5_defconfig | 5 +-
arch/arm/configs/mvebu_v7_defconfig | 2 +-
arch/arm/configs/orion5x_defconfig | 3 +-
arch/tile/configs/tilegx_defconfig | 3 +-
arch/tile/configs/tilepro_defconfig | 3 +-
drivers/net/dsa/Kconfig | 45 +-
drivers/net/dsa/Makefile | 15 +-
drivers/net/dsa/mv88e6123.c | 130 -----
drivers/net/dsa/mv88e6131.c | 204 --------
drivers/net/dsa/mv88e6171.c | 151 ------
drivers/net/dsa/mv88e6352.c | 377 --------------
drivers/net/dsa/mv88e6xxx.c | 984 +++++++++++++++++++++++++++---------
drivers/net/dsa/mv88e6xxx.h | 249 ++++++---
13 files changed, 908 insertions(+), 1263 deletions(-)
delete mode 100644 drivers/net/dsa/mv88e6123.c
delete mode 100644 drivers/net/dsa/mv88e6131.c
delete mode 100644 drivers/net/dsa/mv88e6171.c
delete mode 100644 drivers/net/dsa/mv88e6352.c
--
2.8.2
^ permalink raw reply
* Re: [REGRESSION] asix: Lots of asix_rx_fixup() errors and slow transmissions
From: John Stultz @ 2016-05-06 20:57 UTC (permalink / raw)
To: Dean Jenkins
Cc: David B. Robins, lkml, Mark Craske, David S. Miller, YongQin Liu,
Guodong Xu, linux-usb, netdev, Ivan Vecera
In-Reply-To: <57291539.6080405@mentor.com>
On Tue, May 3, 2016 at 2:16 PM, Dean Jenkins <Dean_Jenkins@mentor.com> wrote:
>
> [ 239.027993] asix 1-1.1:1.0 eth0: asix_rx_fixup() Data Header
> synchronisation was lost, remaining 988
>
> This error message consistently shows the remaining value to be 988, at
> least for the 3 examples provided by John. This does not suggest a random
> failure unless there are other examples of a non 988 remaining value error
> message. 988 is well within a Ethernet frame length so seems to be valid.
>
> I think a good step would be to add some debug to print the rx->remaining
> value at entry to asix_rx_fixup_internal(). This would generate a lot of
> debug but a pattern of the values might emerge.
So I've been trying to add some print messages here to better
understand whats going on.
Again, I'm a bit new to this code, so forgive me for my lack of
understanding things. Since the remaining value seems to be key, I
tried to look around and figure out where it was being set. It seems
like its only set in this function, is that right? So this made me
guess something might be happening in a previous iteration that was
causing this to trigger.
I added some debug prints to every time we set the remaining value, or
modify it, as well as to print the value if we enter the fixup
function with a non-zero remaining value.
When we set the remaining value, usually its to 1514, when the skblen is 1518.
However, right before we catch the problem, I see this:
[ 84.844337] JDB set remaining to 1514 (skblen: 1518)
[ 84.844379] JDB set remaining to 1514 (skblen: 1518)
[ 84.844429] JDB set remaining to 1514 (skblen: 1518)
[ 84.844458] JDB set remaining to 1514 (skblen: 1518)
[ 84.844483] JDB set remaining to 1514 (skblen: 1518)
[ 84.844507] JDB set remaining to 1514 (skblen: 1518)
[ 84.844559] JDB set remaining to 1514 (skblen: 2048)
[ 84.844583] JDB set remaining to 1514 (skblen: 2048)
[ 84.844595] JDB: 1514 > 2048 - 1522
[ 84.844606] JDB: dropping remaining by 526
[ 84.844624] asix_rx_fixup_internal() remaining: 988, skb->len: 2048
[ 84.844672] asix 1-5:1.0 eth1: asix_rx_fixup() Data Header
synchronisation was lost, remaining 988
[ 84.844945] asix 1-5:1.0 eth1: asix_rx_fixup() Bad Header Length
0xdd5f8f9b, offset 4
[ 84.845217] asix 1-5:1.0 eth1: asix_rx_fixup() Bad Header Length
0x3ce1ad3c, offset 4
[ 84.845451] JDB set remaining to 1514 (skblen: 1518)
[ 84.845485] JDB set remaining to 1514 (skblen: 1518)
[ 84.845511] JDB set remaining to 1514 (skblen: 1518)
[ 84.851003] JDB set remaining to 1514 (skblen: 1518)
So when the issue happens, it seems to be due to an larger then usual
skb (2048). The first time through the wile loop we set the remaining
to 1514, but offset is fairly small, so we set copy_length to 1514,
and clear remaining. The offset is bumped by a little more then the
copy length and we loop again. Then the second time through we set
remaining to 1514, but since offset is bigger now, the if
(rx->remaining > skb->len - offset) case is true..
This is where it feels a little strange..
We calculate the copy_length as the difference between the offset and
the skb->len (so how much is left in the skb, which is 526), then
decrement remaining by that amount. Not really sure what remaining
(now 988) is supposed to represent here. We copy the 526 bytes, and
then exit the loop.
Now the next time we are called, we enter and we have a remaining
value still of 988, which triggers the header synchronization error
path.
Now, I'm not sure if the remainder handling logic is sane, or if the
skb->len being 2048 is problematic, or what. The skb->lens can vary
in sizes, usually 1518 during high throughput, but I've seen 1588,
1640, and other larger numbers that don't trigger the same problem.
ie:
[ 106.946473] JDB set remaining to 1514 (skblen: 1518)
[ 106.946525] JDB set remaining to 1514 (skblen: 1640)
[ 106.946546] JDB set remaining to 118 (skblen: 1640)
[ 106.946586] JDB set remaining to 1514 (skblen: 1518)
So yea.. maybe that will help clue things in a bit? I'm still a bit lost. :)
thanks
-john
^ permalink raw reply
* Re: [RFC PATCH net-next 19/20] net: dsa: mv88e6xxx: factorize tag protocol
From: Vivien Didelot @ 2016-05-06 20:56 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <20160506010949.GM7972@lunn.ch>
Hi Andrew,
Andrew Lunn <andrew@lunn.ch> writes:
> On Thu, May 05, 2016 at 06:41:03PM -0400, Vivien Didelot wrote:
>> 6131 is the only driver to set the tag protocol to DSA_TAG_PROTO_DSA.
>> Since it works fine with DSA_TAG_PROTO_EDSA, change its value, like all
>> other mv88e6xxx drivers.
>
> You might as well remove net/dsa/tag_dsa.c as well, since it is now
> unused. Please do that as a separate patch.
Why not, but isn't it a bit out of the scope of this patchset?
Thanks,
Vivien
^ permalink raw reply
* Re: [PATCH v2 next-next 02/12] net: define gso types for IPx over IPv4 and IPv6
From: Alexander Duyck @ 2016-05-06 20:54 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, Netdev, Kernel Team
In-Reply-To: <CALx6S374bWLRk2T6UhNa30e-rRRyNe6cemuqRHbphkAfo6991w@mail.gmail.com>
On Fri, May 6, 2016 at 1:43 PM, Tom Herbert <tom@herbertland.com> wrote:
> On Fri, May 6, 2016 at 1:34 PM, Alexander Duyck
> <alexander.duyck@gmail.com> wrote:
>> On Fri, May 6, 2016 at 1:04 PM, Tom Herbert <tom@herbertland.com> wrote:
>>> This patch defines two new GDO definitions SKB_GSO_IPXIP4 and
>>> SKB_GSO_IPXIP6 along with corresponding NETIF_F_GSO_IPXIP4 and
>>> NETIF_F_GSO_IPXIP6. These are used to described IP in IP
>>> tunnel and what the outer protocol is. The inner protocol
>>> can be deduced from other GSO types (e.g. SKB_GSO_TCPV4 and
>>> SKB_GSO_TCPV6). The GSO types of SKB_GSO_IPIP and SKB_GSO_SIT
>>> are removed (these are both instances of SKB_GSO_IPXIP4).
>>> SKB_GSO_IPXIP6 will be used when support for GSO with IP
>>> encapsulation over IPv6 is added.
>>>
>>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>>> ---
>>> drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 5 ++---
>>> drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++--
>>> drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +--
>>> drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +--
>>> drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 3 +--
>>> drivers/net/ethernet/intel/i40evf/i40evf_main.c | 3 +--
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +--
>>> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 3 +--
>>> include/linux/netdev_features.h | 12 ++++++------
>>> include/linux/netdevice.h | 4 ++--
>>> include/linux/skbuff.h | 4 ++--
>>> net/core/ethtool.c | 4 ++--
>>> net/ipv4/af_inet.c | 2 +-
>>> net/ipv4/ipip.c | 2 +-
>>> net/ipv6/ip6_offload.c | 4 ++--
>>> net/ipv6/sit.c | 4 ++--
>>> net/netfilter/ipvs/ip_vs_xmit.c | 11 ++---------
>>> 17 files changed, 30 insertions(+), 44 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
>>> index d465bd7..0a5b770 100644
>>> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
>>> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
>>> @@ -13259,12 +13259,11 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
>>> NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
>>> if (!chip_is_e1x) {
>>> dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
>>> - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT;
>>> + NETIF_F_GSO_IPXIP4;
>>> dev->hw_enc_features =
>>> NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
>>> NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
>>> - NETIF_F_GSO_IPIP |
>>> - NETIF_F_GSO_SIT |
>>> + NETIF_F_GSO_IPXIP4 |
>>> NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL;
>>> }
>>>
>>> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
>>> index fd85b6d..e449228 100644
>>> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
>>> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
>>> @@ -6218,7 +6218,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>>> dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
>>> NETIF_F_TSO | NETIF_F_TSO6 |
>>> NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
>>> - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
>>> + NETIF_F_GSO_IPXIP4 |
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
>>> NETIF_F_GSO_PARTIAL | NETIF_F_RXHASH |
>>> NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO;
>>> @@ -6228,7 +6228,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>>> NETIF_F_TSO | NETIF_F_TSO6 |
>>> NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
>>> - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
>>> + NETIF_F_GSO_IPXIP4;
>>> NETIF_F_GSO_PARTIAL;
>>> dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
>>> NETIF_F_GSO_GRE_CSUM;
>>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
>>> index f6da6b7..c2a4c10 100644
>>> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
>>> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
>>> @@ -9131,8 +9131,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
>>> NETIF_F_TSO6 |
>>> NETIF_F_GSO_GRE |
>>> NETIF_F_GSO_GRE_CSUM |
>>> - NETIF_F_GSO_IPIP |
>>> - NETIF_F_GSO_SIT |
>>> + NETIF_F_GSO_IPXIP4 |
>>> NETIF_F_GSO_UDP_TUNNEL |
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM |
>>> NETIF_F_GSO_PARTIAL |
>>
>> So for all the Intel drivers they support IPv6 and IPv4 outer header
>> tunnel types. As such you can add SKB_GSO_IPXIP6 as well and you
>> should be able to see offloads without any issues. This applies for
>> all the Intel drivers below and igb which should have a patch
>> available sometime soon as it is still in Jeff Kirsher's tree.
>>
> Can we do this in a follow up patch?
The Intel driver piece yes, but the problem is there was also the bit
at the end where you deleted a comment about needing an IPv6 type and
didn't add an IPv6 type. That is one piece I would be a bit more of a
stickler on as that comment is there for a reason and you are removing
it without resolving the issue it is meant to flag.
>>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>>> index 2765d7e..4a3d60a 100644
>>> --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>>> +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>>> @@ -2302,8 +2302,7 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
>>>
>>> if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
>>> SKB_GSO_GRE_CSUM |
>>> - SKB_GSO_IPIP |
>>> - SKB_GSO_SIT |
>>> + SKB_GSO_IPXIP4 |
>>> SKB_GSO_UDP_TUNNEL |
>>> SKB_GSO_UDP_TUNNEL_CSUM)) {
>>> if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
>>> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
>>> index ede8dfc..aaccb7e 100644
>>> --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
>>> +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
>>> @@ -1567,8 +1567,7 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
>>>
>>> if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
>>> SKB_GSO_GRE_CSUM |
>>> - SKB_GSO_IPIP |
>>> - SKB_GSO_SIT |
>>> + SKB_GSO_IPXIP4 |
>>> SKB_GSO_UDP_TUNNEL |
>>> SKB_GSO_UDP_TUNNEL_CSUM)) {
>>> if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
>>> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
>>> index 9f0bd7a..bfd0962 100644
>>> --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
>>> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
>>> @@ -2241,8 +2241,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
>>> NETIF_F_TSO6 |
>>> NETIF_F_GSO_GRE |
>>> NETIF_F_GSO_GRE_CSUM |
>>> - NETIF_F_GSO_IPIP |
>>> - NETIF_F_GSO_SIT |
>>> + NETIF_F_GSO_IPXIP4 |
>>> NETIF_F_GSO_UDP_TUNNEL |
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM |
>>> NETIF_F_GSO_PARTIAL |
>>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>>> index d08fbcf..28e3b5a 100644
>>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>>> @@ -9482,8 +9482,7 @@ skip_sriov:
>>>
>>> #define IXGBE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>>> NETIF_F_GSO_GRE_CSUM | \
>>> - NETIF_F_GSO_IPIP | \
>>> - NETIF_F_GSO_SIT | \
>>> + NETIF_F_GSO_IPXIP4 | \
>>> NETIF_F_GSO_UDP_TUNNEL | \
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM)
>>>
>>> diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
>>> index 5e348b1..d86e511 100644
>>> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
>>> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
>>> @@ -4062,8 +4062,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>>>
>>> #define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>>> NETIF_F_GSO_GRE_CSUM | \
>>> - NETIF_F_GSO_IPIP | \
>>> - NETIF_F_GSO_SIT | \
>>> + NETIF_F_GSO_IPXIP4 | \
>>> NETIF_F_GSO_UDP_TUNNEL | \
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM)
>>>
>>
>> So with GSO partial all of the igb/ixgbe parts should be able to
>> support any tunnel type you can throw at it.
>>
>>> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
>>> index bc87362..aa7b240 100644
>>> --- a/include/linux/netdev_features.h
>>> +++ b/include/linux/netdev_features.h
>>> @@ -44,8 +44,8 @@ enum {
>>> NETIF_F_FSO_BIT, /* ... FCoE segmentation */
>>> NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */
>>> NETIF_F_GSO_GRE_CSUM_BIT, /* ... GRE with csum with TSO */
>>> - NETIF_F_GSO_IPIP_BIT, /* ... IPIP tunnel with TSO */
>>> - NETIF_F_GSO_SIT_BIT, /* ... SIT tunnel with TSO */
>>> + NETIF_F_GSO_IPXIP4_BIT, /* ... IP4 or IP6 over IP4 with TSO */
>>> + NETIF_F_GSO_IPXIP6_BIT, /* ... IP4 or IP6 over IP6 with TSO */
>>> NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
>>> NETIF_F_GSO_PARTIAL_BIT, /* ... Only segment inner-most L4
>>> @@ -121,8 +121,8 @@ enum {
>>> #define NETIF_F_RXALL __NETIF_F(RXALL)
>>> #define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE)
>>> #define NETIF_F_GSO_GRE_CSUM __NETIF_F(GSO_GRE_CSUM)
>>> -#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP)
>>> -#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
>>> +#define NETIF_F_GSO_IPXIP4 __NETIF_F(GSO_IPXIP4)
>>> +#define NETIF_F_GSO_IPXIP6 __NETIF_F(GSO_IPXIP6)
>>> #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
>>> #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
>>> #define NETIF_F_TSO_MANGLEID __NETIF_F(TSO_MANGLEID)
>>> @@ -200,8 +200,8 @@ enum {
>>>
>>> #define NETIF_F_GSO_ENCAP_ALL (NETIF_F_GSO_GRE | \
>>> NETIF_F_GSO_GRE_CSUM | \
>>> - NETIF_F_GSO_IPIP | \
>>> - NETIF_F_GSO_SIT | \
>>> + NETIF_F_GSO_IPXIP4 | \
>>> + NETIF_F_GSO_IPXIP6 | \
>>> NETIF_F_GSO_UDP_TUNNEL | \
>>> NETIF_F_GSO_UDP_TUNNEL_CSUM)
>>>
>>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>>> index 63580e6..8b1eedc 100644
>>> --- a/include/linux/netdevice.h
>>> +++ b/include/linux/netdevice.h
>>> @@ -4005,8 +4005,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>>> BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
>>> BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
>>> BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
>>> - BUILD_BUG_ON(SKB_GSO_IPIP != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
>>> - BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
>>> + BUILD_BUG_ON(SKB_GSO_IPXIP4 != (NETIF_F_GSO_IPXIP4 >> NETIF_F_GSO_SHIFT));
>>> + BUILD_BUG_ON(SKB_GSO_IPXIP6 != (NETIF_F_GSO_IPXIP6 >> NETIF_F_GSO_SHIFT));
>>> BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
>>> BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
>>> BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
>>> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>>> index c413c58..65968a9 100644
>>> --- a/include/linux/skbuff.h
>>> +++ b/include/linux/skbuff.h
>>> @@ -471,9 +471,9 @@ enum {
>>>
>>> SKB_GSO_GRE_CSUM = 1 << 8,
>>>
>>> - SKB_GSO_IPIP = 1 << 9,
>>> + SKB_GSO_IPXIP4 = 1 << 9,
>>>
>>> - SKB_GSO_SIT = 1 << 10,
>>> + SKB_GSO_IPXIP6 = 1 << 10,
>>>
>>> SKB_GSO_UDP_TUNNEL = 1 << 11,
>>>
>>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>>> index bdb4013..f403481 100644
>>> --- a/net/core/ethtool.c
>>> +++ b/net/core/ethtool.c
>>> @@ -84,8 +84,8 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
>>> [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
>>> [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
>>> [NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation",
>>> - [NETIF_F_GSO_IPIP_BIT] = "tx-ipip-segmentation",
>>> - [NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation",
>>> + [NETIF_F_GSO_IPXIP4_BIT] = "tx-ipxip4-segmentation",
>>> + [NETIF_F_GSO_IPXIP6_BIT] = "tx-ipxip6-segmentation",
>>> [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
>>> [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
>>> [NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial",
>>> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
>>> index 7f08d45..25040b1 100644
>>> --- a/net/ipv4/af_inet.c
>>> +++ b/net/ipv4/af_inet.c
>>> @@ -1483,7 +1483,7 @@ out_unlock:
>>> static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
>>> {
>>> skb->encapsulation = 1;
>>> - skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
>>> + skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
>>> return inet_gro_complete(skb, nhoff);
>>> }
>>>
>>> diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
>>> index 9282748..9783701 100644
>>> --- a/net/ipv4/ipip.c
>>> +++ b/net/ipv4/ipip.c
>>> @@ -219,7 +219,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
>>> if (unlikely(skb->protocol != htons(ETH_P_IP)))
>>> goto tx_error;
>>>
>>> - if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
>>> + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
>>> goto tx_error;
>>>
>>> skb_set_inner_ipproto(skb, IPPROTO_IPIP);
>>> diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
>>> index 9ad743b..787e55f 100644
>>> --- a/net/ipv6/ip6_offload.c
>>> +++ b/net/ipv6/ip6_offload.c
>>> @@ -86,7 +86,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
>>> proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
>>>
>>> if (skb->encapsulation &&
>>> - skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
>>> + skb_shinfo(skb)->gso_type & (SKB_GSO_IPXIP4 | SKB_GSO_IPXIP6))
>>> udpfrag = proto == IPPROTO_UDP && encap;
>>> else
>>> udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
>>> @@ -294,7 +294,7 @@ out_unlock:
>>> static int sit_gro_complete(struct sk_buff *skb, int nhoff)
>>> {
>>> skb->encapsulation = 1;
>>> - skb_shinfo(skb)->gso_type |= SKB_GSO_SIT;
>>> + skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
>>> return ipv6_gro_complete(skb, nhoff);
>>> }
>>>
>>> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
>>> index a13d8c1..0a5a255 100644
>>> --- a/net/ipv6/sit.c
>>> +++ b/net/ipv6/sit.c
>>> @@ -913,7 +913,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
>>> goto tx_error;
>>> }
>>>
>>> - if (iptunnel_handle_offloads(skb, SKB_GSO_SIT)) {
>>> + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) {
>>> ip_rt_put(rt);
>>> goto tx_error;
>>> }
>>> @@ -1000,7 +1000,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
>>> struct ip_tunnel *tunnel = netdev_priv(dev);
>>> const struct iphdr *tiph = &tunnel->parms.iph;
>>>
>>> - if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
>>> + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
>>> goto tx_error;
>>>
>>> skb_set_inner_ipproto(skb, IPPROTO_IPIP);
>>> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
>>> index 6d19d2e..f646ef6 100644
>>> --- a/net/netfilter/ipvs/ip_vs_xmit.c
>>> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
>>> @@ -932,16 +932,9 @@ error:
>>>
>>> static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
>>> {
>>> - if (encaps_af == AF_INET) {
>>> - if (orig_af == AF_INET)
>>> - return SKB_GSO_IPIP;
>>> + if (encaps_af == AF_INET)
>>> + return SKB_GSO_IPXIP4;
>>>
>>> - return SKB_GSO_SIT;
>>> - }
>>> -
>>> - /* GSO: we need to provide proper SKB_GSO_ value for IPv6:
>>> - * SKB_GSO_SIT/IPV6
>>> - */
>>
>> I wouldn't delete this comment until you actually have resolved the
>> issue of providing a proper GSO value for IPv6.
>>
>>> return 0;
>>> }
>>>
>>> --
>>> 2.8.0.rc2
>>>
^ permalink raw reply
* Re: [REGRESSION] asix: Lots of asix_rx_fixup() errors and slow transmissions
From: David B. Robins @ 2016-05-06 20:45 UTC (permalink / raw)
To: Dean Jenkins
Cc: John Stultz, lkml, Mark Craske, David S. Miller, YongQin Liu,
Guodong Xu, linux-usb, netdev, Ivan Vecera
In-Reply-To: <5729AB90.9010704@mentor.com>
On 2016-05-04 03:58, Dean Jenkins wrote:
> On 04/05/16 01:28, David B. Robins wrote:
>>
>>>
>>> Here is the code snippet from the patch with my annotations between #
>>> #, I will try to explain my intentions. Feel free to point out any
>>> flaws:
>>>
>>> if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
>>> # Only runs when rx->remaining !=0 and the end of the
>>> Ethernet
>>> frame + next 32-bit header word is within the URB buffer. #
>>> # Therefore, this code does not run when the end of an
>>> Ethernet frame has been reached in the previous URB #
>>> # or when the end of the Ethernet frame + next 32-bit header
>>> word will be in a later URB buffer #
>>
>> It may well be. I don't have the setup with me now, but I can try
>> tomorrow to reproduce an environment where I can add some more
>> detailed logging.
>>
>> Since the URB length has to be >= than the remaining data plus a u32,
>> the devices that John Stultz and I are using (AX88772B in my case) may
>> be adding some additional data/padding after an Ethernet frame,
>> expecting it to be discarded, and running into this check and its
>> consequences. This may mean the device is badly behaved, if it is
>> specified not to send anything extra; in any case, a well-intentioned
>> error correction has gone badly, but I better understand the intent
>> now. I am curious to know how often the device you are using benefits
>> from this block of code.
>
> The issue is that the driver should be robust to cope with missing
> URBs. Whilst testing with D-Link DUB-E100 C1 AX88772 USB to Ethernet
> adaptor in our ARM embedded system which runs in hostile environments,
> it was noticed that URBs could be lost (probably due to a bug
> elsewhere or low memory issue). Without this patch, a missing URB
> causes bad Ethernet frames to be passed up to the IP stack because
> rx->remaining spans multiple URBs.
>
> In the good case of an Ethernet frame spanning 2 URBs, the 1st URB is
> processed and copies the 1st part of the Ethernet frame into the
> netdev buffer, for the 2nd URB the remaining part of the Ethernet
> frame is copied into the same netdev buffer to complete the Ethernet
> frame. The netdev buffer is then sent up to the IP stack.
>
> In the case of a missing URB, a bad Ethernet frame is created as
> follows:
> The 1st URB is processed and copies the 1st part of the Ethernet frame
> into the netdev buffer, the 2nd URB is lost (somehow), the 3rd URB is
> processed and blindly copies what it thinks is the remaining part of
> the Ethernet frame in the same netdev buffer which corrupts the
> Ethernet frame. The netdev buffer is then sent up to the IP stack. The
> 3rd URB and subsequent URBs are processed but synchronisation has been
> lost so can misread data as a 32-bit header word. It is likely that
> some good Ethernet frames get discarded whilst trying to
> resynchronise.
>
> A recovery strategy for regaining lock with the 32-bit header word is
> necessary otherwise the driver will have difficulty in recovering from
> a lost URB.
>
> In the "olden days", the 32-bit header word was always at the start of
> the URB buffer so previous URBs did not influence the current URB. So
> no recovery strategy was needed at that time. But now we have to
> remember what happened in the previous URB and a lost URB can cause a
> discontinuity in the data stream because the data is not always
> aligned to the start of the URB buffer.
>
> I agree that your environment may never suffer from lost URBs so
> removal of the patch would work OK.
>
> I will try to find some time to setup a test environment.
I got the chance to add some more logging (and add back the header
synchronization code) to a system which is receiving video data on an
8-port POE device using AX88772Bs - it replaces the "Data header
synchronization was lost" log and logs a few more local items ("u32" =
rx->header):
[3105478.073908] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3105478.073918] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() Bad Header
Length 0xf05b7c5f, offset 4
[3105478.074022] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() skb->len =
2048
[3105478.074032] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() Bad Header
Length 0xffaae2a5, offset 4
[3105478.074146] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() skb->len =
1518
[3105478.074280] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() skb->len =
2048
[3105478.074291] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() Bad Header
Length 0xe1478400, offset 4
[3105478.074399] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() skb->len = 916
[3105478.074409] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() Bad Header
Length 0x9fa84eb5, offset 4
[3105478.074657] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() skb->len =
1518
Grepping for just the SYNC_LOSS messages shows a similar pattern to that
seen elsewhere in the thread:
[3104761.056033] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.058035] asix 1-1.4.1.3:1.0 poe2: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.076795] asix 1-1.4.2.3:1.0 poe4: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.107904] asix 1-1.4.2.3:1.0 poe4: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.114649] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.121152] asix 1-1.4.1.1:1.0 poe1: asix_rx_fixup() SYNC_LOSS
remain 988 len 1518 offset 992 u32 0xecf95000
[3104761.147784] asix 1-1.4.1.3:1.0 poe2: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.160535] asix 1-1.4.1.1:1.0 poe1: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.168024] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.168403] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.170654] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.180418] asix 1-1.4.1.1:1.0 poe1: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.221783] asix 1-1.4.1.1:1.0 poe1: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.248784] asix 1-1.4.2.2:1.0 poe7: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.252421] asix 1-1.4.1.2:1.0 poe5: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.262903] asix 1-1.4.2.4:1.0 poe8: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.266904] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.267281] asix 1-1.4.2.4:1.0 poe8: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.271665] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.273915] asix 1-1.4.2.4:1.0 poe8: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.280048] asix 1-1.4.2.4:1.0 poe8: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.287152] asix 1-1.4.2.3:1.0 poe4: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.292157] asix 1-1.4.2.3:1.0 poe4: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.295054] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.310915] asix 1-1.4.1.1:1.0 poe1: asix_rx_fixup() SYNC_LOSS
remain 988 len 2022 offset 992 u32 0xecf95000
[3104761.316918] asix 1-1.4.2.3:1.0 poe4: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.324935] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.326665] asix 1-1.4.2.3:1.0 poe4: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
[3104761.336420] asix 1-1.4.1.4:1.0 poe6: asix_rx_fixup() SYNC_LOSS
remain 988 len 2048 offset 992 u32 0xecf95000
This is an Ubuntu 14.04.2 LTS i686 (32-bit) system running kernel
3.13.0-53-generic. I don't see any "low-speed" warnings, and lsusb -t
shows each device (and their hubs) running at 480M.
ifconfig poe1:
poe1 Link encap:Ethernet HWaddr 00:50:f9:ec:4f:d8
inet addr:192.168.201.1 Bcast:192.168.201.255
Mask:255.255.255.0
inet6 addr: fe80::250:f9ff:feec:4fd8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:194441 errors:16649 dropped:15 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:267310738 (267.3 MB) TX bytes:10300282 (10.3 MB)
Without the "sanity test/synchronization" code:
poe1 Link encap:Ethernet HWaddr 00:50:f9:ec:4f:d8
inet addr:192.168.201.1 Bcast:192.168.201.255
Mask:255.255.255.0
inet6 addr: fe80::250:f9ff:feec:4fd8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:398910 errors:1 dropped:14 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:513363997 (513.3 MB) TX bytes:13154142 (13.1 MB)
>
> Regards,
> Dean
David
^ permalink raw reply
* Re: [PATCH v2 next-next 02/12] net: define gso types for IPx over IPv4 and IPv6
From: Tom Herbert @ 2016-05-06 20:43 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, Netdev, Kernel Team
In-Reply-To: <CAKgT0UdXWPqBN9SN45U80+fPOoukns38gZbR1B2abpCr1iDhcA@mail.gmail.com>
On Fri, May 6, 2016 at 1:34 PM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Fri, May 6, 2016 at 1:04 PM, Tom Herbert <tom@herbertland.com> wrote:
>> This patch defines two new GDO definitions SKB_GSO_IPXIP4 and
>> SKB_GSO_IPXIP6 along with corresponding NETIF_F_GSO_IPXIP4 and
>> NETIF_F_GSO_IPXIP6. These are used to described IP in IP
>> tunnel and what the outer protocol is. The inner protocol
>> can be deduced from other GSO types (e.g. SKB_GSO_TCPV4 and
>> SKB_GSO_TCPV6). The GSO types of SKB_GSO_IPIP and SKB_GSO_SIT
>> are removed (these are both instances of SKB_GSO_IPXIP4).
>> SKB_GSO_IPXIP6 will be used when support for GSO with IP
>> encapsulation over IPv6 is added.
>>
>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>> ---
>> drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 5 ++---
>> drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++--
>> drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +--
>> drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +--
>> drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 3 +--
>> drivers/net/ethernet/intel/i40evf/i40evf_main.c | 3 +--
>> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +--
>> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 3 +--
>> include/linux/netdev_features.h | 12 ++++++------
>> include/linux/netdevice.h | 4 ++--
>> include/linux/skbuff.h | 4 ++--
>> net/core/ethtool.c | 4 ++--
>> net/ipv4/af_inet.c | 2 +-
>> net/ipv4/ipip.c | 2 +-
>> net/ipv6/ip6_offload.c | 4 ++--
>> net/ipv6/sit.c | 4 ++--
>> net/netfilter/ipvs/ip_vs_xmit.c | 11 ++---------
>> 17 files changed, 30 insertions(+), 44 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
>> index d465bd7..0a5b770 100644
>> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
>> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
>> @@ -13259,12 +13259,11 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
>> NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
>> if (!chip_is_e1x) {
>> dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
>> - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT;
>> + NETIF_F_GSO_IPXIP4;
>> dev->hw_enc_features =
>> NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
>> NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
>> - NETIF_F_GSO_IPIP |
>> - NETIF_F_GSO_SIT |
>> + NETIF_F_GSO_IPXIP4 |
>> NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL;
>> }
>>
>> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
>> index fd85b6d..e449228 100644
>> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
>> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
>> @@ -6218,7 +6218,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>> dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
>> NETIF_F_TSO | NETIF_F_TSO6 |
>> NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
>> - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
>> + NETIF_F_GSO_IPXIP4 |
>> NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
>> NETIF_F_GSO_PARTIAL | NETIF_F_RXHASH |
>> NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO;
>> @@ -6228,7 +6228,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>> NETIF_F_TSO | NETIF_F_TSO6 |
>> NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
>> NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
>> - NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
>> + NETIF_F_GSO_IPXIP4;
>> NETIF_F_GSO_PARTIAL;
>> dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
>> NETIF_F_GSO_GRE_CSUM;
>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
>> index f6da6b7..c2a4c10 100644
>> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
>> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
>> @@ -9131,8 +9131,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
>> NETIF_F_TSO6 |
>> NETIF_F_GSO_GRE |
>> NETIF_F_GSO_GRE_CSUM |
>> - NETIF_F_GSO_IPIP |
>> - NETIF_F_GSO_SIT |
>> + NETIF_F_GSO_IPXIP4 |
>> NETIF_F_GSO_UDP_TUNNEL |
>> NETIF_F_GSO_UDP_TUNNEL_CSUM |
>> NETIF_F_GSO_PARTIAL |
>
> So for all the Intel drivers they support IPv6 and IPv4 outer header
> tunnel types. As such you can add SKB_GSO_IPXIP6 as well and you
> should be able to see offloads without any issues. This applies for
> all the Intel drivers below and igb which should have a patch
> available sometime soon as it is still in Jeff Kirsher's tree.
>
Can we do this in a follow up patch?
>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>> index 2765d7e..4a3d60a 100644
>> --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>> +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>> @@ -2302,8 +2302,7 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
>>
>> if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
>> SKB_GSO_GRE_CSUM |
>> - SKB_GSO_IPIP |
>> - SKB_GSO_SIT |
>> + SKB_GSO_IPXIP4 |
>> SKB_GSO_UDP_TUNNEL |
>> SKB_GSO_UDP_TUNNEL_CSUM)) {
>> if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
>> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
>> index ede8dfc..aaccb7e 100644
>> --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
>> +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
>> @@ -1567,8 +1567,7 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
>>
>> if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
>> SKB_GSO_GRE_CSUM |
>> - SKB_GSO_IPIP |
>> - SKB_GSO_SIT |
>> + SKB_GSO_IPXIP4 |
>> SKB_GSO_UDP_TUNNEL |
>> SKB_GSO_UDP_TUNNEL_CSUM)) {
>> if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
>> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
>> index 9f0bd7a..bfd0962 100644
>> --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
>> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
>> @@ -2241,8 +2241,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
>> NETIF_F_TSO6 |
>> NETIF_F_GSO_GRE |
>> NETIF_F_GSO_GRE_CSUM |
>> - NETIF_F_GSO_IPIP |
>> - NETIF_F_GSO_SIT |
>> + NETIF_F_GSO_IPXIP4 |
>> NETIF_F_GSO_UDP_TUNNEL |
>> NETIF_F_GSO_UDP_TUNNEL_CSUM |
>> NETIF_F_GSO_PARTIAL |
>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> index d08fbcf..28e3b5a 100644
>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> @@ -9482,8 +9482,7 @@ skip_sriov:
>>
>> #define IXGBE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>> NETIF_F_GSO_GRE_CSUM | \
>> - NETIF_F_GSO_IPIP | \
>> - NETIF_F_GSO_SIT | \
>> + NETIF_F_GSO_IPXIP4 | \
>> NETIF_F_GSO_UDP_TUNNEL | \
>> NETIF_F_GSO_UDP_TUNNEL_CSUM)
>>
>> diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
>> index 5e348b1..d86e511 100644
>> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
>> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
>> @@ -4062,8 +4062,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>>
>> #define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>> NETIF_F_GSO_GRE_CSUM | \
>> - NETIF_F_GSO_IPIP | \
>> - NETIF_F_GSO_SIT | \
>> + NETIF_F_GSO_IPXIP4 | \
>> NETIF_F_GSO_UDP_TUNNEL | \
>> NETIF_F_GSO_UDP_TUNNEL_CSUM)
>>
>
> So with GSO partial all of the igb/ixgbe parts should be able to
> support any tunnel type you can throw at it.
>
>> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
>> index bc87362..aa7b240 100644
>> --- a/include/linux/netdev_features.h
>> +++ b/include/linux/netdev_features.h
>> @@ -44,8 +44,8 @@ enum {
>> NETIF_F_FSO_BIT, /* ... FCoE segmentation */
>> NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */
>> NETIF_F_GSO_GRE_CSUM_BIT, /* ... GRE with csum with TSO */
>> - NETIF_F_GSO_IPIP_BIT, /* ... IPIP tunnel with TSO */
>> - NETIF_F_GSO_SIT_BIT, /* ... SIT tunnel with TSO */
>> + NETIF_F_GSO_IPXIP4_BIT, /* ... IP4 or IP6 over IP4 with TSO */
>> + NETIF_F_GSO_IPXIP6_BIT, /* ... IP4 or IP6 over IP6 with TSO */
>> NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
>> NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
>> NETIF_F_GSO_PARTIAL_BIT, /* ... Only segment inner-most L4
>> @@ -121,8 +121,8 @@ enum {
>> #define NETIF_F_RXALL __NETIF_F(RXALL)
>> #define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE)
>> #define NETIF_F_GSO_GRE_CSUM __NETIF_F(GSO_GRE_CSUM)
>> -#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP)
>> -#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
>> +#define NETIF_F_GSO_IPXIP4 __NETIF_F(GSO_IPXIP4)
>> +#define NETIF_F_GSO_IPXIP6 __NETIF_F(GSO_IPXIP6)
>> #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
>> #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
>> #define NETIF_F_TSO_MANGLEID __NETIF_F(TSO_MANGLEID)
>> @@ -200,8 +200,8 @@ enum {
>>
>> #define NETIF_F_GSO_ENCAP_ALL (NETIF_F_GSO_GRE | \
>> NETIF_F_GSO_GRE_CSUM | \
>> - NETIF_F_GSO_IPIP | \
>> - NETIF_F_GSO_SIT | \
>> + NETIF_F_GSO_IPXIP4 | \
>> + NETIF_F_GSO_IPXIP6 | \
>> NETIF_F_GSO_UDP_TUNNEL | \
>> NETIF_F_GSO_UDP_TUNNEL_CSUM)
>>
>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> index 63580e6..8b1eedc 100644
>> --- a/include/linux/netdevice.h
>> +++ b/include/linux/netdevice.h
>> @@ -4005,8 +4005,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>> BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
>> BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
>> BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
>> - BUILD_BUG_ON(SKB_GSO_IPIP != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
>> - BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
>> + BUILD_BUG_ON(SKB_GSO_IPXIP4 != (NETIF_F_GSO_IPXIP4 >> NETIF_F_GSO_SHIFT));
>> + BUILD_BUG_ON(SKB_GSO_IPXIP6 != (NETIF_F_GSO_IPXIP6 >> NETIF_F_GSO_SHIFT));
>> BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
>> BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
>> BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
>> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>> index c413c58..65968a9 100644
>> --- a/include/linux/skbuff.h
>> +++ b/include/linux/skbuff.h
>> @@ -471,9 +471,9 @@ enum {
>>
>> SKB_GSO_GRE_CSUM = 1 << 8,
>>
>> - SKB_GSO_IPIP = 1 << 9,
>> + SKB_GSO_IPXIP4 = 1 << 9,
>>
>> - SKB_GSO_SIT = 1 << 10,
>> + SKB_GSO_IPXIP6 = 1 << 10,
>>
>> SKB_GSO_UDP_TUNNEL = 1 << 11,
>>
>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>> index bdb4013..f403481 100644
>> --- a/net/core/ethtool.c
>> +++ b/net/core/ethtool.c
>> @@ -84,8 +84,8 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
>> [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
>> [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
>> [NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation",
>> - [NETIF_F_GSO_IPIP_BIT] = "tx-ipip-segmentation",
>> - [NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation",
>> + [NETIF_F_GSO_IPXIP4_BIT] = "tx-ipxip4-segmentation",
>> + [NETIF_F_GSO_IPXIP6_BIT] = "tx-ipxip6-segmentation",
>> [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
>> [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
>> [NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial",
>> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
>> index 7f08d45..25040b1 100644
>> --- a/net/ipv4/af_inet.c
>> +++ b/net/ipv4/af_inet.c
>> @@ -1483,7 +1483,7 @@ out_unlock:
>> static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
>> {
>> skb->encapsulation = 1;
>> - skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
>> + skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
>> return inet_gro_complete(skb, nhoff);
>> }
>>
>> diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
>> index 9282748..9783701 100644
>> --- a/net/ipv4/ipip.c
>> +++ b/net/ipv4/ipip.c
>> @@ -219,7 +219,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
>> if (unlikely(skb->protocol != htons(ETH_P_IP)))
>> goto tx_error;
>>
>> - if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
>> + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
>> goto tx_error;
>>
>> skb_set_inner_ipproto(skb, IPPROTO_IPIP);
>> diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
>> index 9ad743b..787e55f 100644
>> --- a/net/ipv6/ip6_offload.c
>> +++ b/net/ipv6/ip6_offload.c
>> @@ -86,7 +86,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
>> proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
>>
>> if (skb->encapsulation &&
>> - skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
>> + skb_shinfo(skb)->gso_type & (SKB_GSO_IPXIP4 | SKB_GSO_IPXIP6))
>> udpfrag = proto == IPPROTO_UDP && encap;
>> else
>> udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
>> @@ -294,7 +294,7 @@ out_unlock:
>> static int sit_gro_complete(struct sk_buff *skb, int nhoff)
>> {
>> skb->encapsulation = 1;
>> - skb_shinfo(skb)->gso_type |= SKB_GSO_SIT;
>> + skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
>> return ipv6_gro_complete(skb, nhoff);
>> }
>>
>> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
>> index a13d8c1..0a5a255 100644
>> --- a/net/ipv6/sit.c
>> +++ b/net/ipv6/sit.c
>> @@ -913,7 +913,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
>> goto tx_error;
>> }
>>
>> - if (iptunnel_handle_offloads(skb, SKB_GSO_SIT)) {
>> + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) {
>> ip_rt_put(rt);
>> goto tx_error;
>> }
>> @@ -1000,7 +1000,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
>> struct ip_tunnel *tunnel = netdev_priv(dev);
>> const struct iphdr *tiph = &tunnel->parms.iph;
>>
>> - if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
>> + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4))
>> goto tx_error;
>>
>> skb_set_inner_ipproto(skb, IPPROTO_IPIP);
>> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
>> index 6d19d2e..f646ef6 100644
>> --- a/net/netfilter/ipvs/ip_vs_xmit.c
>> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
>> @@ -932,16 +932,9 @@ error:
>>
>> static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
>> {
>> - if (encaps_af == AF_INET) {
>> - if (orig_af == AF_INET)
>> - return SKB_GSO_IPIP;
>> + if (encaps_af == AF_INET)
>> + return SKB_GSO_IPXIP4;
>>
>> - return SKB_GSO_SIT;
>> - }
>> -
>> - /* GSO: we need to provide proper SKB_GSO_ value for IPv6:
>> - * SKB_GSO_SIT/IPV6
>> - */
>
> I wouldn't delete this comment until you actually have resolved the
> issue of providing a proper GSO value for IPv6.
>
>> return 0;
>> }
>>
>> --
>> 2.8.0.rc2
>>
^ permalink raw reply
* Re: [PATCH] netdev: enc28j60 kernel panic fix.
From: Francois Romieu @ 2016-05-06 20:35 UTC (permalink / raw)
To: David Russell; +Cc: netdev
In-Reply-To: <CAEGHc+ymc3uY0C0WhjfEo5RoS-bQ7h7f6tbBQpAGEJ=D9rr6FA@mail.gmail.com>
(please don't top post)
David Russell <david@aprsworld.com> :
> I kind of thought my patch was at best incomplete. When you state
> this change silences the bug but does not fix it, what are the
> implications of systems running this patch? We have some production
> systems using this patch. They reboot daily, but have been solid.
If my assumption is right it should drop an extra packet here and there.
No leak.
However transmit errors + transmit packets should still match the number
of times the driver calls enc28j60_send_packet (you would have to cook
your own stat to check the latter though).
> In addition, if we sent you a pi and the ethernet controller and a
> small but reasonable sum of money for your labor, would you be able to
> properly fix it ?
I'd rather see you testing my crap. :o)
Pi as multi-core (the expected race needs several cores or a netconsole
style transmit from an irq/bh context) ?
> Short of that, do you have any recommendations on quick overviews of
> the networking stack in the kernel and then documentation on the
> various flags and such?
A tad bit too high-level a question... Plain ctags + printk for a start ?
Does the patch below make a difference ?
Takes longer to crash counts as a difference.
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 7066954..405fe3f 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -1170,7 +1170,8 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
enc28j60_dump_tsv(priv, "Tx Done", tsv);
}
enc28j60_tx_clear(ndev, err);
- locked_reg_bfclr(priv, EIR, EIR_TXIF);
+ locked_reg_bfclr(priv, EIR, EIR_TXIF | EIR_TXERIF);
+ intflags &= ~EIR_TXERIF;
}
/* TX Error handler */
if ((intflags & EIR_TXERIF) != 0) {
@@ -1190,6 +1191,7 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
nolock_reg_bfclr(priv, ECON1, ECON1_TXRST);
nolock_txfifo_init(priv, TXSTART_INIT, TXEND_INIT);
mutex_unlock(&priv->lock);
+ locked_reg_bfclr(priv, EIR, EIR_TXIF | EIR_TXERIF);
/* Transmit Late collision check for retransmit */
if (TSV_GETBIT(tsv, TSV_TXLATECOLLISION)) {
if (netif_msg_tx_err(priv))
@@ -1203,7 +1205,6 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
enc28j60_tx_clear(ndev, true);
} else
enc28j60_tx_clear(ndev, true);
- locked_reg_bfclr(priv, EIR, EIR_TXERIF);
}
/* RX Error handler */
if ((intflags & EIR_RXERIF) != 0) {
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox