Skip to content

Commit 31e0aa9

Browse files
daniellertsdavem330
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. In order to veto those scenarios, add a flag in 'struct net_device' that indicates when a firmware flash is taking place on the module and use it to prevent interruptions during the process. Signed-off-by: Danielle Ratson <[email protected]> Reviewed-by: Petr Machata <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d7d4cfc commit 31e0aa9

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

include/linux/netdevice.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1990,6 +1990,8 @@ enum netdev_reg_state {
19901990
*
19911991
* @threaded: napi threaded mode is enabled
19921992
*
1993+
* @module_fw_flash_in_progress: Module firmware flashing is in progress.
1994+
*
19931995
* @net_notifier_list: List of per-net netdev notifier block
19941996
* that follow this device when it is moved
19951997
* to another network namespace.
@@ -2374,7 +2376,7 @@ struct net_device {
23742376
bool proto_down;
23752377
bool threaded;
23762378
unsigned wol_enabled:1;
2377-
2379+
unsigned module_fw_flash_in_progress:1;
23782380
struct list_head net_notifier_list;
23792381

23802382
#if IS_ENABLED(CONFIG_MACSEC)

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/netlink.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,22 @@ static void ethnl_notify_features(struct netdev_notifier_info *info)
765765
static int ethnl_netdev_event(struct notifier_block *this, unsigned long event,
766766
void *ptr)
767767
{
768+
struct netdev_notifier_info *info = ptr;
769+
struct netlink_ext_ack *extack;
770+
struct net_device *dev;
771+
772+
dev = netdev_notifier_info_to_dev(info);
773+
extack = netdev_notifier_info_to_extack(info);
774+
768775
switch (event) {
769776
case NETDEV_FEAT_CHANGE:
770777
ethnl_notify_features(ptr);
771778
break;
779+
case NETDEV_PRE_UP:
780+
if (dev->module_fw_flash_in_progress) {
781+
NL_SET_ERR_MSG(extack, "Can't set port up while flashing module firmware");
782+
return NOTIFY_BAD;
783+
}
772784
}
773785

774786
return NOTIFY_DONE;

0 commit comments

Comments
 (0)