diff --git a/Documentation/networking/netdevices.rst b/Documentation/networking/netdevices.rst index 60492d4df2ee..8fc96975b3bd 100644 --- a/Documentation/networking/netdevices.rst +++ b/Documentation/networking/netdevices.rst @@ -415,6 +415,7 @@ The following netdev notifiers are always run under the instance lock: For devices with locked ops, currently only the following notifiers are running under the lock: * ``NETDEV_CHANGE`` +* ``NETDEV_CHANGENAME`` * ``NETDEV_REGISTER`` * ``NETDEV_UP`` diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 12cb3311ea22..64c078e997f2 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "../leds.h" #define NETDEV_LED_DEFAULT_INTERVAL 50 @@ -228,7 +229,7 @@ static void get_device_state(struct led_netdev_data *trigger_data) trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); - if (__ethtool_get_link_ksettings(trigger_data->net_dev, &cmd)) + if (netif_get_link_ksettings(trigger_data->net_dev, &cmd)) return; if (trigger_data->carrier_link_up) { @@ -259,31 +260,33 @@ static ssize_t device_name_show(struct device *dev, static int set_device_name(struct led_netdev_data *trigger_data, const char *name, size_t size) { + struct net_device *new_dev = NULL; + char device_name[IFNAMSIZ]; + if (size >= IFNAMSIZ) return -EINVAL; cancel_delayed_work_sync(&trigger_data->work); + memcpy(device_name, name, size); + device_name[size] = 0; + if (size > 0 && device_name[size - 1] == '\n') + device_name[size - 1] = 0; + /* - * Take RTNL lock before trigger_data lock to prevent potential - * deadlock with netdev notifier registration. + * Lock order: rtnl_lock -> netdev instance lock -> trigger_data lock. */ rtnl_lock(); + if (device_name[0]) { + new_dev = dev_get_by_name(&init_net, device_name); + if (new_dev) + netdev_lock_ops(new_dev); + } mutex_lock(&trigger_data->lock); - if (trigger_data->net_dev) { - dev_put(trigger_data->net_dev); - trigger_data->net_dev = NULL; - } - - memcpy(trigger_data->device_name, name, size); - trigger_data->device_name[size] = 0; - if (size > 0 && trigger_data->device_name[size - 1] == '\n') - trigger_data->device_name[size - 1] = 0; - - if (trigger_data->device_name[0] != 0) - trigger_data->net_dev = - dev_get_by_name(&init_net, trigger_data->device_name); + dev_put(trigger_data->net_dev); + trigger_data->net_dev = new_dev; + strscpy(trigger_data->device_name, device_name); trigger_data->carrier_link_up = false; trigger_data->link_speed = SPEED_UNKNOWN; @@ -298,6 +301,8 @@ static int set_device_name(struct led_netdev_data *trigger_data, set_baseline_state(trigger_data); mutex_unlock(&trigger_data->lock); + if (new_dev) + netdev_unlock_ops(new_dev); rtnl_unlock(); return 0; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 82e779f7916b..0bcab797e468 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -787,6 +787,10 @@ int bond_set_carrier(struct bonding *bond) * 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) { @@ -794,7 +798,7 @@ 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)) @@ -2112,8 +2116,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, 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 - @@ -2780,6 +2786,7 @@ static void bond_miimon_commit(struct bonding *bond) struct slave *slave, *primary, *active; bool do_failover = false; struct list_head *iter; + int err; ASSERT_RTNL(); @@ -2798,8 +2805,10 @@ static void bond_miimon_commit(struct bonding *bond) 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, @@ -5861,7 +5870,9 @@ static int bond_ethtool_get_link_ksettings(struct net_device *bond_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, diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 3587f39202d2..2402cc865e76 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -16762,7 +16762,7 @@ int bnxt_restore_pf_fw_resources(struct bnxt *bp) { int rc; - netdev_ops_assert_locked(bp->dev); + netdev_assert_locked_ops_compat(bp->dev); bnxt_hwrm_func_qcaps(bp); if (netif_running(bp->dev)) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index f51388d50307..feaa75fbf8fc 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -1375,7 +1375,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev, list_add_tail_rcu(&port->list, &team->port_list); team_port_enable(team, port); netdev_compute_master_upper_features(dev, true); + netdev_lock_ops(port_dev); __team_port_change_port_added(port, !!netif_oper_up(port_dev)); + netdev_unlock_ops(port_dev); __team_options_change_check(team); netdev_info(dev, "Port device %s added\n", portname); @@ -3090,7 +3092,7 @@ static void __team_port_change_send(struct team_port *port, bool linkup) if (linkup) { struct ethtool_link_ksettings ecmd; - err = __ethtool_get_link_ksettings(port->dev, &ecmd); + err = netif_get_link_ksettings(port->dev, &ecmd); if (!err) { port->state.speed = ecmd.base.speed; port->state.duplex = ecmd.base.duplex; diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 26e0ff380860..c95b084cad69 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -17,6 +17,7 @@ #include "bnx2fc.h" #include +#include static struct list_head adapter_list; static struct list_head if_list; @@ -815,7 +816,9 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) port->fcoe_pending_queue_active = 0; timer_setup(&port->timer, fcoe_queue_timer, 0); + netdev_lock_ops(netdev); fcoe_link_speed_update(lport); + netdev_unlock_ops(netdev); if (!lport->vport) { if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 534596c6d76c..438ac7c3a9e3 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -737,7 +738,9 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) port->fcoe_pending_queue_active = 0; timer_setup(&port->timer, fcoe_queue_timer, 0); + netdev_lock_ops(netdev); fcoe_link_speed_update(lport); + netdev_unlock_ops(netdev); if (!lport->vport) { if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) @@ -1841,6 +1844,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, break; case NETDEV_UP: case NETDEV_CHANGE: + fcoe_link_speed_update(lport); break; case NETDEV_CHANGEMTU: if (netdev->fcoe_mtu) @@ -1871,8 +1875,6 @@ static int fcoe_device_notification(struct notifier_block *notifier, "from netdev netlink\n", event); } - fcoe_link_speed_update(lport); - cdev = fcoe_ctlr_to_ctlr_dev(ctlr); if (link_possible && !fcoe_link_ok(lport)) { diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index 88d85fc9a52a..2bbb9a38e61d 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -111,6 +111,8 @@ static inline u32 eth2fc_speed(u32 eth_port_speed) * fcoe_link_speed_update() - Update the supported and actual link speeds * @lport: The local port to update speeds for * + * Caller must hold the netdev's ops lock. + * * Returns: 0 if the ethtool query was successful * -1 if the ethtool query failed */ @@ -119,7 +121,7 @@ int fcoe_link_speed_update(struct fc_lport *lport) struct net_device *netdev = fcoe_get_netdev(lport); struct ethtool_link_ksettings ecmd; - if (!__ethtool_get_link_ksettings(netdev, &ecmd)) { + if (!netif_get_link_ksettings(netdev, &ecmd)) { lport->link_supported_speeds &= ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT | FC_PORTSPEED_20GBIT | diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 1cb0740ba331..f51346a6a686 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -325,6 +325,8 @@ struct ethtool_link_ksettings { extern int __ethtool_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *link_ksettings); +int netif_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *link_ksettings); struct ethtool_keee { __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); diff --git a/include/net/netdev_lock.h b/include/net/netdev_lock.h index 3d3aef80beac..d3daec4e93f3 100644 --- a/include/net/netdev_lock.h +++ b/include/net/netdev_lock.h @@ -64,7 +64,7 @@ static inline void netdev_unlock_full_to_ops(struct net_device *dev) netdev_unlock(dev); } -static inline void netdev_ops_assert_locked(const struct net_device *dev) +static inline void netdev_assert_locked_ops_compat(const struct net_device *dev) { if (netdev_need_ops_lock(dev)) lockdep_assert_held(&dev->lock); @@ -73,11 +73,17 @@ static inline void netdev_ops_assert_locked(const struct net_device *dev) } static inline void -netdev_ops_assert_locked_or_invisible(const struct net_device *dev) +netdev_assert_locked_ops_compat_or_invisible(const struct net_device *dev) { if (dev->reg_state == NETREG_REGISTERED || dev->reg_state == NETREG_UNREGISTERING) - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); +} + +static inline void netdev_assert_locked_ops(const struct net_device *dev) +{ + if (netdev_need_ops_lock(dev)) + netdev_assert_locked(dev); } static inline void netdev_lock_ops_compat(struct net_device *dev) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index d39571e13744..049d1d25bc26 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -30,13 +31,13 @@ * Determine initial path cost based on speed. * using recommendations from 802.1d standard * - * Since driver might sleep need to not be holding any locks. + * Since driver might sleep, we need to not be holding any bridge spinlocks. */ static int port_cost(struct net_device *dev) { struct ethtool_link_ksettings ecmd; - if (!__ethtool_get_link_ksettings(dev, &ecmd)) { + if (!netif_get_link_ksettings(dev, &ecmd)) { switch (ecmd.base.speed) { case SPEED_10000: return 2; @@ -436,7 +437,9 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->br = br; netdev_hold(dev, &p->dev_tracker, GFP_KERNEL); p->dev = dev; + netdev_lock_ops(dev); p->path_cost = port_cost(dev); + netdev_unlock_ops(dev); p->priority = 0x8000 >> BR_PORT_BITS; p->port_no = index; p->flags = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; diff --git a/net/core/dev.c b/net/core/dev.c index 804e8ad25010..1ecd5691992e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1593,7 +1593,7 @@ EXPORT_SYMBOL(netdev_features_change); void netif_state_change(struct net_device *dev) { - netdev_ops_assert_locked_or_invisible(dev); + netdev_assert_locked_ops_compat_or_invisible(dev); if (dev->flags & IFF_UP) { struct netdev_notifier_change_info change_info = { @@ -1693,7 +1693,7 @@ static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack) set_bit(__LINK_STATE_START, &dev->state); - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (ops->ndo_validate_addr) ret = ops->ndo_validate_addr(dev); @@ -1770,7 +1770,7 @@ static void __dev_close_many(struct list_head *head) * event. */ - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (ops->ndo_stop) ops->ndo_stop(dev); @@ -3198,7 +3198,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) if (dev->reg_state == NETREG_REGISTERED || dev->reg_state == NETREG_UNREGISTERING) { - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues, txq); @@ -3247,7 +3247,7 @@ int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq) return -EINVAL; if (dev->reg_state == NETREG_REGISTERED) { - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues, rxq); @@ -7294,7 +7294,7 @@ void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index, if (WARN_ON_ONCE(napi && !napi->dev)) return; - netdev_ops_assert_locked_or_invisible(dev); + netdev_assert_locked_ops_compat_or_invisible(dev); switch (type) { case NETDEV_QUEUE_TYPE_RX: @@ -9589,7 +9589,7 @@ int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify) kuid_t uid; kgid_t gid; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); promiscuity = dev->promiscuity + inc; if (promiscuity == 0) { @@ -9648,7 +9648,7 @@ int netif_set_allmulti(struct net_device *dev, int inc, bool notify) unsigned int old_flags = dev->flags, old_gflags = dev->gflags; unsigned int allmulti, flags; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); allmulti = dev->allmulti + inc; if (allmulti == 0) { @@ -9716,7 +9716,7 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags, unsigned int old_flags = dev->flags; int ret; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); /* * Set the flags on our device. @@ -9864,7 +9864,7 @@ int netif_set_mtu_ext(struct net_device *dev, int new_mtu, { int err, orig_mtu; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (new_mtu == dev->mtu) return 0; @@ -10317,7 +10317,7 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode, struct netdev_bpf xdp; int err; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED && prog && !prog->aux->xdp_has_frags) { @@ -10769,7 +10769,7 @@ u32 dev_get_min_mp_channel_count(const struct net_device *dev) { int i; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); for (i = dev->real_num_rx_queues - 1; i >= 0; i--) if (dev->_rx[i].mp_params.mp_priv) @@ -10997,7 +10997,7 @@ int __netdev_update_features(struct net_device *dev) int err = -1; ASSERT_RTNL(); - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); features = netdev_get_wanted_features(dev); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index d73fcb0c6785..6b493af8dc8b 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -1260,7 +1260,7 @@ static void netif_rx_mode_run(struct net_device *dev) int err; might_sleep(); - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); __hw_addr_init(&uc_snap); __hw_addr_init(&mc_snap); diff --git a/net/core/link_watch.c b/net/core/link_watch.c index ff2c1d4538ef..9c35aac8b2e9 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -277,7 +277,7 @@ static bool linkwatch_clean_dev(struct net_device *dev) void __linkwatch_sync_dev(struct net_device *dev) { - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (linkwatch_clean_dev(dev)) { linkwatch_do_dev(dev); diff --git a/net/core/lock_debug.c b/net/core/lock_debug.c index 9e9fb25314b9..8a81c5430705 100644 --- a/net/core/lock_debug.c +++ b/net/core/lock_debug.c @@ -24,7 +24,7 @@ int netdev_debug_event(struct notifier_block *nb, unsigned long event, case NETDEV_CHANGE: case NETDEV_REGISTER: case NETDEV_UP: - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); fallthrough; case NETDEV_DOWN: case NETDEV_REBOOT: @@ -65,6 +65,7 @@ int netdev_debug_event(struct notifier_block *nb, unsigned long event, break; case NETDEV_CHANGENAME: + netdev_assert_locked_ops(dev); ASSERT_RTNL_NET(net); break; } diff --git a/net/core/netdev_queues.c b/net/core/netdev_queues.c index 73fb28087a93..4d6864bb4f6b 100644 --- a/net/core/netdev_queues.c +++ b/net/core/netdev_queues.c @@ -40,7 +40,7 @@ struct device *netdev_queue_get_dma_dev(struct net_device *dev, struct netdev_rx_queue *hw_rxq; struct device *dma_dev; - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); /* Only RX side supports queue leasing today. */ if (type != NETDEV_QUEUE_TYPE_RX || !netif_rxq_is_leased(dev, idx)) diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c index f3a53a984460..a4e8f4b3fb75 100644 --- a/net/ethtool/cmis_cdb.c +++ b/net/ethtool/cmis_cdb.c @@ -2,6 +2,7 @@ #include #include +#include #include "common.h" #include "module_fw.h" @@ -179,6 +180,7 @@ cmis_cdb_validate_password(struct ethtool_cmis_cdb *cdb, pe_pl = *((struct cmis_password_entry_pl *)page_data.data); pe_pl.password = params->password; + netdev_assert_locked_ops(dev); err = ops->set_module_eeprom_by_page(dev, &page_data, &extack); if (err < 0) { if (extack._msg) @@ -546,6 +548,7 @@ __ethtool_cmis_cdb_execute_cmd(struct net_device *dev, if (!page_data->data) return -ENOMEM; + netdev_assert_locked_ops(dev); err = ops->set_module_eeprom_by_page(dev, page_data, &extack); if (err < 0) { if (extack._msg) diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c index 291d04d2776a..dff83807e975 100644 --- a/net/ethtool/cmis_fw_update.c +++ b/net/ethtool/cmis_fw_update.c @@ -435,13 +435,9 @@ cmis_fw_update_commit_image(struct ethtool_cmis_cdb *cdb, static int cmis_fw_update_reset(struct net_device *dev) { __u32 reset_data = ETH_RESET_PHY; - int ret; - netdev_lock_ops(dev); - ret = dev->ethtool_ops->reset(dev, &reset_data); - netdev_unlock_ops(dev); - - return ret; + netdev_assert_locked_ops(dev); + return dev->ethtool_ops->reset(dev, &reset_data); } void diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index bd97f9b9bf18..a4b0cbae4063 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -436,10 +436,10 @@ struct ethtool_link_usettings { }; /* Internal kernel helper to query a device ethtool_link_settings. */ -int __ethtool_get_link_ksettings(struct net_device *dev, - struct ethtool_link_ksettings *link_ksettings) +int netif_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *link_ksettings) { - ASSERT_RTNL(); + netdev_assert_locked_ops_compat(dev); if (!dev->ethtool_ops->get_link_ksettings) return -EOPNOTSUPP; @@ -450,6 +450,21 @@ int __ethtool_get_link_ksettings(struct net_device *dev, memset(link_ksettings, 0, sizeof(*link_ksettings)); return dev->ethtool_ops->get_link_ksettings(dev, link_ksettings); } +EXPORT_SYMBOL(netif_get_link_ksettings); + +/* Convenience helper for callers that hold only rtnl_lock(). */ +int __ethtool_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *link_ksettings) +{ + int ret; + + ASSERT_RTNL(); + + netdev_lock_ops(dev); + ret = netif_get_link_ksettings(dev, link_ksettings); + netdev_unlock_ops(dev); + return ret; +} EXPORT_SYMBOL(__ethtool_get_link_ksettings); /* convert ethtool_link_usettings in user space to a kernel internal diff --git a/net/ethtool/linkinfo.c b/net/ethtool/linkinfo.c index 244ff92e2ff9..d5b3dbc53c5f 100644 --- a/net/ethtool/linkinfo.c +++ b/net/ethtool/linkinfo.c @@ -34,7 +34,7 @@ static int linkinfo_prepare_data(const struct ethnl_req_info *req_base, ret = ethnl_ops_begin(dev); if (ret < 0) return ret; - ret = __ethtool_get_link_ksettings(dev, &data->ksettings); + ret = netif_get_link_ksettings(dev, &data->ksettings); if (ret < 0) GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); ethnl_ops_complete(dev); @@ -104,7 +104,7 @@ ethnl_set_linkinfo(struct ethnl_req_info *req_info, struct genl_info *info) bool mod = false; int ret; - ret = __ethtool_get_link_ksettings(dev, &ksettings); + ret = netif_get_link_ksettings(dev, &ksettings); if (ret < 0) { GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); return ret; diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c index 30d703531652..a6d32f0d9fcc 100644 --- a/net/ethtool/linkmodes.c +++ b/net/ethtool/linkmodes.c @@ -39,7 +39,7 @@ static int linkmodes_prepare_data(const struct ethnl_req_info *req_base, if (ret < 0) return ret; - ret = __ethtool_get_link_ksettings(dev, &data->ksettings); + ret = netif_get_link_ksettings(dev, &data->ksettings); if (ret < 0) { GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); goto out; @@ -324,7 +324,7 @@ ethnl_set_linkmodes(struct ethnl_req_info *req_info, struct genl_info *info) bool mod = false; int ret; - ret = __ethtool_get_link_ksettings(dev, &ksettings); + ret = netif_get_link_ksettings(dev, &ksettings); if (ret < 0) { GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); return ret; diff --git a/net/ethtool/module.c b/net/ethtool/module.c index ea4fb2a76650..c3388e6d7ec8 100644 --- a/net/ethtool/module.c +++ b/net/ethtool/module.c @@ -226,7 +226,9 @@ static void module_flash_fw_work(struct work_struct *work) module_fw = container_of(work, struct ethtool_module_fw_flash, work); dev = module_fw->fw_update.dev; + netdev_lock_ops(dev); ethtool_cmis_fw_update(&module_fw->fw_update); + netdev_unlock_ops(dev); module_flash_fw_work_list_del(&module_fw->list); diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 6cbd13b61bd1..25e22c48060a 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -98,7 +98,7 @@ int ethnl_ops_begin(struct net_device *dev) if (dev->dev.parent) pm_runtime_get_sync(dev->dev.parent); - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (!netif_device_present(dev) || dev->reg_state >= NETREG_UNREGISTERING) { @@ -1005,7 +1005,7 @@ static void ethnl_default_notify(struct net_device *dev, unsigned int cmd, ops->req_info_size - sizeof(*req_info)); } - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); ethnl_init_reply_data(reply_data, ops, dev); ret = ops->prepare_data(req_info, reply_data, &info); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f5a93155e7eb..af3a0e94773c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -380,7 +380,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) int err = -ENOMEM; ASSERT_RTNL(); - netdev_ops_assert_locked(dev); + netdev_assert_locked_ops_compat(dev); if (dev->mtu < IPV6_MIN_MTU && dev != blackhole_netdev) return ERR_PTR(-EINVAL); diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c index b952353ec2a5..85b41ffc63ff 100644 --- a/net/sched/sch_cbs.c +++ b/net/sched/sch_cbs.c @@ -327,7 +327,7 @@ static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q) s64 port_rate; int err; - err = __ethtool_get_link_ksettings(dev, &ecmd); + err = netif_get_link_ksettings(dev, &ecmd); if (err < 0) goto skip; diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index d6b981e5df11..e83cbce62a54 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1299,7 +1299,7 @@ static void taprio_set_picos_per_byte(struct net_device *dev, int picos_per_byte; int err; - err = __ethtool_get_link_ksettings(dev, &ecmd); + err = netif_get_link_ksettings(dev, &ecmd); if (err < 0) goto skip; diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c index d981cfdd8535..1f28a9641571 100644 --- a/net/xdp/xsk_buff_pool.c +++ b/net/xdp/xsk_buff_pool.c @@ -239,7 +239,7 @@ int xp_assign_dev(struct xsk_buff_pool *pool, bpf.xsk.pool = pool; bpf.xsk.queue_id = queue_id; - netdev_ops_assert_locked(netdev); + netdev_assert_locked_ops_compat(netdev); err = netdev->netdev_ops->ndo_bpf(netdev, &bpf); if (err) goto err_unreg_pool;