Commit ed0abfe9 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'net-phy-improve-stats-handling-in-mdio_bus-c'

Heiner Kallweit says:

====================
net: phy: improve stats handling in mdio_bus.c

Improve stats handling in mdio_bus.c.
====================

Link: https://patch.msgid.link/799114be-1456-442b-b479-142e7ee9d254@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents e07bd1f7 1afccc5a
Loading
Loading
Loading
Loading
+46 −78
Original line number Diff line number Diff line
@@ -124,52 +124,47 @@ static void mdiobus_release(struct device *d)
}

struct mdio_bus_stat_attr {
	int addr;
	struct device_attribute attr;
	int address;
	unsigned int field_offset;
};

static struct mdio_bus_stat_attr *to_sattr(struct device_attribute *attr)
{
	return container_of(attr, struct mdio_bus_stat_attr, attr);
}

static u64 mdio_bus_get_stat(struct mdio_bus_stats *s, unsigned int offset)
{
	const char *p = (const char *)s + offset;
	const u64_stats_t *stats = (const void *)s + offset;
	unsigned int start;
	u64 val = 0;

	do {
		start = u64_stats_fetch_begin(&s->syncp);
		val = u64_stats_read((const u64_stats_t *)p);
		val = u64_stats_read(stats);
	} while (u64_stats_fetch_retry(&s->syncp, start));

	return val;
}

static u64 mdio_bus_get_global_stat(struct mii_bus *bus, unsigned int offset)
{
	unsigned int i;
	u64 val = 0;

	for (i = 0; i < PHY_MAX_ADDR; i++)
		val += mdio_bus_get_stat(&bus->stats[i], offset);

	return val;
}

static ssize_t mdio_bus_stat_field_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct mdio_bus_stat_attr *sattr = to_sattr(attr);
	struct mii_bus *bus = to_mii_bus(dev);
	struct mdio_bus_stat_attr *sattr;
	struct dev_ext_attribute *eattr;
	u64 val;

	eattr = container_of(attr, struct dev_ext_attribute, attr);
	sattr = eattr->var;
	u64 val = 0;

	if (sattr->addr < 0)
		val = mdio_bus_get_global_stat(bus, sattr->field_offset);
	else
		val = mdio_bus_get_stat(&bus->stats[sattr->addr],
	if (sattr->address < 0) {
		/* get global stats */
		for (int i = 0; i < PHY_MAX_ADDR; i++)
			val += mdio_bus_get_stat(&bus->stats[i],
						 sattr->field_offset);
	} else {
		val = mdio_bus_get_stat(&bus->stats[sattr->address],
					sattr->field_offset);
	}

	return sysfs_emit(buf, "%llu\n", val);
}
@@ -178,41 +173,27 @@ static ssize_t mdio_bus_device_stat_field_show(struct device *dev,
					       struct device_attribute *attr,
					       char *buf)
{
	struct mdio_bus_stat_attr *sattr = to_sattr(attr);
	struct mdio_device *mdiodev = to_mdio_device(dev);
	struct mii_bus *bus = mdiodev->bus;
	struct mdio_bus_stat_attr *sattr;
	struct dev_ext_attribute *eattr;
	int addr = mdiodev->addr;
	u64 val;

	eattr = container_of(attr, struct dev_ext_attribute, attr);
	sattr = eattr->var;

	val = mdio_bus_get_stat(&bus->stats[addr], sattr->field_offset);

	return sysfs_emit(buf, "%llu\n", val);
}

#define MDIO_BUS_STATS_ATTR_DECL(field, file)				\
static struct dev_ext_attribute dev_attr_mdio_bus_##field = {		\
	.attr = { .attr = { .name = file, .mode = 0444 },		\
		     .show = mdio_bus_stat_field_show,			\
	},								\
	.var = &((struct mdio_bus_stat_attr) {				\
		-1, offsetof(struct mdio_bus_stats, field)		\
	}),								\
};									\
static struct dev_ext_attribute dev_attr_mdio_bus_device_##field = {	\
	.attr = { .attr = { .name = file, .mode = 0444 },		\
		     .show = mdio_bus_device_stat_field_show,		\
	},								\
	.var = &((struct mdio_bus_stat_attr) {				\
		-1, offsetof(struct mdio_bus_stats, field)		\
	}),								\
};

#define MDIO_BUS_STATS_ATTR(field)					\
	MDIO_BUS_STATS_ATTR_DECL(field, __stringify(field))
static const struct mdio_bus_stat_attr dev_attr_mdio_bus_##field = {	\
	.attr = __ATTR(field, 0444, mdio_bus_stat_field_show, NULL),	\
	.address = -1,							\
	.field_offset = offsetof(struct mdio_bus_stats, field),		\
};									\
static const struct mdio_bus_stat_attr dev_attr_mdio_bus_device_##field = { \
	.attr = __ATTR(field, 0444, mdio_bus_device_stat_field_show, NULL), \
	.field_offset = offsetof(struct mdio_bus_stats, field),		\
}

MDIO_BUS_STATS_ATTR(transfers);
MDIO_BUS_STATS_ATTR(errors);
@@ -220,13 +201,13 @@ MDIO_BUS_STATS_ATTR(writes);
MDIO_BUS_STATS_ATTR(reads);

#define MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, file)		\
static struct dev_ext_attribute dev_attr_mdio_bus_addr_##field##_##addr = { \
static const struct mdio_bus_stat_attr					\
dev_attr_mdio_bus_addr_##field##_##addr = {				\
	.attr = { .attr = { .name = file, .mode = 0444 },		\
		     .show = mdio_bus_stat_field_show,			\
	},								\
	.var = &((struct mdio_bus_stat_attr) {				\
		addr, offsetof(struct mdio_bus_stats, field)		\
	}),								\
	.address = addr,						\
	.field_offset = offsetof(struct mdio_bus_stats, field),		\
}

#define MDIO_BUS_STATS_ADDR_ATTR(field, addr)				\
@@ -278,7 +259,7 @@ MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(31);
	&dev_attr_mdio_bus_addr_writes_##addr.attr.attr,		\
	&dev_attr_mdio_bus_addr_reads_##addr.attr.attr			\

static struct attribute *mdio_bus_statistics_attrs[] = {
static const struct attribute *const mdio_bus_statistics_attrs[] = {
	&dev_attr_mdio_bus_transfers.attr.attr,
	&dev_attr_mdio_bus_errors.attr.attr,
	&dev_attr_mdio_bus_writes.attr.attr,
@@ -320,18 +301,14 @@ static struct attribute *mdio_bus_statistics_attrs[] = {

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,
	.attrs_const	= mdio_bus_statistics_attrs,
};
__ATTRIBUTE_GROUPS(mdio_bus_statistics);

const struct class mdio_bus_class = {
	.name		= "mdio_bus",
	.dev_release	= mdiobus_release,
	.dev_groups	= mdio_bus_groups,
	.dev_groups	= mdio_bus_statistics_groups,
};
EXPORT_SYMBOL_GPL(mdio_bus_class);

@@ -381,22 +358,17 @@ EXPORT_SYMBOL(of_mdio_find_bus);

static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret)
{
	preempt_disable();
	u64_stats_update_begin(&stats->syncp);

	u64_stats_inc(&stats->transfers);
	if (ret < 0) {
	if (ret < 0)
		u64_stats_inc(&stats->errors);
		goto out;
	}

	if (op)
	else if (op)
		u64_stats_inc(&stats->reads);
	else
		u64_stats_inc(&stats->writes);
out:

	u64_stats_update_end(&stats->syncp);
	preempt_enable();
}

/**
@@ -986,7 +958,7 @@ static int mdio_uevent(const struct device *dev, struct kobj_uevent_env *env)
	return 0;
}

static struct attribute *mdio_bus_device_statistics_attrs[] = {
static const struct attribute *const mdio_bus_device_statistics_attrs[] = {
	&dev_attr_mdio_bus_device_transfers.attr.attr,
	&dev_attr_mdio_bus_device_errors.attr.attr,
	&dev_attr_mdio_bus_device_writes.attr.attr,
@@ -996,17 +968,13 @@ static struct attribute *mdio_bus_device_statistics_attrs[] = {

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,
	.attrs_const	= mdio_bus_device_statistics_attrs,
};
__ATTRIBUTE_GROUPS(mdio_bus_device_statistics);

const struct bus_type mdio_bus_type = {
	.name		= "mdio_bus",
	.dev_groups	= mdio_bus_dev_groups,
	.dev_groups	= mdio_bus_device_statistics_groups,
	.match		= mdio_bus_match,
	.uevent		= mdio_uevent,
};