* values are invalid, set speed and duplex to -1,
* and return. Return 1 if speed or duplex settings are
* UNKNOWN; 0 otherwise.
+ *
+ * Caller must hold the slave's netdev ops lock. The notifier path
+ * (bond_netdev_event NETDEV_CHANGE/UP) reaches us with the slave's ops
+ * lock held; other call sites take it explicitly.
*/
static int bond_update_speed_duplex(struct slave *slave)
{
struct ethtool_link_ksettings ecmd;
int res;
- res = __ethtool_get_link_ksettings(slave_dev, &ecmd);
+ res = netif_get_link_ksettings(slave_dev, &ecmd);
if (res < 0)
goto speed_duplex_unknown;
if (ecmd.base.speed == 0 || ecmd.base.speed == ((__u32)-1))
new_slave->delay = 0;
new_slave->link_failure_count = 0;
- if (bond_update_speed_duplex(new_slave) &&
- bond_needs_speed_duplex(bond))
+ netdev_lock_ops(slave_dev);
+ res = bond_update_speed_duplex(new_slave);
+ netdev_unlock_ops(slave_dev);
+ if (res && bond_needs_speed_duplex(bond))
new_slave->link = BOND_LINK_DOWN;
new_slave->last_rx = jiffies -
struct slave *slave, *primary, *active;
bool do_failover = false;
struct list_head *iter;
+ int err;
ASSERT_RTNL();
continue;
case BOND_LINK_UP:
- if (bond_update_speed_duplex(slave) &&
- bond_needs_speed_duplex(bond)) {
+ netdev_lock_ops(slave->dev);
+ err = bond_update_speed_duplex(slave);
+ netdev_unlock_ops(slave->dev);
+ if (err && bond_needs_speed_duplex(bond)) {
slave->link = BOND_LINK_DOWN;
if (net_ratelimit())
slave_warn(bond->dev, slave->dev,
*/
bond_for_each_slave(bond, slave, iter) {
if (bond_slave_can_tx(slave)) {
+ netdev_lock_ops(slave->dev);
bond_update_speed_duplex(slave);
+ netdev_unlock_ops(slave->dev);
if (slave->speed != SPEED_UNKNOWN) {
if (BOND_MODE(bond) == BOND_MODE_BROADCAST)
speed = bond_mode_bcast_speed(slave,