Merge tag 'for-6.3/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/devic...
[linux-block.git] / net / ethtool / linkmodes.c
index 126e06c713a3ac1cf8d57c179a088995ff2e268a..fab66c169b9fa92f2f23b6d3654076f0d0457377 100644 (file)
@@ -151,18 +151,6 @@ static int linkmodes_fill_reply(struct sk_buff *skb,
        return 0;
 }
 
-const struct ethnl_request_ops ethnl_linkmodes_request_ops = {
-       .request_cmd            = ETHTOOL_MSG_LINKMODES_GET,
-       .reply_cmd              = ETHTOOL_MSG_LINKMODES_GET_REPLY,
-       .hdr_attr               = ETHTOOL_A_LINKMODES_HEADER,
-       .req_info_size          = sizeof(struct linkmodes_req_info),
-       .reply_data_size        = sizeof(struct linkmodes_reply_data),
-
-       .prepare_data           = linkmodes_prepare_data,
-       .reply_size             = linkmodes_reply_size,
-       .fill_reply             = linkmodes_fill_reply,
-};
-
 /* LINKMODES_SET */
 
 const struct nla_policy ethnl_linkmodes_set_policy[] = {
@@ -310,59 +298,64 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb,
        return 0;
 }
 
-int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info)
+static int
+ethnl_set_linkmodes_validate(struct ethnl_req_info *req_info,
+                            struct genl_info *info)
 {
-       struct ethtool_link_ksettings ksettings = {};
-       struct ethnl_req_info req_info = {};
-       struct nlattr **tb = info->attrs;
-       struct net_device *dev;
-       bool mod = false;
+       const struct ethtool_ops *ops = req_info->dev->ethtool_ops;
        int ret;
 
-       ret = ethnl_check_linkmodes(info, tb);
+       ret = ethnl_check_linkmodes(info, info->attrs);
        if (ret < 0)
                return ret;
 
-       ret = ethnl_parse_header_dev_get(&req_info,
-                                        tb[ETHTOOL_A_LINKMODES_HEADER],
-                                        genl_info_net(info), info->extack,
-                                        true);
-       if (ret < 0)
-               return ret;
-       dev = req_info.dev;
-       ret = -EOPNOTSUPP;
-       if (!dev->ethtool_ops->get_link_ksettings ||
-           !dev->ethtool_ops->set_link_ksettings)
-               goto out_dev;
+       if (!ops->get_link_ksettings || !ops->set_link_ksettings)
+               return -EOPNOTSUPP;
+       return 1;
+}
 
-       rtnl_lock();
-       ret = ethnl_ops_begin(dev);
-       if (ret < 0)
-               goto out_rtnl;
+static int
+ethnl_set_linkmodes(struct ethnl_req_info *req_info, struct genl_info *info)
+{
+       struct ethtool_link_ksettings ksettings = {};
+       struct net_device *dev = req_info->dev;
+       struct nlattr **tb = info->attrs;
+       bool mod = false;
+       int ret;
 
        ret = __ethtool_get_link_ksettings(dev, &ksettings);
        if (ret < 0) {
                GENL_SET_ERR_MSG(info, "failed to retrieve link settings");
-               goto out_ops;
+               return ret;
        }
 
        ret = ethnl_update_linkmodes(info, tb, &ksettings, &mod, dev);
        if (ret < 0)
-               goto out_ops;
+               return ret;
+       if (!mod)
+               return 0;
 
-       if (mod) {
-               ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings);
-               if (ret < 0)
-                       GENL_SET_ERR_MSG(info, "link settings update failed");
-               else
-                       ethtool_notify(dev, ETHTOOL_MSG_LINKMODES_NTF, NULL);
+       ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings);
+       if (ret < 0) {
+               GENL_SET_ERR_MSG(info, "link settings update failed");
+               return ret;
        }
 
-out_ops:
-       ethnl_ops_complete(dev);
-out_rtnl:
-       rtnl_unlock();
-out_dev:
-       ethnl_parse_header_dev_put(&req_info);
-       return ret;
+       return 1;
 }
+
+const struct ethnl_request_ops ethnl_linkmodes_request_ops = {
+       .request_cmd            = ETHTOOL_MSG_LINKMODES_GET,
+       .reply_cmd              = ETHTOOL_MSG_LINKMODES_GET_REPLY,
+       .hdr_attr               = ETHTOOL_A_LINKMODES_HEADER,
+       .req_info_size          = sizeof(struct linkmodes_req_info),
+       .reply_data_size        = sizeof(struct linkmodes_reply_data),
+
+       .prepare_data           = linkmodes_prepare_data,
+       .reply_size             = linkmodes_reply_size,
+       .fill_reply             = linkmodes_fill_reply,
+
+       .set_validate           = ethnl_set_linkmodes_validate,
+       .set                    = ethnl_set_linkmodes,
+       .set_ntf_cmd            = ETHTOOL_MSG_LINKMODES_NTF,
+};