|
@@ -4226,6 +4226,37 @@ void bond_set_mode_ops(struct bonding *bond, int mode)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int bond_ethtool_get_settings(struct net_device *bond_dev,
|
|
|
+ struct ethtool_cmd *ecmd)
|
|
|
+{
|
|
|
+ struct bonding *bond = netdev_priv(bond_dev);
|
|
|
+ struct slave *slave;
|
|
|
+ int i;
|
|
|
+ unsigned long speed = 0;
|
|
|
+
|
|
|
+ ecmd->duplex = DUPLEX_UNKNOWN;
|
|
|
+ ecmd->port = PORT_OTHER;
|
|
|
+
|
|
|
+ /* Since SLAVE_IS_OK returns false for all inactive or down slaves, we
|
|
|
+ * do not need to check mode. Though link speed might not represent
|
|
|
+ * the true receive or transmit bandwidth (not all modes are symmetric)
|
|
|
+ * this is an accurate maximum.
|
|
|
+ */
|
|
|
+ read_lock(&bond->lock);
|
|
|
+ bond_for_each_slave(bond, slave, i) {
|
|
|
+ if (SLAVE_IS_OK(slave)) {
|
|
|
+ if (slave->speed != SPEED_UNKNOWN)
|
|
|
+ speed += slave->speed;
|
|
|
+ if (ecmd->duplex == DUPLEX_UNKNOWN &&
|
|
|
+ slave->duplex != DUPLEX_UNKNOWN)
|
|
|
+ ecmd->duplex = slave->duplex;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ethtool_cmd_speed_set(ecmd, speed ? : SPEED_UNKNOWN);
|
|
|
+ read_unlock(&bond->lock);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
|
|
|
struct ethtool_drvinfo *drvinfo)
|
|
|
{
|
|
@@ -4237,6 +4268,7 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
|
|
|
|
|
|
static const struct ethtool_ops bond_ethtool_ops = {
|
|
|
.get_drvinfo = bond_ethtool_get_drvinfo,
|
|
|
+ .get_settings = bond_ethtool_get_settings,
|
|
|
.get_link = ethtool_op_get_link,
|
|
|
};
|
|
|
|