Skip to content

Commit 27c8cf1

Browse files
daniellertsNipaLocal
authored andcommitted
ethtool: Veto some operations during firmware flashing process
Some operations cannot be performed during the firmware flashing process. For example: - Port must be down during the whole flashing process to avoid packet loss while committing reset for example. - Writing to EEPROM interrupts the flashing process, so operations like ethtool dump, module reset, get and set power mode should be vetoed. - Split port firmware flashing should be vetoed. - Flashing firmware on a device which is already in a flashing process should be forbidden. Use the 'module_fw_flashing_in_progress' flag introduced in a previous patch to veto those operations and prevent interruptions while preforming module firmware flash. Signed-off-by: Danielle Ratson <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 622f622 commit 27c8cf1

File tree

4 files changed

+76
-1
lines changed

4 files changed

+76
-1
lines changed

net/ethtool/eeprom.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ static int get_module_eeprom_by_page(struct net_device *dev,
9191
{
9292
const struct ethtool_ops *ops = dev->ethtool_ops;
9393

94+
if (dev->module_fw_flash_in_progress) {
95+
NL_SET_ERR_MSG(extack,
96+
"Module firmware flashing is in progress");
97+
return -EBUSY;
98+
}
99+
94100
if (dev->sfp_bus)
95101
return sfp_get_module_eeprom_by_page(dev->sfp_bus, page_data, extack);
96102

net/ethtool/ioctl.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,9 @@ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
658658
if (!dev->ethtool_ops->get_link_ksettings)
659659
return -EOPNOTSUPP;
660660

661+
if (dev->module_fw_flash_in_progress)
662+
return -EBUSY;
663+
661664
memset(&link_ksettings, 0, sizeof(link_ksettings));
662665
err = dev->ethtool_ops->get_link_ksettings(dev, &link_ksettings);
663666
if (err < 0)
@@ -1449,6 +1452,9 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
14491452
if (!dev->ethtool_ops->reset)
14501453
return -EOPNOTSUPP;
14511454

1455+
if (dev->module_fw_flash_in_progress)
1456+
return -EBUSY;
1457+
14521458
if (copy_from_user(&reset, useraddr, sizeof(reset)))
14531459
return -EFAULT;
14541460

@@ -2462,6 +2468,9 @@ int ethtool_get_module_info_call(struct net_device *dev,
24622468
const struct ethtool_ops *ops = dev->ethtool_ops;
24632469
struct phy_device *phydev = dev->phydev;
24642470

2471+
if (dev->module_fw_flash_in_progress)
2472+
return -EBUSY;
2473+
24652474
if (dev->sfp_bus)
24662475
return sfp_get_module_info(dev->sfp_bus, modinfo);
24672476

@@ -2499,6 +2508,9 @@ int ethtool_get_module_eeprom_call(struct net_device *dev,
24992508
const struct ethtool_ops *ops = dev->ethtool_ops;
25002509
struct phy_device *phydev = dev->phydev;
25012510

2511+
if (dev->module_fw_flash_in_progress)
2512+
return -EBUSY;
2513+
25022514
if (dev->sfp_bus)
25032515
return sfp_get_module_eeprom(dev->sfp_bus, ee, data);
25042516

net/ethtool/module.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <linux/ethtool.h>
44
#include <linux/firmware.h>
55
#include <linux/sfp.h>
6+
#include <net/devlink.h>
67

78
#include "netlink.h"
89
#include "common.h"
@@ -36,6 +37,12 @@ static int module_get_power_mode(struct net_device *dev,
3637
if (!ops->get_module_power_mode)
3738
return 0;
3839

40+
if (dev->module_fw_flash_in_progress) {
41+
NL_SET_ERR_MSG(extack,
42+
"Module firmware flashing is in progress");
43+
return -EBUSY;
44+
}
45+
3946
return ops->get_module_power_mode(dev, &data->power, extack);
4047
}
4148

@@ -112,6 +119,12 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
112119
if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
113120
return 0;
114121

122+
if (req_info->dev->module_fw_flash_in_progress) {
123+
NL_SET_ERR_MSG(info->extack,
124+
"Module firmware flashing is in progress");
125+
return -EBUSY;
126+
}
127+
115128
if (!ops->get_module_power_mode || !ops->set_module_power_mode) {
116129
NL_SET_ERR_MSG_ATTR(info->extack,
117130
tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
@@ -219,6 +232,7 @@ static int module_flash_fw_work_init(struct ethtool_module_fw_flash *module_fw,
219232
static int __module_flash_fw_schedule(struct net_device *dev,
220233
struct netlink_ext_ack *extack)
221234
{
235+
struct devlink_port *devlink_port = dev->devlink_port;
222236
const struct ethtool_ops *ops = dev->ethtool_ops;
223237

224238
if (!ops->set_module_eeprom_by_page ||
@@ -234,6 +248,21 @@ static int __module_flash_fw_schedule(struct net_device *dev,
234248
return -EOPNOTSUPP;
235249
}
236250

251+
if (dev->module_fw_flash_in_progress) {
252+
NL_SET_ERR_MSG(extack, "Module firmware flashing already in progress");
253+
return -EBUSY;
254+
}
255+
256+
if (dev->flags & IFF_UP) {
257+
NL_SET_ERR_MSG(extack, "Netdevice is up, so flashing is not permitted");
258+
return -EBUSY;
259+
}
260+
261+
if (devlink_port && devlink_port->attrs.split) {
262+
NL_SET_ERR_MSG(extack, "Can't perform firmware flashing on a split port");
263+
return -EOPNOTSUPP;
264+
}
265+
237266
return 0;
238267
}
239268

net/ethtool/netlink.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,29 @@ static struct genl_family ethtool_genl_family __ro_after_init = {
11941194
.n_mcgrps = ARRAY_SIZE(ethtool_nl_mcgrps),
11951195
};
11961196

1197+
static int module_netdev_pre_up_event(struct notifier_block *this,
1198+
unsigned long event, void *ptr)
1199+
{
1200+
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1201+
struct netdev_notifier_info *info = ptr;
1202+
struct netlink_ext_ack *extack;
1203+
1204+
extack = netdev_notifier_info_to_extack(info);
1205+
1206+
if (event == NETDEV_PRE_UP) {
1207+
if (dev->module_fw_flash_in_progress) {
1208+
NL_SET_ERR_MSG(extack, "Can't set port up while flashing module firmware");
1209+
return NOTIFY_BAD;
1210+
}
1211+
}
1212+
1213+
return NOTIFY_DONE;
1214+
}
1215+
1216+
static struct notifier_block ethtool_module_netdev_pre_up_notifier = {
1217+
.notifier_call = module_netdev_pre_up_event,
1218+
};
1219+
11971220
/* module setup */
11981221

11991222
static int __init ethnl_init(void)
@@ -1206,7 +1229,12 @@ static int __init ethnl_init(void)
12061229
ethnl_ok = true;
12071230

12081231
ret = register_netdevice_notifier(&ethnl_netdev_notifier);
1209-
WARN(ret < 0, "ethtool: net device notifier registration failed");
1232+
if (WARN(ret < 0, "ethtool: net device notifier registration failed"))
1233+
return ret;
1234+
1235+
ret = register_netdevice_notifier(&ethtool_module_netdev_pre_up_notifier);
1236+
WARN(ret < 0, "ethtool: net device port up notifier registration failed");
1237+
12101238
return ret;
12111239
}
12121240

0 commit comments

Comments
 (0)