Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7d28c9d authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller
Browse files

net: dsa: b53: Add support for reading PHY statistics



Allow the b53 driver to return PHY statistics when the CPU port used is
different than 5, 7 or 8, because those are typically PHY-less on most
devices. This is useful for debugging link problems between the switch
and an external host when using a non standard CPU port number (e.g: 4).

Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cf963573
Loading
Loading
Loading
Loading
+68 −10
Original line number Diff line number Diff line
@@ -806,20 +806,39 @@ static unsigned int b53_get_mib_size(struct b53_device *dev)
		return B53_MIBS_SIZE;
}

static struct phy_device *b53_get_phy_device(struct dsa_switch *ds, int port)
{
	/* These ports typically do not have built-in PHYs */
	switch (port) {
	case B53_CPU_PORT_25:
	case 7:
	case B53_CPU_PORT:
		return NULL;
	}

	return mdiobus_get_phy(ds->slave_mii_bus, port);
}

void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
		     uint8_t *data)
{
	struct b53_device *dev = ds->priv;
	const struct b53_mib_desc *mibs = b53_get_mib(dev);
	unsigned int mib_size = b53_get_mib_size(dev);
	struct phy_device *phydev;
	unsigned int i;

	if (stringset != ETH_SS_STATS)
		return;

	if (stringset == ETH_SS_STATS) {
		for (i = 0; i < mib_size; i++)
			strlcpy(data + i * ETH_GSTRING_LEN,
				mibs[i].name, ETH_GSTRING_LEN);
	} else if (stringset == ETH_SS_PHY_STATS) {
		phydev = b53_get_phy_device(ds, port);
		if (!phydev)
			return;

		phy_ethtool_get_strings(phydev, data);
	}
}
EXPORT_SYMBOL(b53_get_strings);

@@ -856,14 +875,34 @@ void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
}
EXPORT_SYMBOL(b53_get_ethtool_stats);

void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
	struct phy_device *phydev;

	phydev = b53_get_phy_device(ds, port);
	if (!phydev)
		return;

	phy_ethtool_get_stats(phydev, NULL, data);
}
EXPORT_SYMBOL(b53_get_ethtool_phy_stats);

int b53_get_sset_count(struct dsa_switch *ds, int port, int sset)
{
	struct b53_device *dev = ds->priv;
	struct phy_device *phydev;

	if (sset != ETH_SS_STATS)
	if (sset == ETH_SS_STATS) {
		return b53_get_mib_size(dev);
	} else if (sset == ETH_SS_PHY_STATS) {
		phydev = b53_get_phy_device(ds, port);
		if (!phydev)
			return 0;

	return b53_get_mib_size(dev);
		return phy_ethtool_get_sset_count(phydev);
	}

	return 0;
}
EXPORT_SYMBOL(b53_get_sset_count);

@@ -1484,7 +1523,7 @@ void b53_br_fast_age(struct dsa_switch *ds, int port)
}
EXPORT_SYMBOL(b53_br_fast_age);

static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port)
static bool b53_possible_cpu_port(struct dsa_switch *ds, int port)
{
	/* Broadcom switches will accept enabling Broadcom tags on the
	 * following ports: 5, 7 and 8, any other port is not supported
@@ -1496,10 +1535,19 @@ static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port)
		return true;
	}

	dev_warn(ds->dev, "Port %d is not Broadcom tag capable\n", port);
	return false;
}

static bool b53_can_enable_brcm_tags(struct dsa_switch *ds, int port)
{
	bool ret = b53_possible_cpu_port(ds, port);

	if (!ret)
		dev_warn(ds->dev, "Port %d is not Broadcom tag capable\n",
			 port);
	return ret;
}

enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port)
{
	struct b53_device *dev = ds->priv;
@@ -1657,6 +1705,7 @@ static const struct dsa_switch_ops b53_switch_ops = {
	.get_strings		= b53_get_strings,
	.get_ethtool_stats	= b53_get_ethtool_stats,
	.get_sset_count		= b53_get_sset_count,
	.get_ethtool_phy_stats	= b53_get_ethtool_phy_stats,
	.phy_read		= b53_phy_read16,
	.phy_write		= b53_phy_write16,
	.adjust_link		= b53_adjust_link,
@@ -1961,6 +2010,15 @@ static int b53_switch_init(struct b53_device *dev)
	dev->num_ports = dev->cpu_port + 1;
	dev->enabled_ports |= BIT(dev->cpu_port);

	/* Include non standard CPU port built-in PHYs to be probed */
	if (is539x(dev) || is531x5(dev)) {
		for (i = 0; i < dev->num_ports; i++) {
			if (!(dev->ds->phys_mii_mask & BIT(i)) &&
			    !b53_possible_cpu_port(dev->ds, i))
				dev->ds->phys_mii_mask |= BIT(i);
		}
	}

	dev->ports = devm_kzalloc(dev->dev,
				  sizeof(struct b53_port) * dev->num_ports,
				  GFP_KERNEL);
+1 −0
Original line number Diff line number Diff line
@@ -290,6 +290,7 @@ void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
		     uint8_t *data);
void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
int b53_get_sset_count(struct dsa_switch *ds, int port, int sset);
void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data);
int b53_br_join(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *bridge);
void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state);
+1 −0
Original line number Diff line number Diff line
@@ -859,6 +859,7 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
	.get_strings		= b53_get_strings,
	.get_ethtool_stats	= b53_get_ethtool_stats,
	.get_sset_count		= b53_get_sset_count,
	.get_ethtool_phy_stats	= b53_get_ethtool_phy_stats,
	.get_phy_flags		= bcm_sf2_sw_get_phy_flags,
	.adjust_link		= bcm_sf2_sw_adjust_link,
	.fixed_link_update	= bcm_sf2_sw_fixed_link_update,