|
@@ -806,20 +806,39 @@ static unsigned int b53_get_mib_size(struct b53_device *dev)
|
|
return B53_MIBS_SIZE;
|
|
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,
|
|
void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
|
|
uint8_t *data)
|
|
uint8_t *data)
|
|
{
|
|
{
|
|
struct b53_device *dev = ds->priv;
|
|
struct b53_device *dev = ds->priv;
|
|
const struct b53_mib_desc *mibs = b53_get_mib(dev);
|
|
const struct b53_mib_desc *mibs = b53_get_mib(dev);
|
|
unsigned int mib_size = b53_get_mib_size(dev);
|
|
unsigned int mib_size = b53_get_mib_size(dev);
|
|
|
|
+ struct phy_device *phydev;
|
|
unsigned int i;
|
|
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;
|
|
|
|
|
|
- for (i = 0; i < mib_size; i++)
|
|
|
|
- strlcpy(data + i * ETH_GSTRING_LEN,
|
|
|
|
- mibs[i].name, ETH_GSTRING_LEN);
|
|
|
|
|
|
+ phy_ethtool_get_strings(phydev, data);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(b53_get_strings);
|
|
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);
|
|
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)
|
|
int b53_get_sset_count(struct dsa_switch *ds, int port, int sset)
|
|
{
|
|
{
|
|
struct b53_device *dev = ds->priv;
|
|
struct b53_device *dev = ds->priv;
|
|
|
|
+ struct phy_device *phydev;
|
|
|
|
|
|
- if (sset != ETH_SS_STATS)
|
|
|
|
- return 0;
|
|
|
|
|
|
+ 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 phy_ethtool_get_sset_count(phydev);
|
|
|
|
+ }
|
|
|
|
|
|
- return b53_get_mib_size(dev);
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(b53_get_sset_count);
|
|
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);
|
|
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
|
|
/* Broadcom switches will accept enabling Broadcom tags on the
|
|
* following ports: 5, 7 and 8, any other port is not supported
|
|
* 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;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- dev_warn(ds->dev, "Port %d is not Broadcom tag capable\n", port);
|
|
|
|
return false;
|
|
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)
|
|
enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port)
|
|
{
|
|
{
|
|
struct b53_device *dev = ds->priv;
|
|
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_strings = b53_get_strings,
|
|
.get_ethtool_stats = b53_get_ethtool_stats,
|
|
.get_ethtool_stats = b53_get_ethtool_stats,
|
|
.get_sset_count = b53_get_sset_count,
|
|
.get_sset_count = b53_get_sset_count,
|
|
|
|
+ .get_ethtool_phy_stats = b53_get_ethtool_phy_stats,
|
|
.phy_read = b53_phy_read16,
|
|
.phy_read = b53_phy_read16,
|
|
.phy_write = b53_phy_write16,
|
|
.phy_write = b53_phy_write16,
|
|
.adjust_link = b53_adjust_link,
|
|
.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->num_ports = dev->cpu_port + 1;
|
|
dev->enabled_ports |= BIT(dev->cpu_port);
|
|
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,
|
|
dev->ports = devm_kzalloc(dev->dev,
|
|
sizeof(struct b53_port) * dev->num_ports,
|
|
sizeof(struct b53_port) * dev->num_ports,
|
|
GFP_KERNEL);
|
|
GFP_KERNEL);
|