* [PATCH 1/1] ax25: Fix segfault after sock connection timeout
From: Basil Gunn @ 2017-01-14 20:18 UTC (permalink / raw)
To: Joerg Reuter, Ralf Baechle, David S. Miller, linux-hams, netdev,
linux-kernel
Cc: stable, Jeremy McDermond, f6bvp
The ax.25 socket connection timed out & the sock struct has been
previously taken down ie. sock struct is now a NULL pointer. Checking
the sock_flag causes the segfault. Check if the socket struct pointer
is NULL before checking sock_flag. This segfault is seen in
timed out netrom connections.
Please submit to -stable.
Signed-off-by: Basil Gunn <basil@pacabunga.com>
---
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 4855d18..038b109 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -264,7 +264,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
{
ax25_clear_queues(ax25);
- if (!sock_flag(ax25->sk, SOCK_DESTROY))
+ if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
ax25_stop_heartbeat(ax25);
ax25_stop_t1timer(ax25);
ax25_stop_t2timer(ax25);
^ permalink raw reply related
* [PATCH net-next v3 00/10] net: dsa: Support for pdata in dsa2
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Florian Fainelli, Jason Cooper, Vivien Didelot,
gregkh, Russell King, open list, Gregory Clement, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, Sebastian Hesselbarth
Hi all,
This is not exactly new, and was sent before, although back then, I did not
have an user of the pre-declared MDIO board information, but now we do. Note
that I have additional changes queued up to have b53 register platform data for
MIPS bcm47xx and bcm63xx.
Yes I know that we should have the Orion platforms eventually be converted to
Device Tree, but until that happens, I don't want any remaining users of the
old "dsa" platform device (hence the previous DTS submissions for ARM/mvebu)
and, there will be platforms out there that most likely won't never see DT
coming their way (BCM47xx is almost 100% sure, BCM63xx maybe not in a distant
future).
We would probably want the whole series to be merged via David Miller's tree
to simplify things.
Greg, can you Ack/Nack patch 5 since it touched the core LDD?
Vivien, since some patches did change, I did not apply your Tested-by tag
to all patches.
Thanks!
Changes in v3:
- Tested EPROBE_DEFER from a mockup MDIO/DSA switch driver and everything
is fine, once the driver finally probes we have access to platform data
as expected
- added comment above dsa_port_is_valid() that port->name is mandatory
for platform data cases
- added an extra check in dsa_parse_member() for a NULL pdata pointer
- fixed a bunch of checkpatch errors and warnings
Changes in v2:
- Rebased against latest net-next/master
- Moved dev_find_class() to device_find_class() into drivers/base/core.c
- Moved dev_to_net_device into net/core/dev.c
- Utilize dsa_chip_data directly instead of dsa_platform_data
- Augmented dsa_chip_data to be multi-CPU port ready
Changes from last submission (few months back):
- rebased against latest net-next
- do not introduce dsa2_platform_data which was overkill and was meant to
allow us to do exaclty the same things with platform data and Device Tree
we use the existing dsa_platform_data instead
- properly register MDIO devices when the MDIO bus is registered and associate
platform_data with them
- add a change to the Orion platform code to demonstrate how this can be used
Thank you
Florian Fainelli (10):
net: dsa: Pass device pointer to dsa_register_switch
net: dsa: Make most functions take a dsa_port argument
net: dsa: Suffix function manipulating device_node with _dn
net: dsa: Move ports assignment closer to error checking
drivers: base: Add device_find_class()
net: dsa: Migrate to device_find_class()
net: Relocate dev_to_net_device() into core
net: dsa: Add support for platform data
net: phy: Allow pre-declaration of MDIO devices
ARM: orion: Register DSA switch as a MDIO device
arch/arm/mach-orion5x/common.c | 2 +-
arch/arm/mach-orion5x/common.h | 4 +-
arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c | 7 +-
arch/arm/mach-orion5x/rd88f5181l-ge-setup.c | 7 +-
arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c | 7 +-
arch/arm/mach-orion5x/wnr854t-setup.c | 2 +-
arch/arm/mach-orion5x/wrt350n-v2-setup.c | 7 +-
arch/arm/plat-orion/common.c | 25 +++-
arch/arm/plat-orion/include/plat/common.h | 4 +-
drivers/base/core.c | 19 +++
drivers/net/dsa/b53/b53_common.c | 2 +-
drivers/net/dsa/mv88e6xxx/chip.c | 11 +-
drivers/net/dsa/qca8k.c | 2 +-
drivers/net/phy/Makefile | 3 +-
drivers/net/phy/mdio-boardinfo.c | 86 +++++++++++++
drivers/net/phy/mdio-boardinfo.h | 19 +++
drivers/net/phy/mdio_bus.c | 4 +
drivers/net/phy/mdio_device.c | 11 ++
include/linux/device.h | 1 +
include/linux/mdio.h | 3 +
include/linux/mod_devicetable.h | 1 +
include/linux/netdevice.h | 2 +
include/linux/phy.h | 19 +++
include/net/dsa.h | 8 +-
net/core/dev.c | 19 +++
net/dsa/dsa.c | 53 ++------
net/dsa/dsa2.c | 174 +++++++++++++++++++--------
net/dsa/dsa_priv.h | 4 +-
28 files changed, 365 insertions(+), 141 deletions(-)
create mode 100644 drivers/net/phy/mdio-boardinfo.c
create mode 100644 drivers/net/phy/mdio-boardinfo.h
--
2.9.3
^ permalink raw reply
* [PATCH net-next v3 01/10] net: dsa: Pass device pointer to dsa_register_switch
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
In preparation for allowing dsa_register_switch() to be supplied with
device/platform data, pass down a struct device pointer instead of a
struct device_node.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 2 +-
drivers/net/dsa/mv88e6xxx/chip.c | 11 ++++++-----
drivers/net/dsa/qca8k.c | 2 +-
include/net/dsa.h | 2 +-
net/dsa/dsa2.c | 7 ++++---
5 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 5102a3701a1a..7179eed9ee6d 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1882,7 +1882,7 @@ int b53_switch_register(struct b53_device *dev)
pr_info("found switch: %s, rev %i\n", dev->name, dev->core_rev);
- return dsa_register_switch(dev->ds, dev->ds->dev->of_node);
+ return dsa_register_switch(dev->ds, dev->ds->dev);
}
EXPORT_SYMBOL(b53_switch_register);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 987b2dbbd35a..3238a4752b98 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -4421,8 +4421,7 @@ static struct dsa_switch_driver mv88e6xxx_switch_drv = {
.ops = &mv88e6xxx_switch_ops,
};
-static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip,
- struct device_node *np)
+static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
{
struct device *dev = chip->dev;
struct dsa_switch *ds;
@@ -4437,7 +4436,7 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip,
dev_set_drvdata(dev, ds);
- return dsa_register_switch(ds, np);
+ return dsa_register_switch(ds, dev);
}
static void mv88e6xxx_unregister_switch(struct mv88e6xxx_chip *chip)
@@ -4521,9 +4520,11 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
if (err)
goto out_g2_irq;
- err = mv88e6xxx_register_switch(chip, np);
- if (err)
+ err = mv88e6xxx_register_switch(chip);
+ if (err) {
+ mv88e6xxx_mdio_unregister(chip);
goto out_mdio;
+ }
return 0;
diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
index 54d270d59eb0..c084aa484d2b 100644
--- a/drivers/net/dsa/qca8k.c
+++ b/drivers/net/dsa/qca8k.c
@@ -964,7 +964,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
mutex_init(&priv->reg_mutex);
dev_set_drvdata(&mdiodev->dev, priv);
- return dsa_register_switch(priv->ds, priv->ds->dev->of_node);
+ return dsa_register_switch(priv->ds, &mdiodev->dev);
}
static void
diff --git a/include/net/dsa.h b/include/net/dsa.h
index b94d1f2ef912..16a502a6c26a 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -403,7 +403,7 @@ static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
}
void dsa_unregister_switch(struct dsa_switch *ds);
-int dsa_register_switch(struct dsa_switch *ds, struct device_node *np);
+int dsa_register_switch(struct dsa_switch *ds, struct device *dev);
#ifdef CONFIG_PM_SLEEP
int dsa_switch_suspend(struct dsa_switch *ds);
int dsa_switch_resume(struct dsa_switch *ds);
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 42a41d84053c..4170f7ea8e28 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -579,8 +579,9 @@ static struct device_node *dsa_get_ports(struct dsa_switch *ds,
return ports;
}
-static int _dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
+static int _dsa_register_switch(struct dsa_switch *ds, struct device *dev)
{
+ struct device_node *np = dev->of_node;
struct device_node *ports = dsa_get_ports(ds, np);
struct dsa_switch_tree *dst;
u32 tree, index;
@@ -660,12 +661,12 @@ static int _dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
return err;
}
-int dsa_register_switch(struct dsa_switch *ds, struct device_node *np)
+int dsa_register_switch(struct dsa_switch *ds, struct device *dev)
{
int err;
mutex_lock(&dsa2_mutex);
- err = _dsa_register_switch(ds, np);
+ err = _dsa_register_switch(ds, dev);
mutex_unlock(&dsa2_mutex);
return err;
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 02/10] net: dsa: Make most functions take a dsa_port argument
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Florian Fainelli, Jason Cooper, Vivien Didelot,
gregkh, Russell King, open list, Gregory Clement, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, Sebastian Hesselbarth
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
In preparation for allowing platform data, and therefore no valid
device_node pointer, make most DSA functions takes a pointer to a
dsa_port structure whenever possible. While at it, introduce a
dsa_port_is_valid() helper function which checks whether port->dn is
NULL or not at the moment.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa.c | 15 ++++++++------
net/dsa/dsa2.c | 61 +++++++++++++++++++++++++++++-------------------------
net/dsa/dsa_priv.h | 4 ++--
3 files changed, 44 insertions(+), 36 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index fd532487dfdf..2306d1b87c83 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -110,8 +110,9 @@ dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
/* basic switch operations **************************************************/
int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
- struct device_node *port_dn, int port)
+ struct dsa_port *dport, int port)
{
+ struct device_node *port_dn = dport->dn;
struct phy_device *phydev;
int ret, mode;
@@ -141,15 +142,15 @@ int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
static int dsa_cpu_dsa_setups(struct dsa_switch *ds, struct device *dev)
{
- struct device_node *port_dn;
+ struct dsa_port *dport;
int ret, port;
for (port = 0; port < DSA_MAX_PORTS; port++) {
if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
continue;
- port_dn = ds->ports[port].dn;
- ret = dsa_cpu_dsa_setup(ds, dev, port_dn, port);
+ dport = &ds->ports[port];
+ ret = dsa_cpu_dsa_setup(ds, dev, dport, port);
if (ret)
return ret;
}
@@ -366,8 +367,10 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
return ds;
}
-void dsa_cpu_dsa_destroy(struct device_node *port_dn)
+void dsa_cpu_dsa_destroy(struct dsa_port *port)
{
+ struct device_node *port_dn = port->dn;
+
if (of_phy_is_fixed_link(port_dn))
of_phy_deregister_fixed_link(port_dn);
}
@@ -393,7 +396,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
for (port = 0; port < DSA_MAX_PORTS; port++) {
if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
continue;
- dsa_cpu_dsa_destroy(ds->ports[port].dn);
+ dsa_cpu_dsa_destroy(&ds->ports[port]);
/* Clearing a bit which is not set does no harm */
ds->cpu_port_mask |= ~(1 << port);
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 4170f7ea8e28..6e3675220fef 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -79,14 +79,19 @@ static void dsa_dst_del_ds(struct dsa_switch_tree *dst,
kref_put(&dst->refcount, dsa_free_dst);
}
-static bool dsa_port_is_dsa(struct device_node *port)
+static bool dsa_port_is_valid(struct dsa_port *port)
{
- return !!of_parse_phandle(port, "link", 0);
+ return !!port->dn;
}
-static bool dsa_port_is_cpu(struct device_node *port)
+static bool dsa_port_is_dsa(struct dsa_port *port)
{
- return !!of_parse_phandle(port, "ethernet", 0);
+ return !!of_parse_phandle(port->dn, "link", 0);
+}
+
+static bool dsa_port_is_cpu(struct dsa_port *port)
+{
+ return !!of_parse_phandle(port->dn, "ethernet", 0);
}
static bool dsa_ds_find_port(struct dsa_switch *ds,
@@ -120,7 +125,7 @@ static struct dsa_switch *dsa_dst_find_port(struct dsa_switch_tree *dst,
static int dsa_port_complete(struct dsa_switch_tree *dst,
struct dsa_switch *src_ds,
- struct device_node *port,
+ struct dsa_port *port,
u32 src_port)
{
struct device_node *link;
@@ -128,7 +133,7 @@ static int dsa_port_complete(struct dsa_switch_tree *dst,
struct dsa_switch *dst_ds;
for (index = 0;; index++) {
- link = of_parse_phandle(port, "link", index);
+ link = of_parse_phandle(port->dn, "link", index);
if (!link)
break;
@@ -151,13 +156,13 @@ static int dsa_port_complete(struct dsa_switch_tree *dst,
*/
static int dsa_ds_complete(struct dsa_switch_tree *dst, struct dsa_switch *ds)
{
- struct device_node *port;
+ struct dsa_port *port;
u32 index;
int err;
for (index = 0; index < DSA_MAX_PORTS; index++) {
- port = ds->ports[index].dn;
- if (!port)
+ port = &ds->ports[index];
+ if (!dsa_port_is_valid(port))
continue;
if (!dsa_port_is_dsa(port))
@@ -197,7 +202,7 @@ static int dsa_dst_complete(struct dsa_switch_tree *dst)
return 0;
}
-static int dsa_dsa_port_apply(struct device_node *port, u32 index,
+static int dsa_dsa_port_apply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
int err;
@@ -212,13 +217,13 @@ static int dsa_dsa_port_apply(struct device_node *port, u32 index,
return 0;
}
-static void dsa_dsa_port_unapply(struct device_node *port, u32 index,
+static void dsa_dsa_port_unapply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
dsa_cpu_dsa_destroy(port);
}
-static int dsa_cpu_port_apply(struct device_node *port, u32 index,
+static int dsa_cpu_port_apply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
int err;
@@ -235,7 +240,7 @@ static int dsa_cpu_port_apply(struct device_node *port, u32 index,
return 0;
}
-static void dsa_cpu_port_unapply(struct device_node *port, u32 index,
+static void dsa_cpu_port_unapply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
dsa_cpu_dsa_destroy(port);
@@ -243,13 +248,13 @@ static void dsa_cpu_port_unapply(struct device_node *port, u32 index,
}
-static int dsa_user_port_apply(struct device_node *port, u32 index,
+static int dsa_user_port_apply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
const char *name;
int err;
- name = of_get_property(port, "label", NULL);
+ name = of_get_property(port->dn, "label", NULL);
if (!name)
name = "eth%d";
@@ -263,7 +268,7 @@ static int dsa_user_port_apply(struct device_node *port, u32 index,
return 0;
}
-static void dsa_user_port_unapply(struct device_node *port, u32 index,
+static void dsa_user_port_unapply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
if (ds->ports[index].netdev) {
@@ -275,7 +280,7 @@ static void dsa_user_port_unapply(struct device_node *port, u32 index,
static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
{
- struct device_node *port;
+ struct dsa_port *port;
u32 index;
int err;
@@ -309,8 +314,8 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
}
for (index = 0; index < DSA_MAX_PORTS; index++) {
- port = ds->ports[index].dn;
- if (!port)
+ port = &ds->ports[index];
+ if (!dsa_port_is_valid(port))
continue;
if (dsa_port_is_dsa(port)) {
@@ -337,12 +342,12 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
static void dsa_ds_unapply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
{
- struct device_node *port;
+ struct dsa_port *port;
u32 index;
for (index = 0; index < DSA_MAX_PORTS; index++) {
- port = ds->ports[index].dn;
- if (!port)
+ port = &ds->ports[index];
+ if (!dsa_port_is_valid(port))
continue;
if (dsa_port_is_dsa(port)) {
@@ -426,7 +431,7 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
dst->applied = false;
}
-static int dsa_cpu_parse(struct device_node *port, u32 index,
+static int dsa_cpu_parse(struct dsa_port *port, u32 index,
struct dsa_switch_tree *dst,
struct dsa_switch *ds)
{
@@ -434,7 +439,7 @@ static int dsa_cpu_parse(struct device_node *port, u32 index,
struct net_device *ethernet_dev;
struct device_node *ethernet;
- ethernet = of_parse_phandle(port, "ethernet", 0);
+ ethernet = of_parse_phandle(port->dn, "ethernet", 0);
if (!ethernet)
return -EINVAL;
@@ -467,13 +472,13 @@ static int dsa_cpu_parse(struct device_node *port, u32 index,
static int dsa_ds_parse(struct dsa_switch_tree *dst, struct dsa_switch *ds)
{
- struct device_node *port;
+ struct dsa_port *port;
u32 index;
int err;
for (index = 0; index < DSA_MAX_PORTS; index++) {
- port = ds->ports[index].dn;
- if (!port)
+ port = &ds->ports[index];
+ if (!dsa_port_is_valid(port))
continue;
if (dsa_port_is_cpu(port)) {
@@ -534,7 +539,7 @@ static int dsa_parse_ports_dn(struct device_node *ports, struct dsa_switch *ds)
* to have access to a correct value, just like what
* net/dsa/dsa.c::dsa_switch_setup_one does.
*/
- if (!dsa_port_is_cpu(port))
+ if (!dsa_port_is_cpu(&ds->ports[reg]))
ds->enabled_port_mask |= 1 << reg;
}
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 7e3385ec73f4..a015ec97c289 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -50,8 +50,8 @@ struct dsa_slave_priv {
/* dsa.c */
int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
- struct device_node *port_dn, int port);
-void dsa_cpu_dsa_destroy(struct device_node *port_dn);
+ struct dsa_port *dport, int port);
+void dsa_cpu_dsa_destroy(struct dsa_port *dport);
const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds);
void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 03/10] net: dsa: Suffix function manipulating device_node with _dn
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Make it clear that these functions take a device_node structure pointer
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa2.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 6e3675220fef..04ab62251fe3 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -94,8 +94,8 @@ static bool dsa_port_is_cpu(struct dsa_port *port)
return !!of_parse_phandle(port->dn, "ethernet", 0);
}
-static bool dsa_ds_find_port(struct dsa_switch *ds,
- struct device_node *port)
+static bool dsa_ds_find_port_dn(struct dsa_switch *ds,
+ struct device_node *port)
{
u32 index;
@@ -105,8 +105,8 @@ static bool dsa_ds_find_port(struct dsa_switch *ds,
return false;
}
-static struct dsa_switch *dsa_dst_find_port(struct dsa_switch_tree *dst,
- struct device_node *port)
+static struct dsa_switch *dsa_dst_find_port_dn(struct dsa_switch_tree *dst,
+ struct device_node *port)
{
struct dsa_switch *ds;
u32 index;
@@ -116,7 +116,7 @@ static struct dsa_switch *dsa_dst_find_port(struct dsa_switch_tree *dst,
if (!ds)
continue;
- if (dsa_ds_find_port(ds, port))
+ if (dsa_ds_find_port_dn(ds, port))
return ds;
}
@@ -137,7 +137,7 @@ static int dsa_port_complete(struct dsa_switch_tree *dst,
if (!link)
break;
- dst_ds = dsa_dst_find_port(dst, link);
+ dst_ds = dsa_dst_find_port_dn(dst, link);
of_node_put(link);
if (!dst_ds)
@@ -546,7 +546,7 @@ static int dsa_parse_ports_dn(struct device_node *ports, struct dsa_switch *ds)
return 0;
}
-static int dsa_parse_member(struct device_node *np, u32 *tree, u32 *index)
+static int dsa_parse_member_dn(struct device_node *np, u32 *tree, u32 *index)
{
int err;
@@ -592,7 +592,7 @@ static int _dsa_register_switch(struct dsa_switch *ds, struct device *dev)
u32 tree, index;
int i, err;
- err = dsa_parse_member(np, &tree, &index);
+ err = dsa_parse_member_dn(np, &tree, &index);
if (err)
return err;
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 04/10] net: dsa: Move ports assignment closer to error checking
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Florian Fainelli, Jason Cooper, Vivien Didelot,
gregkh, Russell King, open list, Gregory Clement, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, Sebastian Hesselbarth
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Move the assignment of ports in _dsa_register_switch() closer to where
it is checked, no functional change. Re-order declarations to be
preserve the inverted christmas tree style.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa2.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 04ab62251fe3..cd91070b5467 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -587,8 +587,8 @@ static struct device_node *dsa_get_ports(struct dsa_switch *ds,
static int _dsa_register_switch(struct dsa_switch *ds, struct device *dev)
{
struct device_node *np = dev->of_node;
- struct device_node *ports = dsa_get_ports(ds, np);
struct dsa_switch_tree *dst;
+ struct device_node *ports;
u32 tree, index;
int i, err;
@@ -596,6 +596,7 @@ static int _dsa_register_switch(struct dsa_switch *ds, struct device *dev)
if (err)
return err;
+ ports = dsa_get_ports(ds, np);
if (IS_ERR(ports))
return PTR_ERR(ports);
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 06/10] net: dsa: Migrate to device_find_class()
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Now that the base device driver code provides an identical
implementation of dev_find_class() utilize device_find_class() instead
of our own version of it.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa.c | 22 ++--------------------
1 file changed, 2 insertions(+), 20 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 2306d1b87c83..77fa4c4f5828 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -455,29 +455,11 @@ EXPORT_SYMBOL_GPL(dsa_switch_resume);
#endif
/* platform driver init and cleanup *****************************************/
-static int dev_is_class(struct device *dev, void *class)
-{
- if (dev->class != NULL && !strcmp(dev->class->name, class))
- return 1;
-
- return 0;
-}
-
-static struct device *dev_find_class(struct device *parent, char *class)
-{
- if (dev_is_class(parent, class)) {
- get_device(parent);
- return parent;
- }
-
- return device_find_child(parent, class, dev_is_class);
-}
-
struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev)
{
struct device *d;
- d = dev_find_class(dev, "mdio_bus");
+ d = device_find_class(dev, "mdio_bus");
if (d != NULL) {
struct mii_bus *bus;
@@ -495,7 +477,7 @@ static struct net_device *dev_to_net_device(struct device *dev)
{
struct device *d;
- d = dev_find_class(dev, "net");
+ d = device_find_class(dev, "net");
if (d != NULL) {
struct net_device *nd;
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 07/10] net: Relocate dev_to_net_device() into core
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
dev_to_net_device() is moved from net/dsa/dsa.c to net/core/dev.c since
it going to be used by net/dsa/dsa2.c and the namespace of the function
justifies making it available to other users potentially.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/linux/netdevice.h | 2 ++
net/core/dev.c | 19 +++++++++++++++++++
net/dsa/dsa.c | 18 ------------------
3 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 97ae0ac513ee..6d021c37b774 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4390,4 +4390,6 @@ do { \
#define PTYPE_HASH_SIZE (16)
#define PTYPE_HASH_MASK (PTYPE_HASH_SIZE - 1)
+struct net_device *dev_to_net_device(struct device *dev);
+
#endif /* _LINUX_NETDEVICE_H */
diff --git a/net/core/dev.c b/net/core/dev.c
index ad5959e56116..7547e2ccc06b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -8128,6 +8128,25 @@ const char *netdev_drivername(const struct net_device *dev)
return empty;
}
+struct net_device *dev_to_net_device(struct device *dev)
+{
+ struct device *d;
+
+ d = device_find_class(dev, "net");
+ if (d) {
+ struct net_device *nd;
+
+ nd = to_net_dev(d);
+ dev_hold(nd);
+ put_device(d);
+
+ return nd;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(dev_to_net_device);
+
static void __netdev_printk(const char *level, const struct net_device *dev,
struct va_format *vaf)
{
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 77fa4c4f5828..6c264f92fec5 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -473,24 +473,6 @@ struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev)
}
EXPORT_SYMBOL_GPL(dsa_host_dev_to_mii_bus);
-static struct net_device *dev_to_net_device(struct device *dev)
-{
- struct device *d;
-
- d = device_find_class(dev, "net");
- if (d != NULL) {
- struct net_device *nd;
-
- nd = to_net_dev(d);
- dev_hold(nd);
- put_device(d);
-
- return nd;
- }
-
- return NULL;
-}
-
#ifdef CONFIG_OF
static int dsa_of_setup_routing_table(struct dsa_platform_data *pd,
struct dsa_chip_data *cd,
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 08/10] net: dsa: Add support for platform data
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Allow drivers to use the new DSA API with platform data. Most of the
code in net/dsa/dsa2.c does not rely so much on device_nodes and can get
the same information from platform_data instead.
We purposely do not support distributed configurations with platform
data, so drivers should be providing a pointer to a 'struct
dsa_chip_data' structure if they wish to communicate per-port layout.
Multiple CPUs port could potentially be supported and dsa_chip_data is
extended to receive up to one reference to an upstream network device
per port described by a dsa_chip_data structure.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/net/dsa.h | 6 ++++
net/dsa/dsa2.c | 101 ++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 89 insertions(+), 18 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 16a502a6c26a..491008792e4d 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -42,6 +42,11 @@ struct dsa_chip_data {
struct device *host_dev;
int sw_addr;
+ /*
+ * Reference to network devices
+ */
+ struct device *netdev[DSA_MAX_PORTS];
+
/* set to size of eeprom if supported by the switch */
int eeprom_len;
@@ -140,6 +145,7 @@ struct dsa_switch_tree {
};
struct dsa_port {
+ const char *name;
struct net_device *netdev;
struct device_node *dn;
unsigned int ageing_time;
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index cd91070b5467..598229b02fd3 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -79,19 +79,28 @@ static void dsa_dst_del_ds(struct dsa_switch_tree *dst,
kref_put(&dst->refcount, dsa_free_dst);
}
+/* For platform data configurations, we need to have a valid name argument to
+ * differentiate a disabled port from an enabled one
+ */
static bool dsa_port_is_valid(struct dsa_port *port)
{
- return !!port->dn;
+ return !!(port->dn || port->name);
}
static bool dsa_port_is_dsa(struct dsa_port *port)
{
- return !!of_parse_phandle(port->dn, "link", 0);
+ if (port->name && !strcmp(port->name, "dsa"))
+ return true;
+ else
+ return !!of_parse_phandle(port->dn, "link", 0);
}
static bool dsa_port_is_cpu(struct dsa_port *port)
{
- return !!of_parse_phandle(port->dn, "ethernet", 0);
+ if (port->name && !strcmp(port->name, "cpu"))
+ return true;
+ else
+ return !!of_parse_phandle(port->dn, "ethernet", 0);
}
static bool dsa_ds_find_port_dn(struct dsa_switch *ds,
@@ -251,10 +260,11 @@ static void dsa_cpu_port_unapply(struct dsa_port *port, u32 index,
static int dsa_user_port_apply(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
- const char *name;
+ const char *name = port->name;
int err;
- name = of_get_property(port->dn, "label", NULL);
+ if (port->dn)
+ name = of_get_property(port->dn, "label", NULL);
if (!name)
name = "eth%d";
@@ -439,11 +449,15 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
struct net_device *ethernet_dev;
struct device_node *ethernet;
- ethernet = of_parse_phandle(port->dn, "ethernet", 0);
- if (!ethernet)
- return -EINVAL;
+ if (port->dn) {
+ ethernet = of_parse_phandle(port->dn, "ethernet", 0);
+ if (!ethernet)
+ return -EINVAL;
+ ethernet_dev = of_find_net_device_by_node(ethernet);
+ } else {
+ ethernet_dev = dev_to_net_device(ds->cd->netdev[index]);
+ }
- ethernet_dev = of_find_net_device_by_node(ethernet);
if (!ethernet_dev)
return -EPROBE_DEFER;
@@ -546,6 +560,33 @@ static int dsa_parse_ports_dn(struct device_node *ports, struct dsa_switch *ds)
return 0;
}
+static int dsa_parse_ports(struct dsa_chip_data *cd, struct dsa_switch *ds)
+{
+ bool valid_name_found = false;
+ unsigned int i;
+
+ for (i = 0; i < DSA_MAX_PORTS; i++) {
+ if (!cd->port_names[i])
+ continue;
+
+ ds->ports[i].name = cd->port_names[i];
+
+ /* Initialize enabled_port_mask now for drv->setup()
+ * to have access to a correct value, just like what
+ * net/dsa/dsa.c::dsa_switch_setup_one does.
+ */
+ if (!dsa_port_is_cpu(&ds->ports[i]))
+ ds->enabled_port_mask |= 1 << i;
+
+ valid_name_found = true;
+ }
+
+ if (!valid_name_found && i == DSA_MAX_PORTS)
+ return -EINVAL;
+
+ return 0;
+}
+
static int dsa_parse_member_dn(struct device_node *np, u32 *tree, u32 *index)
{
int err;
@@ -570,6 +611,18 @@ static int dsa_parse_member_dn(struct device_node *np, u32 *tree, u32 *index)
return 0;
}
+static int dsa_parse_member(struct dsa_chip_data *pd, u32 *tree, u32 *index)
+{
+ if (!pd)
+ return -ENODEV;
+
+ /* We do not support complex trees with dsa_chip_data */
+ *tree = 0;
+ *index = 0;
+
+ return 0;
+}
+
static struct device_node *dsa_get_ports(struct dsa_switch *ds,
struct device_node *np)
{
@@ -586,23 +639,34 @@ static struct device_node *dsa_get_ports(struct dsa_switch *ds,
static int _dsa_register_switch(struct dsa_switch *ds, struct device *dev)
{
+ struct dsa_chip_data *pdata = dev->platform_data;
struct device_node *np = dev->of_node;
struct dsa_switch_tree *dst;
struct device_node *ports;
u32 tree, index;
int i, err;
- err = dsa_parse_member_dn(np, &tree, &index);
- if (err)
- return err;
+ if (np) {
+ err = dsa_parse_member_dn(np, &tree, &index);
+ if (err)
+ return err;
- ports = dsa_get_ports(ds, np);
- if (IS_ERR(ports))
- return PTR_ERR(ports);
+ ports = dsa_get_ports(ds, np);
+ if (IS_ERR(ports))
+ return PTR_ERR(ports);
- err = dsa_parse_ports_dn(ports, ds);
- if (err)
- return err;
+ err = dsa_parse_ports_dn(ports, ds);
+ if (err)
+ return err;
+ } else {
+ err = dsa_parse_member(pdata, &tree, &index);
+ if (err)
+ return err;
+
+ err = dsa_parse_ports(pdata, ds);
+ if (err)
+ return err;
+ }
dst = dsa_get_dst(tree);
if (!dst) {
@@ -618,6 +682,7 @@ static int _dsa_register_switch(struct dsa_switch *ds, struct device *dev)
ds->dst = dst;
ds->index = index;
+ ds->cd = pdata;
/* Initialize the routing table */
for (i = 0; i < DSA_MAX_SWITCHES; ++i)
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 09/10] net: phy: Allow pre-declaration of MDIO devices
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Allow board support code to collect pre-declarations for MDIO devices by
registering them with mdiobus_register_board_info(). SPI and I2C buses
have a similar feature, we were missing this for MDIO devices, but this
is particularly useful for e.g: MDIO-connected switches which need to
provide their port layout (often board-specific) to a MDIO Ethernet
switch driver.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/Makefile | 3 +-
drivers/net/phy/mdio-boardinfo.c | 86 ++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/mdio-boardinfo.h | 19 +++++++++
drivers/net/phy/mdio_bus.c | 4 ++
drivers/net/phy/mdio_device.c | 11 +++++
include/linux/mdio.h | 3 ++
include/linux/mod_devicetable.h | 1 +
include/linux/phy.h | 19 +++++++++
8 files changed, 145 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/phy/mdio-boardinfo.c
create mode 100644 drivers/net/phy/mdio-boardinfo.h
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 356859ac7c18..407b0b601ea8 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,6 +1,7 @@
# Makefile for Linux PHY drivers and MDIO bus drivers
-libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o
+libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o \
+ mdio-boardinfo.o
libphy-$(CONFIG_SWPHY) += swphy.o
libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_led_triggers.o
diff --git a/drivers/net/phy/mdio-boardinfo.c b/drivers/net/phy/mdio-boardinfo.c
new file mode 100644
index 000000000000..6b988f77da08
--- /dev/null
+++ b/drivers/net/phy/mdio-boardinfo.c
@@ -0,0 +1,86 @@
+/*
+ * mdio-boardinfo - Collect pre-declarations for MDIO devices
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+
+#include "mdio-boardinfo.h"
+
+static LIST_HEAD(mdio_board_list);
+static DEFINE_MUTEX(mdio_board_lock);
+
+/**
+ * mdiobus_setup_mdiodev_from_board_info - create and setup MDIO devices
+ * from pre-collected board specific MDIO information
+ * @mdiodev: MDIO device pointer
+ * Context: can sleep
+ */
+void mdiobus_setup_mdiodev_from_board_info(struct mii_bus *bus)
+{
+ struct mdio_board_entry *be;
+ struct mdio_device *mdiodev;
+ struct mdio_board_info *bi;
+ int ret;
+
+ mutex_lock(&mdio_board_lock);
+ list_for_each_entry(be, &mdio_board_list, list) {
+ bi = &be->board_info;
+
+ if (strcmp(bus->id, bi->bus_id))
+ continue;
+
+ mdiodev = mdio_device_create(bus, bi->mdio_addr);
+ if (IS_ERR(mdiodev))
+ continue;
+
+ strncpy(mdiodev->modalias, bi->modalias,
+ sizeof(mdiodev->modalias));
+ mdiodev->bus_match = mdio_device_bus_match;
+ mdiodev->dev.platform_data = (void *)bi->platform_data;
+
+ ret = mdio_device_register(mdiodev);
+ if (ret) {
+ mdio_device_free(mdiodev);
+ continue;
+ }
+ }
+ mutex_unlock(&mdio_board_lock);
+}
+
+/**
+ * mdio_register_board_info - register MDIO devices for a given board
+ * @info: array of devices descriptors
+ * @n: number of descriptors provided
+ * Context: can sleep
+ *
+ * The board info passed can be marked with __initdata but be pointers
+ * such as platform_data etc. are copied as-is
+ */
+int mdiobus_register_board_info(const struct mdio_board_info *info,
+ unsigned int n)
+{
+ struct mdio_board_entry *be;
+ unsigned int i;
+
+ be = kcalloc(n, sizeof(*be), GFP_KERNEL);
+ if (!be)
+ return -ENOMEM;
+
+ for (i = 0; i < n; i++, be++, info++) {
+ memcpy(&be->board_info, info, sizeof(*info));
+ mutex_lock(&mdio_board_lock);
+ list_add_tail(&be->list, &mdio_board_list);
+ mutex_unlock(&mdio_board_lock);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/phy/mdio-boardinfo.h b/drivers/net/phy/mdio-boardinfo.h
new file mode 100644
index 000000000000..00f98163e90e
--- /dev/null
+++ b/drivers/net/phy/mdio-boardinfo.h
@@ -0,0 +1,19 @@
+/*
+ * mdio-boardinfo.h - board info interface internal to the mdio_bus
+ * component
+ */
+
+#ifndef __MDIO_BOARD_INFO_H
+#define __MDIO_BOARD_INFO_H
+
+#include <linux/phy.h>
+#include <linux/mutex.h>
+
+struct mdio_board_entry {
+ struct list_head list;
+ struct mdio_board_info board_info;
+};
+
+void mdiobus_setup_mdiodev_from_board_info(struct mii_bus *bus);
+
+#endif /* __MDIO_BOARD_INFO_H */
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 653d076eafe5..fa7d51f14869 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -41,6 +41,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/mdio.h>
+#include "mdio-boardinfo.h"
+
int mdiobus_register_device(struct mdio_device *mdiodev)
{
if (mdiodev->bus->mdio_map[mdiodev->addr])
@@ -343,6 +345,8 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
}
}
+ mdiobus_setup_mdiodev_from_board_info(bus);
+
bus->state = MDIOBUS_REGISTERED;
pr_info("%s: probed\n", bus->name);
return 0;
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index fc3aaaa36b1d..e24f28924af8 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -34,6 +34,17 @@ static void mdio_device_release(struct device *dev)
kfree(to_mdio_device(dev));
}
+int mdio_device_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct mdio_device *mdiodev = to_mdio_device(dev);
+ struct mdio_driver *mdiodrv = to_mdio_driver(drv);
+
+ if (mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY)
+ return 0;
+
+ return strcmp(mdiodev->modalias, drv->name) == 0;
+}
+
struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
{
struct mdio_device *mdiodev;
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index b6587a4b32e7..00a7f43c1482 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -10,6 +10,7 @@
#define __LINUX_MDIO_H__
#include <uapi/linux/mdio.h>
+#include <linux/mod_devicetable.h>
struct mii_bus;
@@ -29,6 +30,7 @@ struct mdio_device {
const struct dev_pm_ops *pm_ops;
struct mii_bus *bus;
+ char modalias[MDIO_NAME_SIZE];
int (*bus_match)(struct device *dev, struct device_driver *drv);
void (*device_free)(struct mdio_device *mdiodev);
@@ -71,6 +73,7 @@ int mdio_device_register(struct mdio_device *mdiodev);
void mdio_device_remove(struct mdio_device *mdiodev);
int mdio_driver_register(struct mdio_driver *drv);
void mdio_driver_unregister(struct mdio_driver *drv);
+int mdio_device_bus_match(struct device *dev, struct device_driver *drv);
static inline bool mdio_phy_id_is_c45(int phy_id)
{
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 8a57f0b1242d..8850fcaf50db 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -501,6 +501,7 @@ struct platform_device_id {
kernel_ulong_t driver_data;
};
+#define MDIO_NAME_SIZE 32
#define MDIO_MODULE_PREFIX "mdio:"
#define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
diff --git a/include/linux/phy.h b/include/linux/phy.h
index f7d95f644eed..7745f7391d3e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -882,6 +882,25 @@ void mdio_bus_exit(void);
extern struct bus_type mdio_bus_type;
+struct mdio_board_info {
+ const char *bus_id;
+ char modalias[MDIO_NAME_SIZE];
+ int mdio_addr;
+ const void *platform_data;
+};
+
+#if IS_ENABLED(CONFIG_PHYLIB)
+int mdiobus_register_board_info(const struct mdio_board_info *info,
+ unsigned int n);
+#else
+static inline int mdiobus_register_board_info(const struct mdio_board_info *i,
+ unsigned int n)
+{
+ return 0;
+}
+#endif
+
+
/**
* module_phy_driver() - Helper macro for registering PHY drivers
* @__phy_drivers: array of PHY drivers to register
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 10/10] ARM: orion: Register DSA switch as a MDIO device
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Utilize the ability to pass board specific MDIO bus information towards a
particular MDIO device thus allowing us to provide the per-port switch layout
to the Marvell 88E6XXX switch driver.
Since we would end-up with conflicting registration paths, do not register the
"dsa" platform device anymore.
Note that the MDIO devices registered by code in net/dsa/dsa2.c does not
parse a dsa_platform_data, but directly take a dsa_chip_data (specific
to a single switch chip), so we update the different call sites to pass
this structure down to orion_ge00_switch_init().
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/mach-orion5x/common.c | 2 +-
arch/arm/mach-orion5x/common.h | 4 ++--
arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c | 7 +------
arch/arm/mach-orion5x/rd88f5181l-ge-setup.c | 7 +------
arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c | 7 +------
arch/arm/mach-orion5x/wnr854t-setup.c | 2 +-
arch/arm/mach-orion5x/wrt350n-v2-setup.c | 7 +------
arch/arm/plat-orion/common.c | 25 +++++++++++++++++++------
arch/arm/plat-orion/include/plat/common.h | 4 ++--
9 files changed, 29 insertions(+), 36 deletions(-)
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 04910764c385..83a7ec4c16d0 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -105,7 +105,7 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
/*****************************************************************************
* Ethernet switch
****************************************************************************/
-void __init orion5x_eth_switch_init(struct dsa_platform_data *d)
+void __init orion5x_eth_switch_init(struct dsa_chip_data *d)
{
orion_ge00_switch_init(d);
}
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 8a4115bd441d..efeffc6b4ebb 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -3,7 +3,7 @@
#include <linux/reboot.h>
-struct dsa_platform_data;
+struct dsa_chip_data;
struct mv643xx_eth_platform_data;
struct mv_sata_platform_data;
@@ -41,7 +41,7 @@ void orion5x_setup_wins(void);
void orion5x_ehci0_init(void);
void orion5x_ehci1_init(void);
void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
-void orion5x_eth_switch_init(struct dsa_platform_data *d);
+void orion5x_eth_switch_init(struct dsa_chip_data *d);
void orion5x_i2c_init(void);
void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
void orion5x_spi_init(void);
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index dccadf68ea2b..a3c1336d30c9 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -101,11 +101,6 @@ static struct dsa_chip_data rd88f5181l_fxo_switch_chip_data = {
.port_names[7] = "lan3",
};
-static struct dsa_platform_data __initdata rd88f5181l_fxo_switch_plat_data = {
- .nr_chips = 1,
- .chip = &rd88f5181l_fxo_switch_chip_data,
-};
-
static void __init rd88f5181l_fxo_init(void)
{
/*
@@ -120,7 +115,7 @@ static void __init rd88f5181l_fxo_init(void)
*/
orion5x_ehci0_init();
orion5x_eth_init(&rd88f5181l_fxo_eth_data);
- orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data);
+ orion5x_eth_switch_init(&rd88f5181l_fxo_switch_chip_data);
orion5x_uart0_init();
mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index affe5ec825de..252efe29bd1a 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -102,11 +102,6 @@ static struct dsa_chip_data rd88f5181l_ge_switch_chip_data = {
.port_names[7] = "lan3",
};
-static struct dsa_platform_data __initdata rd88f5181l_ge_switch_plat_data = {
- .nr_chips = 1,
- .chip = &rd88f5181l_ge_switch_chip_data,
-};
-
static struct i2c_board_info __initdata rd88f5181l_ge_i2c_rtc = {
I2C_BOARD_INFO("ds1338", 0x68),
};
@@ -125,7 +120,7 @@ static void __init rd88f5181l_ge_init(void)
*/
orion5x_ehci0_init();
orion5x_eth_init(&rd88f5181l_ge_eth_data);
- orion5x_eth_switch_init(&rd88f5181l_ge_switch_plat_data);
+ orion5x_eth_switch_init(&rd88f5181l_ge_switch_chip_data);
orion5x_i2c_init();
orion5x_uart0_init();
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index 67ee8571b03c..f4f1dbe1d91d 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -40,11 +40,6 @@ static struct dsa_chip_data rd88f6183ap_ge_switch_chip_data = {
.port_names[5] = "cpu",
};
-static struct dsa_platform_data __initdata rd88f6183ap_ge_switch_plat_data = {
- .nr_chips = 1,
- .chip = &rd88f6183ap_ge_switch_chip_data,
-};
-
static struct mtd_partition rd88f6183ap_ge_partitions[] = {
{
.name = "kernel",
@@ -89,7 +84,7 @@ static void __init rd88f6183ap_ge_init(void)
*/
orion5x_ehci0_init();
orion5x_eth_init(&rd88f6183ap_ge_eth_data);
- orion5x_eth_switch_init(&rd88f6183ap_ge_switch_plat_data);
+ orion5x_eth_switch_init(&rd88f6183ap_ge_switch_chip_data);
spi_register_board_info(rd88f6183ap_ge_spi_slave_info,
ARRAY_SIZE(rd88f6183ap_ge_spi_slave_info));
orion5x_spi_init();
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 4dbcdbe1de7c..ac3376fc269f 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -124,7 +124,7 @@ static void __init wnr854t_init(void)
* Configure peripherals.
*/
orion5x_eth_init(&wnr854t_eth_data);
- orion5x_eth_switch_init(&wnr854t_switch_plat_data);
+ orion5x_eth_switch_init(&wnr854t_switch_chip_data);
orion5x_uart0_init();
mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index a6a8c4648d74..9250bb2e429c 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -191,11 +191,6 @@ static struct dsa_chip_data wrt350n_v2_switch_chip_data = {
.port_names[7] = "lan4",
};
-static struct dsa_platform_data __initdata wrt350n_v2_switch_plat_data = {
- .nr_chips = 1,
- .chip = &wrt350n_v2_switch_chip_data,
-};
-
static void __init wrt350n_v2_init(void)
{
/*
@@ -210,7 +205,7 @@ static void __init wrt350n_v2_init(void)
*/
orion5x_ehci0_init();
orion5x_eth_init(&wrt350n_v2_eth_data);
- orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data);
+ orion5x_eth_switch_init(&wrt350n_v2_switch_chip_data);
orion5x_uart0_init();
mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 272f49b2c68f..9255b6d67ba5 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -22,6 +22,7 @@
#include <linux/platform_data/dma-mv_xor.h>
#include <linux/platform_data/usb-ehci-orion.h>
#include <plat/common.h>
+#include <linux/phy.h>
/* Create a clkdev entry for a given device/clk */
void __init orion_clkdev_add(const char *con_id, const char *dev_id,
@@ -470,15 +471,27 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
/*****************************************************************************
* Ethernet switch
****************************************************************************/
-void __init orion_ge00_switch_init(struct dsa_platform_data *d)
+static __initconst const char *orion_ge00_mvmdio_bus_name = "orion-mii";
+static __initdata struct mdio_board_info
+ orion_ge00_switch_board_info;
+
+void __init orion_ge00_switch_init(struct dsa_chip_data *d)
{
- int i;
+ struct mdio_board_info *bd;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(d->port_names); i++)
+ if (!strcmp(d->port_names[i], "cpu"))
+ break;
- d->netdev = &orion_ge00.dev;
- for (i = 0; i < d->nr_chips; i++)
- d->chip[i].host_dev = &orion_ge_mvmdio.dev;
+ bd = &orion_ge00_switch_board_info;
+ bd->bus_id = orion_ge00_mvmdio_bus_name;
+ bd->mdio_addr = d->sw_addr;
+ d->netdev[i] = &orion_ge00.dev;
+ strcpy(bd->modalias, "mv88e6085");
+ bd->platform_data = d;
- platform_device_register_data(NULL, "dsa", 0, d, sizeof(d));
+ mdiobus_register_board_info(&orion_ge00_switch_board_info, 1);
}
/*****************************************************************************
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index 9347f3c58a6d..3647d3b33c20 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -12,7 +12,7 @@
#include <linux/mv643xx_eth.h>
#include <linux/platform_data/usb-ehci-orion.h>
-struct dsa_platform_data;
+struct dsa_chip_data;
struct mv_sata_platform_data;
void __init orion_uart0_init(void __iomem *membase,
@@ -57,7 +57,7 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
unsigned long mapbase,
unsigned long irq);
-void __init orion_ge00_switch_init(struct dsa_platform_data *d);
+void __init orion_ge00_switch_init(struct dsa_chip_data *d);
void __init orion_i2c_init(unsigned long mapbase,
unsigned long irq,
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v3 05/10] drivers: base: Add device_find_class()
From: Florian Fainelli @ 2017-01-14 21:47 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Russell King,
Vivien Didelot, David S. Miller,
moderated list:ARM SUB-ARCHITECTURES, open list, gregkh
In-Reply-To: <20170114214713.28109-1-f.fainelli@gmail.com>
Add a helper function to lookup a device reference given a class name.
This is a preliminary patch to remove adhoc code from net/dsa/dsa.c and
make it more generic.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/base/core.c | 19 +++++++++++++++++++
include/linux/device.h | 1 +
2 files changed, 20 insertions(+)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 020ea7f05520..3dd6047c10d8 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2065,6 +2065,25 @@ struct device *device_find_child(struct device *parent, void *data,
}
EXPORT_SYMBOL_GPL(device_find_child);
+static int dev_is_class(struct device *dev, void *class)
+{
+ if (dev->class != NULL && !strcmp(dev->class->name, class))
+ return 1;
+
+ return 0;
+}
+
+struct device *device_find_class(struct device *parent, char *class)
+{
+ if (dev_is_class(parent, class)) {
+ get_device(parent);
+ return parent;
+ }
+
+ return device_find_child(parent, class, dev_is_class);
+}
+EXPORT_SYMBOL_GPL(device_find_class);
+
int __init devices_init(void)
{
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
diff --git a/include/linux/device.h b/include/linux/device.h
index 491b4c0ca633..8d37f5ecb972 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1120,6 +1120,7 @@ extern int device_for_each_child_reverse(struct device *dev, void *data,
int (*fn)(struct device *dev, void *data));
extern struct device *device_find_child(struct device *dev, void *data,
int (*match)(struct device *dev, void *data));
+extern struct device *device_find_class(struct device *parent, char *class);
extern int device_rename(struct device *dev, const char *new_name);
extern int device_move(struct device *dev, struct device *new_parent,
enum dpm_order dpm_order);
--
2.9.3
^ permalink raw reply related
* [PATCH net-next 1/1] net sched actions: Add support for user cookies
From: Jamal Hadi Salim @ 2017-01-14 21:52 UTC (permalink / raw)
To: davem
Cc: netdev, jiri, paulb, john.fastabend, simon.horman, mrv, hadarh,
ogerlitz, roid, xiyou.wangcong, daniel, Jamal Hadi Salim
From: Jamal Hadi Salim <jhs@mojatatu.com>
Introduce optional 128-bit action cookie.
Like all other cookie schemes in the networking world (eg in protocols
like http or existing kernel fib protocol field, etc) the idea is to save
user state that when retrieved serves as a correlator. The kernel
_should not_ intepret it. The user can store whatever they wish in the
128 bits.
Sample exercise(using two 64bit values to represent the 128 bits):
.. create an accept action with cookie a1b2c3d4
sudo $TC actions add action ok index 1 cookie a1b2c3d4
.. dump all gact actions..
sudo $TC -s actions ls action gact
action order 0: gact action pass
random type none pass val 0
index 1 ref 1 bind 0 installed 5 sec used 5 sec
Action statistics:
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
cookie a1b2c3d4
.. bind the accept action to a filter..
sudo $TC filter add dev lo parent ffff: protocol ip prio 1 \
u32 match ip dst 127.0.0.1/32 flowid 1:1 action gact index 1
... send some traffic..
$ ping 127.0.0.1 -c 3
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.020 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.027 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.038 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2109ms
rtt min/avg/max/mdev = 0.020/0.028/0.038/0.008 ms 1
... show some stats
$ sudo $TC -s actions get action gact index 1
action order 1: gact action pass
random type none pass val 0
index 1 ref 2 bind 1 installed 204 sec used 5 sec
Action statistics:
Sent 12168 bytes 164 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
cookie a1b2c3d4
.. try longer cookie...
$ sudo $TC actions replace action ok index 1 cookie 1234567890abcdef
.. dump..
$ sudo $TC -s actions ls action gact
action order 1: gact action pass
random type none pass val 0
index 1 ref 2 bind 1 installed 204 sec used 5 sec
Action statistics:
Sent 12168 bytes 164 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
cookie 1234567890abcdef
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
include/net/act_api.h | 1 +
include/uapi/linux/pkt_cls.h | 11 +++++++++++
net/sched/act_api.c | 28 ++++++++++++++++++++++++++--
3 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 1d71644..0692458 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -41,6 +41,7 @@ struct tc_action {
struct rcu_head tcfa_rcu;
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
struct gnet_stats_queue __percpu *cpu_qstats;
+ struct tc_cookie *act_ck;
};
#define tcf_head common.tcfa_head
#define tcf_index common.tcfa_index
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 1e5e1dd..063bc89 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -4,6 +4,16 @@
#include <linux/types.h>
#include <linux/pkt_sched.h>
+#define MAX_TC_COOKIE_SZ 16
+
+/* This structure holds cookie structure that is passed from user
+ * to the kernel for actions and classifiers
+ */
+struct tc_cookie {
+ unsigned char ck[MAX_TC_COOKIE_SZ];
+ unsigned char ck_len;
+};
+
/* Action attributes */
enum {
TCA_ACT_UNSPEC,
@@ -12,6 +22,7 @@ enum {
TCA_ACT_INDEX,
TCA_ACT_STATS,
TCA_ACT_PAD,
+ TCA_ACT_COOKIE,
__TCA_ACT_MAX
};
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index f04715a..b82908a 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -33,6 +33,7 @@ static void free_tcf(struct rcu_head *head)
free_percpu(p->cpu_bstats);
free_percpu(p->cpu_qstats);
+ kfree(p->act_ck);
kfree(p);
}
@@ -464,8 +465,8 @@ int tcf_action_destroy(struct list_head *actions, int bind)
return a->ops->dump(skb, a, bind, ref);
}
-int
-tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind,
+ int ref)
{
int err = -EINVAL;
unsigned char *b = skb_tail_pointer(skb);
@@ -475,6 +476,12 @@ int tcf_action_destroy(struct list_head *actions, int bind)
goto nla_put_failure;
if (tcf_action_copy_stats(skb, a, 0))
goto nla_put_failure;
+ if (a->act_ck) {
+ if (nla_put(skb, TCA_ACT_COOKIE, a->act_ck->ck_len,
+ a->act_ck))
+ goto nla_put_failure;
+ }
+
nest = nla_nest_start(skb, TCA_OPTIONS);
if (nest == NULL)
goto nla_put_failure;
@@ -575,6 +582,23 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
if (err < 0)
goto err_mod;
+ if (tb[TCA_ACT_COOKIE]) {
+ if (nla_len(tb[TCA_ACT_COOKIE]) > MAX_TC_COOKIE_SZ) {
+ err = -EINVAL;
+ goto err_mod;
+ }
+
+ a->act_ck = kzalloc(sizeof(*a->act_ck), GFP_KERNEL);
+ if (unlikely(!a->act_ck)) {
+ err = -ENOMEM;
+ goto err_mod;
+ }
+
+ memcpy((void *)a->act_ck->ck, nla_data(tb[TCA_ACT_COOKIE]),
+ nla_len(tb[TCA_ACT_COOKIE]));
+ a->act_ck->ck_len = nla_len(tb[TCA_ACT_COOKIE]);
+ }
+
/* module count goes up only when brand new policy is created
* if it exists and is only bound to in a_o->init() then
* ACT_P_CREATED is not returned (a zero is).
--
1.9.1
^ permalink raw reply related
* [PATCH iproute2 1/1] utils: make hex2mem available to all users
From: Jamal Hadi Salim @ 2017-01-14 22:04 UTC (permalink / raw)
To: tephen; +Cc: netdev, Jamal Hadi Salim
From: Jamal Hadi Salim <jhs@mojatatu.com>
hex2mem() api is useful for parsing hexstrings which are then packed in
a stream of chars.
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
include/utils.h | 1 +
ip/ipl2tp.c | 25 -------------------------
lib/utils.c | 25 +++++++++++++++++++++++++
3 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index dc1d6b9..22369e0 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -118,6 +118,7 @@ int get_be32(__be32 *val, const char *arg, int base);
int get_be16(__be16 *val, const char *arg, int base);
int get_addr64(__u64 *ap, const char *cp);
+int hex2mem(const char *buf, uint8_t *mem, int count);
char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen);
__u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len);
#define ADDR64_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
index 0f91aeb..88664c9 100644
--- a/ip/ipl2tp.c
+++ b/ip/ipl2tp.c
@@ -485,31 +485,6 @@ static int get_tunnel(struct l2tp_data *p)
* Command parser
*****************************************************************************/
-static int hex2mem(const char *buf, uint8_t *mem, int count)
-{
- int i, j;
- int c;
-
- for (i = 0, j = 0; i < count; i++, j += 2) {
- c = get_hex(buf[j]);
- if (c < 0)
- goto err;
-
- mem[i] = c << 4;
-
- c = get_hex(buf[j + 1]);
- if (c < 0)
- goto err;
-
- mem[i] |= c;
- }
-
- return 0;
-
-err:
- return -1;
-}
-
static void usage(void) __attribute__((noreturn));
static void usage(void)
diff --git a/lib/utils.c b/lib/utils.c
index 83c9d09..870c4f1 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -962,6 +962,31 @@ __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len)
return buf;
}
+int hex2mem(const char *buf, uint8_t *mem, int count)
+{
+ int i, j;
+ int c;
+
+ for (i = 0, j = 0; i < count; i++, j += 2) {
+ c = get_hex(buf[j]);
+ if (c < 0)
+ goto err;
+
+ mem[i] = c << 4;
+
+ c = get_hex(buf[j + 1]);
+ if (c < 0)
+ goto err;
+
+ mem[i] |= c;
+ }
+
+ return 0;
+
+err:
+ return -1;
+}
+
int addr64_n2a(__u64 addr, char *buff, size_t len)
{
__u16 *words = (__u16 *)&addr;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH iproute2 1/1] utils: make hex2mem available to all users
From: Jamal Hadi Salim @ 2017-01-14 22:09 UTC (permalink / raw)
To: stephen; +Cc: netdev
In-Reply-To: <1484431483-31896-1-git-send-email-jhs@emojatatu.com>
Sorry, messed up Stephen's address. Resending..
cheers,
jamal
On 17-01-14 05:04 PM, Jamal Hadi Salim wrote:
> From: Jamal Hadi Salim <jhs@mojatatu.com>
>
> hex2mem() api is useful for parsing hexstrings which are then packed in
> a stream of chars.
>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
> include/utils.h | 1 +
> ip/ipl2tp.c | 25 -------------------------
> lib/utils.c | 25 +++++++++++++++++++++++++
> 3 files changed, 26 insertions(+), 25 deletions(-)
>
> diff --git a/include/utils.h b/include/utils.h
> index dc1d6b9..22369e0 100644
> --- a/include/utils.h
> +++ b/include/utils.h
> @@ -118,6 +118,7 @@ int get_be32(__be32 *val, const char *arg, int base);
> int get_be16(__be16 *val, const char *arg, int base);
> int get_addr64(__u64 *ap, const char *cp);
>
> +int hex2mem(const char *buf, uint8_t *mem, int count);
> char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen);
> __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len);
> #define ADDR64_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
> diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
> index 0f91aeb..88664c9 100644
> --- a/ip/ipl2tp.c
> +++ b/ip/ipl2tp.c
> @@ -485,31 +485,6 @@ static int get_tunnel(struct l2tp_data *p)
> * Command parser
> *****************************************************************************/
>
> -static int hex2mem(const char *buf, uint8_t *mem, int count)
> -{
> - int i, j;
> - int c;
> -
> - for (i = 0, j = 0; i < count; i++, j += 2) {
> - c = get_hex(buf[j]);
> - if (c < 0)
> - goto err;
> -
> - mem[i] = c << 4;
> -
> - c = get_hex(buf[j + 1]);
> - if (c < 0)
> - goto err;
> -
> - mem[i] |= c;
> - }
> -
> - return 0;
> -
> -err:
> - return -1;
> -}
> -
> static void usage(void) __attribute__((noreturn));
>
> static void usage(void)
> diff --git a/lib/utils.c b/lib/utils.c
> index 83c9d09..870c4f1 100644
> --- a/lib/utils.c
> +++ b/lib/utils.c
> @@ -962,6 +962,31 @@ __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len)
> return buf;
> }
>
> +int hex2mem(const char *buf, uint8_t *mem, int count)
> +{
> + int i, j;
> + int c;
> +
> + for (i = 0, j = 0; i < count; i++, j += 2) {
> + c = get_hex(buf[j]);
> + if (c < 0)
> + goto err;
> +
> + mem[i] = c << 4;
> +
> + c = get_hex(buf[j + 1]);
> + if (c < 0)
> + goto err;
> +
> + mem[i] |= c;
> + }
> +
> + return 0;
> +
> +err:
> + return -1;
> +}
> +
> int addr64_n2a(__u64 addr, char *buff, size_t len)
> {
> __u16 *words = (__u16 *)&addr;
>
^ permalink raw reply
* [PATCH resend iproute2 1/1] utils: make hex2mem available to all users
From: Jamal Hadi Salim @ 2017-01-14 22:10 UTC (permalink / raw)
To: stephen; +Cc: netdev, Jamal Hadi Salim
From: Jamal Hadi Salim <jhs@mojatatu.com>
hex2mem() api is useful for parsing hexstrings which are then packed in
a stream of chars.
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
include/utils.h | 1 +
ip/ipl2tp.c | 25 -------------------------
lib/utils.c | 25 +++++++++++++++++++++++++
3 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index dc1d6b9..22369e0 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -118,6 +118,7 @@ int get_be32(__be32 *val, const char *arg, int base);
int get_be16(__be16 *val, const char *arg, int base);
int get_addr64(__u64 *ap, const char *cp);
+int hex2mem(const char *buf, uint8_t *mem, int count);
char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen);
__u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len);
#define ADDR64_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
index 0f91aeb..88664c9 100644
--- a/ip/ipl2tp.c
+++ b/ip/ipl2tp.c
@@ -485,31 +485,6 @@ static int get_tunnel(struct l2tp_data *p)
* Command parser
*****************************************************************************/
-static int hex2mem(const char *buf, uint8_t *mem, int count)
-{
- int i, j;
- int c;
-
- for (i = 0, j = 0; i < count; i++, j += 2) {
- c = get_hex(buf[j]);
- if (c < 0)
- goto err;
-
- mem[i] = c << 4;
-
- c = get_hex(buf[j + 1]);
- if (c < 0)
- goto err;
-
- mem[i] |= c;
- }
-
- return 0;
-
-err:
- return -1;
-}
-
static void usage(void) __attribute__((noreturn));
static void usage(void)
diff --git a/lib/utils.c b/lib/utils.c
index 83c9d09..870c4f1 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -962,6 +962,31 @@ __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len)
return buf;
}
+int hex2mem(const char *buf, uint8_t *mem, int count)
+{
+ int i, j;
+ int c;
+
+ for (i = 0, j = 0; i < count; i++, j += 2) {
+ c = get_hex(buf[j]);
+ if (c < 0)
+ goto err;
+
+ mem[i] = c << 4;
+
+ c = get_hex(buf[j + 1]);
+ if (c < 0)
+ goto err;
+
+ mem[i] |= c;
+ }
+
+ return 0;
+
+err:
+ return -1;
+}
+
int addr64_n2a(__u64 addr, char *buff, size_t len)
{
__u16 *words = (__u16 *)&addr;
--
1.9.1
^ permalink raw reply related
* [PATCH] net: marvell: sky2: use new api ethtool_{get|set}_link_ksettings
From: Philippe Reynes @ 2017-01-14 22:26 UTC (permalink / raw)
To: mlindner, stephen, davem; +Cc: netdev, linux-kernel, Philippe Reynes
The ethtool api {get|set}_settings is deprecated.
We move this driver to new api {get|set}_link_ksettings.
Signed-off-by: Philippe Reynes <tremyfr@gmail.com>
---
drivers/net/ethernet/marvell/sky2.c | 68 ++++++++++++++++++++--------------
1 files changed, 40 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 18d6336..be003c5 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -3589,47 +3589,59 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw)
| SUPPORTED_1000baseT_Full;
}
-static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int sky2_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
+ u32 supported, advertising;
- ecmd->transceiver = XCVR_INTERNAL;
- ecmd->supported = sky2_supported_modes(hw);
- ecmd->phy_address = PHY_ADDR_MARV;
+ supported = sky2_supported_modes(hw);
+ cmd->base.phy_address = PHY_ADDR_MARV;
if (sky2_is_copper(hw)) {
- ecmd->port = PORT_TP;
- ethtool_cmd_speed_set(ecmd, sky2->speed);
- ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_TP;
+ cmd->base.port = PORT_TP;
+ cmd->base.speed = sky2->speed;
+ supported |= SUPPORTED_Autoneg | SUPPORTED_TP;
} else {
- ethtool_cmd_speed_set(ecmd, SPEED_1000);
- ecmd->port = PORT_FIBRE;
- ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_FIBRE;
+ cmd->base.speed = SPEED_1000;
+ cmd->base.port = PORT_FIBRE;
+ supported |= SUPPORTED_Autoneg | SUPPORTED_FIBRE;
}
- ecmd->advertising = sky2->advertising;
- ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_SPEED)
+ advertising = sky2->advertising;
+ cmd->base.autoneg = (sky2->flags & SKY2_FLAG_AUTO_SPEED)
? AUTONEG_ENABLE : AUTONEG_DISABLE;
- ecmd->duplex = sky2->duplex;
+ cmd->base.duplex = sky2->duplex;
+
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+ supported);
+ ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+ advertising);
+
return 0;
}
-static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int sky2_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct sky2_port *sky2 = netdev_priv(dev);
const struct sky2_hw *hw = sky2->hw;
u32 supported = sky2_supported_modes(hw);
+ u32 new_advertising;
+
+ ethtool_convert_link_mode_to_legacy_u32(&new_advertising,
+ cmd->link_modes.advertising);
- if (ecmd->autoneg == AUTONEG_ENABLE) {
- if (ecmd->advertising & ~supported)
+ if (cmd->base.autoneg == AUTONEG_ENABLE) {
+ if (new_advertising & ~supported)
return -EINVAL;
if (sky2_is_copper(hw))
- sky2->advertising = ecmd->advertising |
+ sky2->advertising = new_advertising |
ADVERTISED_TP |
ADVERTISED_Autoneg;
else
- sky2->advertising = ecmd->advertising |
+ sky2->advertising = new_advertising |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg;
@@ -3638,30 +3650,30 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
sky2->speed = -1;
} else {
u32 setting;
- u32 speed = ethtool_cmd_speed(ecmd);
+ u32 speed = cmd->base.speed;
switch (speed) {
case SPEED_1000:
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
setting = SUPPORTED_1000baseT_Full;
- else if (ecmd->duplex == DUPLEX_HALF)
+ else if (cmd->base.duplex == DUPLEX_HALF)
setting = SUPPORTED_1000baseT_Half;
else
return -EINVAL;
break;
case SPEED_100:
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
setting = SUPPORTED_100baseT_Full;
- else if (ecmd->duplex == DUPLEX_HALF)
+ else if (cmd->base.duplex == DUPLEX_HALF)
setting = SUPPORTED_100baseT_Half;
else
return -EINVAL;
break;
case SPEED_10:
- if (ecmd->duplex == DUPLEX_FULL)
+ if (cmd->base.duplex == DUPLEX_FULL)
setting = SUPPORTED_10baseT_Full;
- else if (ecmd->duplex == DUPLEX_HALF)
+ else if (cmd->base.duplex == DUPLEX_HALF)
setting = SUPPORTED_10baseT_Half;
else
return -EINVAL;
@@ -3674,7 +3686,7 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EINVAL;
sky2->speed = speed;
- sky2->duplex = ecmd->duplex;
+ sky2->duplex = cmd->base.duplex;
sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
}
@@ -4405,8 +4417,6 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features)
}
static const struct ethtool_ops sky2_ethtool_ops = {
- .get_settings = sky2_get_settings,
- .set_settings = sky2_set_settings,
.get_drvinfo = sky2_get_drvinfo,
.get_wol = sky2_get_wol,
.set_wol = sky2_set_wol,
@@ -4429,6 +4439,8 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features)
.set_phys_id = sky2_set_phys_id,
.get_sset_count = sky2_get_sset_count,
.get_ethtool_stats = sky2_get_ethtool_stats,
+ .get_link_ksettings = sky2_get_link_ksettings,
+ .set_link_ksettings = sky2_set_link_ksettings,
};
#ifdef CONFIG_SKY2_DEBUG
--
1.7.4.4
^ permalink raw reply related
* Re: [PATCH v5 05/13] net: ethernet: aquantia: Support for NIC-specific code
From: Rami Rosen @ 2017-01-14 22:55 UTC (permalink / raw)
To: Florian Fainelli
Cc: Alexander Loktionov, Netdev, David VomLehn, David S . Miller,
Simon Edelhaus, Dmitrii Tarakanov, Pavel Belous, Dmitry Bezrukov
In-Reply-To: <3dfe11ac-4215-21d0-2242-7a4ad6157e56@gmail.com>
Hi, Florian,
> +}
> +
> +static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
> +{
> + struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
> + int err = 0;
> +
> + if (new_mtu == ndev->mtu) {
> + err = 0;
> + goto err_exit;
> + }
> + if (new_mtu < 68) {
> + err = -EINVAL;
> + goto err_exit;
> + }
> What's so special about 68 here?
I think that the check that the passed MTU is at least 68 bytes is
justified and correct.
This convention is followed by a large number of Ethernet drivers; for example,
http://lxr.free-electrons.com/source/drivers/net/ethernet/intel/i40e/i40e_main.c#L2246
http://lxr.free-electrons.com/source/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c#L6049
The size of 68 bytes is originated from RFC 791:
https://tools.ietf.org/html/rfc791
...
Every internet module must be able to forward a datagram of 68 octets
without further fragmentation.
This is because an internet header may be up to 60 octets, and the
minimum fragment is 8 octets.
...
Regards,
Rami Rosen
^ permalink raw reply
* 4.9 conntrack performance issues
From: Denys Fedoryshchenko @ 2017-01-14 23:05 UTC (permalink / raw)
To: Guillaume Nault, Netfilter Devel, Pablo Neira Ayuso,
Linux Kernel Network Developers
Hi!
Sorry if i added someone wrongly to CC, please let me know, if i should
remove.
I just run successfully 4.9 on my nat several days ago, and seems panic
issue disappeared. But i started to face another issue, it seems garbage
collector is hogging one of CPU's.
Here is my data:
2xE5-2640 v3
396G ram
2x10G (bonding) with approx 14-15G load at peak time
It was handling load very well at 4.8 and below, it might be still fine,
but i suspect queues that belong to hogged cpu might experience issues.
Is there anything can be done to improve cpu load distribution or reduce
single core load?
net.netfilter.nf_conntrack_buckets = 65536
net.netfilter.nf_conntrack_checksum = 1
net.netfilter.nf_conntrack_count = 1236021
net.netfilter.nf_conntrack_events = 1
net.netfilter.nf_conntrack_expect_max = 1024
net.netfilter.nf_conntrack_generic_timeout = 600
net.netfilter.nf_conntrack_helper = 0
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_log_invalid = 0
net.netfilter.nf_conntrack_max = 6553600
net.netfilter.nf_conntrack_tcp_be_liberal = 0
net.netfilter.nf_conntrack_tcp_loose = 0
net.netfilter.nf_conntrack_tcp_max_retrans = 3
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_established = 600
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 20
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 20
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 20
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 20
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 30
net.netfilter.nf_conntrack_timestamp = 0
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 180
net.nf_conntrack_max = 6553600
it is non-peak values, as adjustments i have shorter than default
timeouts. Changing net.netfilter.nf_conntrack_buckets to higher value
doesn't fix issue.
I noticed that one of CPU's hogged (N24 in this case):
Linux 4.9.2-build-0127 (NAT) 01/14/17 _x86_64_ (32 CPU)
23:01:54 CPU %usr %nice %sys %iowait %irq %soft %steal
%guest %idle
23:02:04 all 0.09 0.00 1.60 0.01 0.00 28.28 0.00
0.00 70.01
23:02:04 0 0.11 0.00 0.00 0.00 0.00 32.38 0.00
0.00 67.51
23:02:04 1 0.12 0.00 0.12 0.00 0.00 29.91 0.00
0.00 69.86
23:02:04 2 0.23 0.00 0.11 0.00 0.00 29.57 0.00
0.00 70.09
23:02:04 3 0.11 0.00 0.11 0.11 0.00 28.80 0.00
0.00 70.86
23:02:04 4 0.23 0.00 0.11 0.11 0.00 31.41 0.00
0.00 68.14
23:02:04 5 0.11 0.00 0.00 0.00 0.00 29.28 0.00
0.00 70.61
23:02:04 6 0.11 0.00 0.11 0.00 0.00 31.81 0.00
0.00 67.96
23:02:04 7 0.11 0.00 0.11 0.00 0.00 32.69 0.00
0.00 67.08
23:02:04 8 0.00 0.00 0.23 0.00 0.00 42.12 0.00
0.00 57.64
23:02:04 9 0.11 0.00 0.00 0.00 0.00 30.86 0.00
0.00 69.02
23:02:04 10 0.11 0.00 0.11 0.00 0.00 30.93 0.00
0.00 68.84
23:02:04 11 0.00 0.00 0.11 0.00 0.00 32.73 0.00
0.00 67.16
23:02:04 12 0.11 0.00 0.11 0.00 0.00 29.85 0.00
0.00 69.92
23:02:04 13 0.00 0.00 0.00 0.00 0.00 30.96 0.00
0.00 69.04
23:02:04 14 0.00 0.00 0.00 0.00 0.00 30.09 0.00
0.00 69.91
23:02:04 15 0.00 0.00 0.11 0.00 0.00 30.63 0.00
0.00 69.26
23:02:04 16 0.11 0.00 0.00 0.00 0.00 25.88 0.00
0.00 74.01
23:02:04 17 0.11 0.00 0.00 0.00 0.00 22.82 0.00
0.00 77.07
23:02:04 18 0.11 0.00 0.00 0.00 0.00 23.75 0.00
0.00 76.14
23:02:04 19 0.11 0.00 0.11 0.00 0.00 24.86 0.00
0.00 74.92
23:02:04 20 0.11 0.00 0.11 0.11 0.00 24.48 0.00
0.00 75.19
23:02:04 21 0.22 0.00 0.11 0.00 0.00 23.43 0.00
0.00 76.24
23:02:04 22 0.11 0.00 0.11 0.00 0.00 25.46 0.00
0.00 74.32
23:02:04 23 0.00 0.00 0.11 0.00 0.00 25.47 0.00
0.00 74.41
23:02:04 24 0.00 0.00 45.06 0.00 0.00 42.18 0.00
0.00 12.76
23:02:04 25 0.11 0.00 0.11 0.11 0.00 25.22 0.00
0.00 74.46
23:02:04 26 0.11 0.00 0.00 0.11 0.00 23.39 0.00
0.00 76.39
23:02:04 27 0.22 0.00 0.11 0.00 0.00 23.83 0.00
0.00 75.85
23:02:04 28 0.11 0.00 0.11 0.00 0.00 24.10 0.00
0.00 75.68
23:02:04 29 0.11 0.00 0.11 0.00 0.00 23.80 0.00
0.00 75.98
23:02:04 30 0.11 0.00 0.11 0.00 0.00 23.45 0.00
0.00 76.33
23:02:04 31 0.11 0.00 0.11 0.00 0.00 20.37 0.00
0.00 79.42
And this is output of ./perf top -C 24 -e cycles
PerfTop: 933 irqs/sec kernel:100.0% exact: 0.0% [1000Hz
cycles], (all, CPU: 24)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
52.68% [nf_conntrack] [k] gc_worker
3.88% [ip_tables] [k] ipt_do_table
2.39% [ixgbe] [k] ixgbe_xmit_frame_ring
2.29% [kernel] [k] _raw_spin_lock
1.84% [ixgbe] [k] ixgbe_poll
1.76% [nf_conntrack] [k] __nf_conntrack_find_get
perf report for this cpu (same, cycles)
# Children Self Command Shared Object Symbol
# ........ ........ ............ ......................
....................................................
#
88.98% 0.00% kworker/24:1 [kernel.kallsyms] [k]
process_one_work
|
---process_one_work
|
|--54.65%--gc_worker
| |
| --3.58%--nf_ct_gc_expired
| |
| |--1.90%--nf_ct_delete
| | |
| |
--1.31%--nf_ct_delete_from_lists
| |
| --1.61%--nf_conntrack_destroy
| destroy_conntrack
| |
|
--1.53%--nf_conntrack_free
| |
|
|--0.80%--kmem_cache_free
| | |
| |
--0.51%--__slab_free.isra.12
| |
|
--0.52%--__nf_ct_ext_destroy
^ permalink raw reply
* Re: 4.9 conntrack performance issues
From: Florian Westphal @ 2017-01-14 23:53 UTC (permalink / raw)
To: Denys Fedoryshchenko
Cc: Guillaume Nault, Netfilter Devel, Pablo Neira Ayuso,
Linux Kernel Network Developers, nicolas.dichtel
In-Reply-To: <1a71d807acf63135bb037c7144fcd8d9@nuclearcat.com>
Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
[ CC Nicolas since he also played with gc heuristics in the past ]
> Sorry if i added someone wrongly to CC, please let me know, if i should
> remove.
> I just run successfully 4.9 on my nat several days ago, and seems panic
> issue disappeared. But i started to face another issue, it seems garbage
> collector is hogging one of CPU's.
>
> It was handling load very well at 4.8 and below, it might be still fine, but
> i suspect queues that belong to hogged cpu might experience issues.
The worker doesn't grab locks for long and calls scheduler for every
bucket to give a chance for other threads to run.
It also doesn't block softinterrupts.
> Is there anything can be done to improve cpu load distribution or reduce
> single core load?
No, I am afraid we don't export any of the heuristics as tuneables so
far.
You could try changing defaults in net/netfilter/nf_conntrack_core.c:
#define GC_MAX_BUCKETS_DIV 64u
/* upper bound of scan intervals */
#define GC_INTERVAL_MAX (2 * HZ)
/* maximum conntracks to evict per gc run */
#define GC_MAX_EVICTS 256u
(the first two result in ~2 minute worst case timeout detection
on a fully idle system).
For instance you could use
GC_MAX_BUCKETS_DIV -> 128
GC_INTERVAL_MAX -> 30 * HZ
(This means that it takes one hour for a dead connection to be picked
up on an idle system, but thats only relevant in case you use
conntrack events to log when connection went down and need more precise
accounting).
I suspect you might also have to change
1011 } else if (expired_count) {
1012 gc_work->next_gc_run /= 2U;
1013 next_run = msecs_to_jiffies(1);
1014 } else {
line 2013 to
next_run = msecs_to_jiffies(HZ / 2);
or something like this to not have frequent rescans.
The gc is also done from the packet path (i.e. accounted
towards (k)softirq).
How many total connections is the machine handling on average?
And how many new/delete events happen per second?
> 88.98% 0.00% kworker/24:1 [kernel.kallsyms] [k]
> process_one_work
> |
> ---process_one_work
> |
> |--54.65%--gc_worker
> | |
> | --3.58%--nf_ct_gc_expired
> | |
> | |--1.90%--nf_ct_delete
I'd be interested to see how often that shows up on other cores
(from packet path).
^ permalink raw reply
* Re: 4.9 conntrack performance issues
From: Denys Fedoryshchenko @ 2017-01-15 0:18 UTC (permalink / raw)
To: Florian Westphal
Cc: Guillaume Nault, Netfilter Devel, Pablo Neira Ayuso,
Linux Kernel Network Developers, nicolas.dichtel, netdev-owner
In-Reply-To: <20170114235333.GA13421@breakpoint.cc>
On 2017-01-15 01:53, Florian Westphal wrote:
> Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
>
> [ CC Nicolas since he also played with gc heuristics in the past ]
>
>> Sorry if i added someone wrongly to CC, please let me know, if i
>> should
>> remove.
>> I just run successfully 4.9 on my nat several days ago, and seems
>> panic
>> issue disappeared. But i started to face another issue, it seems
>> garbage
>> collector is hogging one of CPU's.
>>
>> It was handling load very well at 4.8 and below, it might be still
>> fine, but
>> i suspect queues that belong to hogged cpu might experience issues.
>
> The worker doesn't grab locks for long and calls scheduler for every
> bucket to give a chance for other threads to run.
>
> It also doesn't block softinterrupts.
>
>> Is there anything can be done to improve cpu load distribution or
>> reduce
>> single core load?
>
> No, I am afraid we don't export any of the heuristics as tuneables so
> far.
>
> You could try changing defaults in net/netfilter/nf_conntrack_core.c:
>
> #define GC_MAX_BUCKETS_DIV 64u
> /* upper bound of scan intervals */
> #define GC_INTERVAL_MAX (2 * HZ)
> /* maximum conntracks to evict per gc run */
> #define GC_MAX_EVICTS 256u
>
> (the first two result in ~2 minute worst case timeout detection
> on a fully idle system).
>
> For instance you could use
>
> GC_MAX_BUCKETS_DIV -> 128
> GC_INTERVAL_MAX -> 30 * HZ
>
> (This means that it takes one hour for a dead connection to be picked
> up on an idle system, but thats only relevant in case you use
> conntrack events to log when connection went down and need more
> precise
> accounting).
Not a big deal in my case.
>
> I suspect you might also have to change
>
> 1011 } else if (expired_count) {
> 1012 gc_work->next_gc_run /= 2U;
> 1013 next_run = msecs_to_jiffies(1);
> 1014 } else {
>
> line 2013 to
> next_run = msecs_to_jiffies(HZ / 2);
>
> or something like this to not have frequent rescans.
OK
>
> The gc is also done from the packet path (i.e. accounted
> towards (k)softirq).
>
> How many total connections is the machine handling on average?
> And how many new/delete events happen per second?
1-2 million connections, at current moment 988k
I dont know if it is correct method to measure events rate:
NAT ~ # timeout -t 5 conntrack -E -e NEW | wc -l
conntrack v1.4.2 (conntrack-tools): 40027 flow events have been shown.
40027
NAT ~ # timeout -t 5 conntrack -E -e DESTROY | wc -l
conntrack v1.4.2 (conntrack-tools): 40951 flow events have been shown.
40951
It is not peak time, so values can be 2-3 higher at peak time, but even
right now, it is hogging one core, leaving only 20% idle left,
while others are 80-83% idle.
>
>> 88.98% 0.00% kworker/24:1 [kernel.kallsyms] [k]
>> process_one_work
>> |
>> ---process_one_work
>> |
>> |--54.65%--gc_worker
>> | |
>> | --3.58%--nf_ct_gc_expired
>> | |
>> | |--1.90%--nf_ct_delete
>
> I'd be interested to see how often that shows up on other cores
> (from packet path).
Other CPU's totally different:
This is top entry
99.60% 0.00% swapper [kernel.kallsyms] [k] start_secondary
|
---start_secondary
|
--99.42%--cpu_startup_entry
|
--98.04%--default_idle_call
arch_cpu_idle
|
|--48.58%--call_function_single_interrupt
| |
|
--46.36%--smp_call_function_single_interrupt
|
smp_trace_call_function_single_interrupt
| |
|
|--44.18%--irq_exit
| | |
| |
|--43.37%--__do_softirq
| | |
|
| | |
--43.18%--net_rx_action
| | |
|
| | |
|--36.02%--process_backlog
| | |
| |
| | |
| --35.64%--__netif_receive_skb
gc_worker didnt appeared on other core at all.
Or i am checking something wrong?
^ permalink raw reply
* Re: 4.9 conntrack performance issues
From: Florian Westphal @ 2017-01-15 0:29 UTC (permalink / raw)
To: Denys Fedoryshchenko
Cc: Florian Westphal, Guillaume Nault, Netfilter Devel,
Pablo Neira Ayuso, Linux Kernel Network Developers,
nicolas.dichtel, netdev-owner
In-Reply-To: <d6dfdd8cf83933fc8f548da62a147775@nuclearcat.com>
Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
> On 2017-01-15 01:53, Florian Westphal wrote:
> >Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
> >
> >I suspect you might also have to change
> >
> >1011 } else if (expired_count) {
> >1012 gc_work->next_gc_run /= 2U;
> >1013 next_run = msecs_to_jiffies(1);
> >1014 } else {
> >
> >line 2013 to
> > next_run = msecs_to_jiffies(HZ / 2);
I think its wrong to rely on "expired_count", with these
kinds of numbers (up to 10k entries are scanned per round
in Denys setup, its basically always going to be > 0.
I think we should only decide to scan more frequently if
eviction ratio is large, say, we found more than 1/4 of
entries to be stale.
I sent a small patch offlist that does just that.
> >How many total connections is the machine handling on average?
> >And how many new/delete events happen per second?
> 1-2 million connections, at current moment 988k
> I dont know if it is correct method to measure events rate:
>
> NAT ~ # timeout -t 5 conntrack -E -e NEW | wc -l
> conntrack v1.4.2 (conntrack-tools): 40027 flow events have been shown.
> 40027
> NAT ~ # timeout -t 5 conntrack -E -e DESTROY | wc -l
> conntrack v1.4.2 (conntrack-tools): 40951 flow events have been shown.
> 40951
Thanks, thats exactly what I was looking for.
So I am not at all surprised that gc_worker eats cpu cycles...
> It is not peak time, so values can be 2-3 higher at peak time, but even
> right now, it is hogging one core, leaving only 20% idle left,
> while others are 80-83% idle.
I agree its a bug.
> >> |--54.65%--gc_worker
> >> | |
> >> | --3.58%--nf_ct_gc_expired
> >> | |
> >> | |--1.90%--nf_ct_delete
> >
> >I'd be interested to see how often that shows up on other cores
> >(from packet path).
> Other CPU's totally different:
> This is top entry
> 99.60% 0.00% swapper [kernel.kallsyms] [k] start_secondary
> |
> ---start_secondary
> |
> --99.42%--cpu_startup_entry
> |
[..]
> |--36.02%--process_backlog
> | | |
> | |
> | | |
> | --35.64%--__netif_receive_skb
>
> gc_worker didnt appeared on other core at all.
> Or i am checking something wrong?
Look for "nf_ct_gc_expired" and "nf_ct_delete".
Its going to be deep down in the call graph.
^ permalink raw reply
* [PATCH net-next] bpf, trace: make ctx access checks more robust
From: Daniel Borkmann @ 2017-01-15 0:34 UTC (permalink / raw)
To: davem; +Cc: alexei.starovoitov, netdev, Daniel Borkmann
Make sure that ctx cannot potentially be accessed oob by asserting
explicitly that ctx access size into pt_regs for BPF_PROG_TYPE_KPROBE
programs must be within limits. In case some 32bit archs have pt_regs
not being a multiple of 8, then BPF_DW access could cause such access.
BPF_PROG_TYPE_KPROBE progs don't have a ctx conversion function since
there's no extra mapping needed. kprobe_prog_is_valid_access() didn't
enforce sizeof(long) as the only allowed access size, since LLVM can
generate non BPF_W/BPF_DW access to regs from time to time.
For BPF_PROG_TYPE_TRACEPOINT we don't have a ctx conversion either, so
add a BUILD_BUG_ON() check to make sure that BPF_DW access will not be
a similar issue in future (ctx works on event buffer as opposed to
pt_regs there).
Fixes: 2541517c32be ("tracing, perf: Implement BPF programs attached to kprobes")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
( Applies to both, but net-next should be just okay. For the comment
I used kernel comment style as done throughout whole bpf_trace.c. )
kernel/trace/bpf_trace.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 1860e7f..81fbc86 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -459,6 +459,13 @@ static bool kprobe_prog_is_valid_access(int off, int size, enum bpf_access_type
return false;
if (off % size != 0)
return false;
+ /*
+ * Assertion for 32 bit to make sure last 8 byte access
+ * (BPF_DW) to the last 4 byte member is disallowed.
+ */
+ if (off + size > sizeof(struct pt_regs))
+ return false;
+
return true;
}
@@ -540,6 +547,8 @@ static bool tp_prog_is_valid_access(int off, int size, enum bpf_access_type type
return false;
if (off % size != 0)
return false;
+
+ BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(__u64));
return true;
}
--
2.5.5
^ permalink raw reply related
* Re: 4.9 conntrack performance issues
From: Denys Fedoryshchenko @ 2017-01-15 0:42 UTC (permalink / raw)
To: Florian Westphal
Cc: Guillaume Nault, Netfilter Devel, Pablo Neira Ayuso,
Linux Kernel Network Developers, nicolas.dichtel, netdev-owner
In-Reply-To: <20170115002936.GC13421@breakpoint.cc>
On 2017-01-15 02:29, Florian Westphal wrote:
> Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
>> On 2017-01-15 01:53, Florian Westphal wrote:
>> >Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
>> >
>> >I suspect you might also have to change
>> >
>> >1011 } else if (expired_count) {
>> >1012 gc_work->next_gc_run /= 2U;
>> >1013 next_run = msecs_to_jiffies(1);
>> >1014 } else {
>> >
>> >line 2013 to
>> > next_run = msecs_to_jiffies(HZ / 2);
>
> I think its wrong to rely on "expired_count", with these
> kinds of numbers (up to 10k entries are scanned per round
> in Denys setup, its basically always going to be > 0.
>
> I think we should only decide to scan more frequently if
> eviction ratio is large, say, we found more than 1/4 of
> entries to be stale.
>
> I sent a small patch offlist that does just that.
>
>> >How many total connections is the machine handling on average?
>> >And how many new/delete events happen per second?
>> 1-2 million connections, at current moment 988k
>> I dont know if it is correct method to measure events rate:
>>
>> NAT ~ # timeout -t 5 conntrack -E -e NEW | wc -l
>> conntrack v1.4.2 (conntrack-tools): 40027 flow events have been shown.
>> 40027
>> NAT ~ # timeout -t 5 conntrack -E -e DESTROY | wc -l
>> conntrack v1.4.2 (conntrack-tools): 40951 flow events have been shown.
>> 40951
>
> Thanks, thats exactly what I was looking for.
> So I am not at all surprised that gc_worker eats cpu cycles...
>
>> It is not peak time, so values can be 2-3 higher at peak time, but
>> even
>> right now, it is hogging one core, leaving only 20% idle left,
>> while others are 80-83% idle.
>
> I agree its a bug.
>
>> >> |--54.65%--gc_worker
>> >> | |
>> >> | --3.58%--nf_ct_gc_expired
>> >> | |
>> >> | |--1.90%--nf_ct_delete
>> >
>> >I'd be interested to see how often that shows up on other cores
>> >(from packet path).
>> Other CPU's totally different:
>> This is top entry
>> 99.60% 0.00% swapper [kernel.kallsyms] [k]
>> start_secondary
>> |
>> ---start_secondary
>> |
>> --99.42%--cpu_startup_entry
>> |
> [..]
>
>> |--36.02%--process_backlog
>> | |
>> |
>> | |
>> | |
>> |
>> | --35.64%--__netif_receive_skb
>>
>> gc_worker didnt appeared on other core at all.
>> Or i am checking something wrong?
>
> Look for "nf_ct_gc_expired" and "nf_ct_delete".
> Its going to be deep down in the call graph.
I tried my best to record as much data as possible, but it doesnt show
it in callgraph, just a little bit in statistics:
0.01% 0.00% swapper [nf_conntrack] [k]
nf_ct_delete
0.01% 0.00% swapper [nf_conntrack] [k]
nf_ct_gc_expired
And thats it.
^ permalink raw reply
* Re: [PATCH v5 05/13] net: ethernet: aquantia: Support for NIC-specific code
From: Andrew Lunn @ 2017-01-15 1:15 UTC (permalink / raw)
To: Rami Rosen
Cc: Florian Fainelli, Alexander Loktionov, Netdev, David VomLehn,
David S . Miller, Simon Edelhaus, Dmitrii Tarakanov, Pavel Belous,
Dmitry Bezrukov
In-Reply-To: <CAKoUArkh3gyVSrX1GWRQsrFFBg8B59LjtXK=yG6JWMHan7fW7A@mail.gmail.com>
On Sun, Jan 15, 2017 at 12:55:02AM +0200, Rami Rosen wrote:
> Hi, Florian,
>
> > +}
> > +
> > +static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu)
> > +{
> > + struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
> > + int err = 0;
> > +
> > + if (new_mtu == ndev->mtu) {
> > + err = 0;
> > + goto err_exit;
> > + }
> > + if (new_mtu < 68) {
> > + err = -EINVAL;
> > + goto err_exit;
> > + }
Actually, the core will already impose min/max of ETH_MIN_MTU and
ETH_DATA_LEN. See
commit a52ad514fdf3b8a57ca4322c92d2d8d5c6182485
Author: Jarod Wilson <jarod@redhat.com>
Date: Fri Oct 7 22:04:34 2016 -0400
net: deprecate eth_change_mtu, remove usage
With centralized MTU checking, there's nothing productive done by
eth_change_mtu that isn't already done in dev_set_mtu, so mark it as
deprecated and remove all usage of it in the kernel. All callers have been
audited for calls to alloc_etherdev* or ether_setup directly, which means
they all have a valid dev->min_mtu and dev->max_mtu. Now eth_change_mtu
prints out a netdev_warn about being deprecated, for the benefit of
out-of-tree drivers that might be utilizing it.
Of note, dvb_net.c actually had dev->mtu = 4096, while using
eth_change_mtu, meaning that if you ever tried changing it's mtu, you
couldn't set it above 1500 anymore. It's now getting dev->max_mtu also set
to 4096 to remedy that.
Andrew
^ permalink raw reply
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