lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Sun, 12 Jan 2020 20:53:19 -0800 From: Florian Fainelli <f.fainelli@...il.com> To: netdev@...r.kernel.org Cc: cphealy@...il.com, rmk+kernel@...linux.org.uk, kuba@...nel.org, Florian Fainelli <f.fainelli@...il.com>, Andrew Lunn <andrew@...n.ch>, Heiner Kallweit <hkallweit1@...il.com>, "David S. Miller" <davem@...emloft.net>, linux-kernel@...r.kernel.org (open list) Subject: [PATCH net-next] net: phy: Maintain MDIO device and bus statistics Maintain per MDIO device and MDIO bus statistics comprised of the number of transfers/operations, reads and writes and errors. This is useful for tracking the per-device and global MDIO bus bandwidth and doing optimizations as necessary. Signed-off-by: Florian Fainelli <f.fainelli@...il.com> --- Documentation/ABI/testing/sysfs-bus-mdio | 34 +++++++ drivers/net/phy/mdio_bus.c | 116 +++++++++++++++++++++++ drivers/net/phy/mdio_device.c | 1 + include/linux/mdio.h | 10 ++ include/linux/phy.h | 2 + 5 files changed, 163 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-mdio diff --git a/Documentation/ABI/testing/sysfs-bus-mdio b/Documentation/ABI/testing/sysfs-bus-mdio new file mode 100644 index 000000000000..a552d92890f1 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-mdio @@ -0,0 +1,34 @@ +What: /sys/bus/mdio_bus/devices/.../statistics/ +Date: January 2020 +KernelVersion: 5.6 +Contact: netdev@...r.kernel.org +Description: + This folder contains statistics about MDIO bus transactions. + +What: /sys/bus/mdio_bus/devices/.../statistics/transfers +Date: January 2020 +KernelVersion: 5.6 +Contact: netdev@...r.kernel.org +Description: + Total number of transfers for this MDIO bus. + +What: /sys/bus/mdio_bus/devices/.../statistics/errors +Date: January 2020 +KernelVersion: 5.6 +Contact: netdev@...r.kernel.org +Description: + Total number of transfer errors for this MDIO bus. + +What: /sys/bus/mdio_bus/devices/.../statistics/writes +Date: January 2020 +KernelVersion: 5.6 +Contact: netdev@...r.kernel.org +Description: + Total number of write transactions for this MDIO bus. + +What: /sys/bus/mdio_bus/devices/.../statistics/reads +Date: January 2020 +KernelVersion: 5.6 +Contact: netdev@...r.kernel.org +Description: + Total number of read transactions for this MDIO bus. diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 229e480179ff..805bc2e3b139 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -168,6 +168,9 @@ struct mii_bus *mdiobus_alloc_size(size_t size) for (i = 0; i < PHY_MAX_ADDR; i++) bus->irq[i] = PHY_POLL; + /* Initialize 64-bit seqcounts */ + u64_stats_init(&bus->stats.syncp); + return bus; } EXPORT_SYMBOL(mdiobus_alloc_size); @@ -255,9 +258,77 @@ static void mdiobus_release(struct device *d) kfree(bus); } +#define MDIO_BUS_STATS_ATTR(field, file) \ +static ssize_t mdio_bus_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct mii_bus *bus = to_mii_bus(dev); \ + return mdio_bus_stats_##field##_show(&bus->stats, buf); \ +} \ +static struct device_attribute dev_attr_mdio_bus_##field = { \ + .attr = { .name = file, .mode = 0444 }, \ + .show = mdio_bus_##field##_show, \ +}; \ +static ssize_t mdio_bus_device_##field##_show(struct device *dev, \ + struct device_attribute *attr,\ + char *buf) \ +{ \ + struct mdio_device *mdiodev = to_mdio_device(dev); \ + return mdio_bus_stats_##field##_show(&mdiodev->stats, buf); \ +} \ +static struct device_attribute dev_attr_mdio_bus_device_##field = { \ + .attr = { .name = file, .mode = 0444 }, \ + .show = mdio_bus_device_##field##_show, \ +} + +#define MDIO_BUS_STATS_SHOW_NAME(name, file, field, format_string) \ +static ssize_t mdio_bus_stats_##name##_show(struct mdio_bus_stats *s, \ + char *buf) \ +{ \ + unsigned int start; \ + ssize_t len; \ + u64 tmp; \ + do { \ + start = u64_stats_fetch_begin(&s->syncp); \ + tmp = u64_stats_read(&s->field); \ + } while (u64_stats_fetch_retry(&s->syncp, start)); \ + len = sprintf(buf, format_string ## "\n", tmp); \ + return len; \ +} \ +MDIO_BUS_STATS_ATTR(name, file) + +#define MDIO_BUS_STATS_SHOW(field, format_string) \ + MDIO_BUS_STATS_SHOW_NAME(field, __stringify(field), \ + field, format_string) + +MDIO_BUS_STATS_SHOW(transfers, "%llu"); +MDIO_BUS_STATS_SHOW(errors, "%llu"); +MDIO_BUS_STATS_SHOW(writes, "%llu"); +MDIO_BUS_STATS_SHOW(reads, "%llu"); + +static struct attribute *mdio_bus_statistics_attrs[] = { + &dev_attr_mdio_bus_transfers.attr, + &dev_attr_mdio_bus_errors.attr, + &dev_attr_mdio_bus_writes.attr, + &dev_attr_mdio_bus_reads.attr, + NULL, +}; + +static const struct attribute_group mdio_bus_statistics_group = { + .name = "statistics", + .attrs = mdio_bus_statistics_attrs, +}; + +static const struct attribute_group *mdio_bus_groups[] = { + &mdio_bus_statistics_group, + NULL, +}; + static struct class mdio_bus_class = { .name = "mdio_bus", .dev_release = mdiobus_release, + .dev_groups = mdio_bus_groups, }; #if IS_ENABLED(CONFIG_OF_MDIO) @@ -536,6 +607,24 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) } EXPORT_SYMBOL(mdiobus_scan); +static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret) +{ + u64_stats_update_begin(&stats->syncp); + + u64_stats_inc(&stats->transfers); + if (ret < 0) { + u64_stats_inc(&stats->errors); + goto out; + } + + if (op) + u64_stats_inc(&stats->reads); + else + u64_stats_inc(&stats->writes); +out: + u64_stats_update_end(&stats->syncp); +} + /** * __mdiobus_read - Unlocked version of the mdiobus_read function * @bus: the mii_bus struct @@ -548,6 +637,7 @@ EXPORT_SYMBOL(mdiobus_scan); */ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) { + struct mdio_device *mdiodev = bus->mdio_map[addr]; int retval; WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); @@ -555,6 +645,9 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) retval = bus->read(bus, addr, regnum); trace_mdio_access(bus, 1, addr, regnum, retval, retval); + mdiobus_stats_acct(&bus->stats, true, retval); + if (mdiodev) + mdiobus_stats_acct(&mdiodev->stats, true, retval); return retval; } @@ -573,6 +666,7 @@ EXPORT_SYMBOL(__mdiobus_read); */ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) { + struct mdio_device *mdiodev = bus->mdio_map[addr]; int err; WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); @@ -580,6 +674,9 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) err = bus->write(bus, addr, regnum, val); trace_mdio_access(bus, 0, addr, regnum, val, err); + mdiobus_stats_acct(&bus->stats, false, err); + if (mdiodev) + mdiobus_stats_acct(&mdiodev->stats, false, err); return err; } @@ -725,8 +822,27 @@ static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static struct attribute *mdio_bus_device_statistics_attrs[] = { + &dev_attr_mdio_bus_device_transfers.attr, + &dev_attr_mdio_bus_device_errors.attr, + &dev_attr_mdio_bus_device_writes.attr, + &dev_attr_mdio_bus_device_reads.attr, + NULL, +}; + +static const struct attribute_group mdio_bus_device_statistics_group = { + .name = "statistics", + .attrs = mdio_bus_device_statistics_attrs, +}; + +static const struct attribute_group *mdio_bus_dev_groups[] = { + &mdio_bus_device_statistics_group, + NULL, +}; + struct bus_type mdio_bus_type = { .name = "mdio_bus", + .dev_groups = mdio_bus_dev_groups, .match = mdio_bus_match, .uevent = mdio_uevent, }; diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index c1d345c3cab3..e89ed990de7d 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -53,6 +53,7 @@ struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr) if (!mdiodev) return ERR_PTR(-ENOMEM); + u64_stats_init(&mdiodev->stats.syncp); mdiodev->dev.release = mdio_device_release; mdiodev->dev.parent = &bus->dev; mdiodev->dev.bus = &mdio_bus_type; diff --git a/include/linux/mdio.h b/include/linux/mdio.h index a7604248777b..d6035d973a0d 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -8,6 +8,7 @@ #include <uapi/linux/mdio.h> #include <linux/mod_devicetable.h> +#include <linux/u64_stats_sync.h> struct gpio_desc; struct mii_bus; @@ -23,11 +24,20 @@ enum mdio_mutex_lock_class { MDIO_MUTEX_NESTED, }; +struct mdio_bus_stats { + struct u64_stats_sync syncp; + u64_stats_t transfers; + u64_stats_t errors; + u64_stats_t writes; + u64_stats_t reads; +}; + struct mdio_device { struct device dev; struct mii_bus *bus; char modalias[MDIO_NAME_SIZE]; + struct mdio_bus_stats stats; int (*bus_match)(struct device *dev, struct device_driver *drv); void (*device_free)(struct mdio_device *mdiodev); diff --git a/include/linux/phy.h b/include/linux/phy.h index 5932bb8e9c35..8d3ac1ebfef2 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -22,6 +22,7 @@ #include <linux/timer.h> #include <linux/workqueue.h> #include <linux/mod_devicetable.h> +#include <linux/u64_stats_sync.h> #include <linux/atomic.h> @@ -224,6 +225,7 @@ struct mii_bus { int (*read)(struct mii_bus *bus, int addr, int regnum); int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); int (*reset)(struct mii_bus *bus); + struct mdio_bus_stats stats; /* * A lock to ensure that only one thing can read/write -- 2.19.1
Powered by blists - more mailing lists