summaryrefslogtreecommitdiff
path: root/net/ethtool/module.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-05-21 15:02:54 -0700
committerJakub Kicinski <kuba@kernel.org>2026-05-28 14:02:21 -0700
commitd44646fc9eeb423ad50f3043f11f66f491d908a7 (patch)
tree18e6b3eda2c313c246ba18b88b4e06b2e18432c2 /net/ethtool/module.c
parent0cf905cb9a12dbfb5d14896729b74508f83f73df (diff)
parent3e20009988e2470063824c58b19d1c80816cc46d (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.1-rc6). Conflicts: drivers/net/phy/air_en8811h.c d895767c33781 ("net: phy: air_en8811h: add AN8811HB MCU assert/deassert support") dddfadd75197e ("net: phy: Add Airoha phy library for shared code") 5226bb6634cdf ("net: phy: air_phy_lib: Factorize BuckPBus register accessors") e08f0ea6daf2e ("net: phy: Rename Airoha common BuckPBus register accessors") net/sched/sch_netem.c a2f6ed7b4873 ("net/sched: netem: add per-impairment extended statistics") 9552b11e3eda ("net/sched: fix packet loop on netem when duplicate is on") Adjacent changes: drivers/dpll/zl3073x/core.c c1224569cef0 ("dpll: zl3073x: make frequency monitor a per-device attribute") 54e65df8cf18 ("dpll: zl3073x: report FFO as DPLL vs input reference offset") net/iucv/af_iucv.c 347fdd4df85f ("af_iucv: convert to getsockopt_iter") 3589d20a666c ("net/iucv: fix locking in .getsockopt") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ethtool/module.c')
-rw-r--r--net/ethtool/module.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/net/ethtool/module.c b/net/ethtool/module.c
index cad2eb25b5a4..ea4fb2a76650 100644
--- a/net/ethtool/module.c
+++ b/net/ethtool/module.c
@@ -120,12 +120,6 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
return 0;
- if (req_info->dev->ethtool->module_fw_flash_in_progress) {
- NL_SET_ERR_MSG(info->extack,
- "Module firmware flashing is in progress");
- return -EBUSY;
- }
-
if (!ops->get_module_power_mode || !ops->set_module_power_mode) {
NL_SET_ERR_MSG_ATTR(info->extack,
tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
@@ -148,6 +142,12 @@ ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
ops = dev->ethtool_ops;
+ if (dev->ethtool->module_fw_flash_in_progress) {
+ NL_SET_ERR_MSG(info->extack,
+ "Module firmware flashing is in progress");
+ return -EBUSY;
+ }
+
power_new.policy = nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
ret = ops->get_module_power_mode(dev, &power, info->extack);
if (ret < 0)
@@ -221,14 +221,22 @@ static void module_flash_fw_work_list_del(struct list_head *list)
static void module_flash_fw_work(struct work_struct *work)
{
struct ethtool_module_fw_flash *module_fw;
+ struct net_device *dev;
module_fw = container_of(work, struct ethtool_module_fw_flash, work);
+ dev = module_fw->fw_update.dev;
ethtool_cmis_fw_update(&module_fw->fw_update);
module_flash_fw_work_list_del(&module_fw->list);
- module_fw->fw_update.dev->ethtool->module_fw_flash_in_progress = false;
- netdev_put(module_fw->fw_update.dev, &module_fw->dev_tracker);
+
+ rtnl_lock();
+ netdev_lock_ops(dev);
+ dev->ethtool->module_fw_flash_in_progress = false;
+ netdev_unlock_ops(dev);
+ rtnl_unlock();
+
+ netdev_put(dev, &module_fw->dev_tracker);
release_firmware(module_fw->fw_update.fw);
kfree(module_fw);
}
@@ -283,11 +291,9 @@ void ethnl_module_fw_flash_sock_destroy(struct ethnl_sock_priv *sk_priv)
spin_lock(&module_fw_flash_work_list_lock);
list_for_each_entry(work, &module_fw_flash_work_list, list) {
- if (work->fw_update.dev == sk_priv->dev &&
- work->fw_update.ntf_params.portid == sk_priv->portid) {
+ if (work->fw_update.ntf_params.portid == sk_priv->portid &&
+ dev_net(work->fw_update.dev) == sk_priv->net)
work->fw_update.ntf_params.closed_sock = true;
- break;
- }
}
spin_unlock(&module_fw_flash_work_list_lock);
}
@@ -319,14 +325,13 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
if (err < 0)
goto err_release_firmware;
- dev->ethtool->module_fw_flash_in_progress = true;
- netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
fw_update->dev = dev;
fw_update->ntf_params.portid = info->snd_portid;
fw_update->ntf_params.seq = info->snd_seq;
fw_update->ntf_params.closed_sock = false;
- err = ethnl_sock_priv_set(skb, dev, fw_update->ntf_params.portid,
+ err = ethnl_sock_priv_set(skb, dev_net(dev),
+ fw_update->ntf_params.portid,
ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH);
if (err < 0)
goto err_release_firmware;
@@ -335,6 +340,9 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
if (err < 0)
goto err_release_firmware;
+ dev->ethtool->module_fw_flash_in_progress = true;
+ netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
+
schedule_work(&module_fw->work);
return 0;
@@ -427,10 +435,11 @@ int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info)
ret = ethnl_module_fw_flash_validate(dev, info->extack);
if (ret < 0)
- goto out_unlock;
+ goto out_complete;
ret = module_flash_fw(dev, tb, skb, info);
+out_complete:
ethnl_ops_complete(dev);
out_unlock: