]> Git Repo - linux.git/commitdiff
ethtool: Veto some operations during firmware flashing process
authorDanielle Ratson <[email protected]>
Thu, 27 Jun 2024 14:08:52 +0000 (17:08 +0300)
committerDavid S. Miller <[email protected]>
Fri, 28 Jun 2024 09:48:22 +0000 (10:48 +0100)
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]>
include/linux/netdevice.h
net/ethtool/eeprom.c
net/ethtool/ioctl.c
net/ethtool/netlink.c

index cc18acd3c58b7753df570a323166c9a9ff74e145..1e3401093c1305198ad41e972760915d66ac3356 100644 (file)
@@ -1990,6 +1990,8 @@ enum netdev_reg_state {
  *
  *     @threaded:      napi threaded mode is enabled
  *
+ *     @module_fw_flash_in_progress:   Module firmware flashing is in progress.
+ *
  *     @net_notifier_list:     List of per-net netdev notifier block
  *                             that follow this device when it is moved
  *                             to another network namespace.
@@ -2374,7 +2376,7 @@ struct net_device {
        bool                    proto_down;
        bool                    threaded;
        unsigned                wol_enabled:1;
-
+       unsigned                module_fw_flash_in_progress:1;
        struct list_head        net_notifier_list;
 
 #if IS_ENABLED(CONFIG_MACSEC)
index 6209c3a9c8f723adeea5c2167869a91ff1ad2c73..f36811b3ecf16e5d8524bcb69541ba7b15e38601 100644 (file)
@@ -91,6 +91,12 @@ static int get_module_eeprom_by_page(struct net_device *dev,
 {
        const struct ethtool_ops *ops = dev->ethtool_ops;
 
+       if (dev->module_fw_flash_in_progress) {
+               NL_SET_ERR_MSG(extack,
+                              "Module firmware flashing is in progress");
+               return -EBUSY;
+       }
+
        if (dev->sfp_bus)
                return sfp_get_module_eeprom_by_page(dev->sfp_bus, page_data, extack);
 
index e645d751a5e8998064ef5fa239d465f66c044e6f..1cca372c0d807b78b2cbd56466324686d39eb493 100644 (file)
@@ -658,6 +658,9 @@ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
        if (!dev->ethtool_ops->get_link_ksettings)
                return -EOPNOTSUPP;
 
+       if (dev->module_fw_flash_in_progress)
+               return -EBUSY;
+
        memset(&link_ksettings, 0, sizeof(link_ksettings));
        err = dev->ethtool_ops->get_link_ksettings(dev, &link_ksettings);
        if (err < 0)
@@ -1449,6 +1452,9 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
        if (!dev->ethtool_ops->reset)
                return -EOPNOTSUPP;
 
+       if (dev->module_fw_flash_in_progress)
+               return -EBUSY;
+
        if (copy_from_user(&reset, useraddr, sizeof(reset)))
                return -EFAULT;
 
@@ -2462,6 +2468,9 @@ int ethtool_get_module_info_call(struct net_device *dev,
        const struct ethtool_ops *ops = dev->ethtool_ops;
        struct phy_device *phydev = dev->phydev;
 
+       if (dev->module_fw_flash_in_progress)
+               return -EBUSY;
+
        if (dev->sfp_bus)
                return sfp_get_module_info(dev->sfp_bus, modinfo);
 
@@ -2499,6 +2508,9 @@ int ethtool_get_module_eeprom_call(struct net_device *dev,
        const struct ethtool_ops *ops = dev->ethtool_ops;
        struct phy_device *phydev = dev->phydev;
 
+       if (dev->module_fw_flash_in_progress)
+               return -EBUSY;
+
        if (dev->sfp_bus)
                return sfp_get_module_eeprom(dev->sfp_bus, ee, data);
 
index 393ce668fb04221e941775e2233def428d5db28d..a5907bbde4272fa911ea0f1758b19ae1d4b6b402 100644 (file)
@@ -765,10 +765,22 @@ static void ethnl_notify_features(struct netdev_notifier_info *info)
 static int ethnl_netdev_event(struct notifier_block *this, unsigned long event,
                              void *ptr)
 {
+       struct netdev_notifier_info *info = ptr;
+       struct netlink_ext_ack *extack;
+       struct net_device *dev;
+
+       dev = netdev_notifier_info_to_dev(info);
+       extack = netdev_notifier_info_to_extack(info);
+
        switch (event) {
        case NETDEV_FEAT_CHANGE:
                ethnl_notify_features(ptr);
                break;
+       case NETDEV_PRE_UP:
+               if (dev->module_fw_flash_in_progress) {
+                       NL_SET_ERR_MSG(extack, "Can't set port up while flashing module firmware");
+                       return NOTIFY_BAD;
+               }
        }
 
        return NOTIFY_DONE;
This page took 0.08371 seconds and 4 git commands to generate.