]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: nl80211: clean up coalescing rule handling
authorJohannes Berg <johannes.berg@intel.com>
Thu, 23 May 2024 10:02:13 +0000 (12:02 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 29 May 2024 08:38:53 +0000 (10:38 +0200)
There's no need to allocate a tiny struct and then
an array again, just allocate the two together and
use __counted_by(). Also unify the freeing.

Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240523120213.48a40cfb96f9.Ia02bf8f8fefbf533c64c5fa26175848d4a3a7899@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/nl80211.h

index d79180bec7a1f27420d985970535a0dfb290746b..5da9bb0ac6a4782fc843597090c4b4724e5dbc29 100644 (file)
@@ -3566,8 +3566,8 @@ struct cfg80211_coalesce_rules {
  * @n_rules: number of rules
  */
 struct cfg80211_coalesce {
-       struct cfg80211_coalesce_rules *rules;
        int n_rules;
+       struct cfg80211_coalesce_rules rules[] __counted_by(n_rules);
 };
 
 /**
index 61f7cd8a8e9cedaf75322daeaff0c27bea10712c..7c35349b959660934660ab1c96bfde4353351edb 100644 (file)
@@ -1145,7 +1145,8 @@ void wiphy_unregister(struct wiphy *wiphy)
        flush_work(&rdev->background_cac_abort_wk);
 
        cfg80211_rdev_free_wowlan(rdev);
-       cfg80211_rdev_free_coalesce(rdev);
+       cfg80211_free_coalesce(rdev->coalesce);
+       rdev->coalesce = NULL;
 }
 EXPORT_SYMBOL(wiphy_unregister);
 
index 6ba988a6f5a22b0710d1fc2274c1f7c91f3907a7..8ff5f79d446ae1fa104059a72d42e55cc49fa679 100644 (file)
@@ -13897,9 +13897,8 @@ nla_put_failure:
        return -ENOBUFS;
 }
 
-void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
+void cfg80211_free_coalesce(struct cfg80211_coalesce *coalesce)
 {
-       struct cfg80211_coalesce *coalesce = rdev->coalesce;
        int i, j;
        struct cfg80211_coalesce_rules *rule;
 
@@ -13908,13 +13907,13 @@ void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev)
 
        for (i = 0; i < coalesce->n_rules; i++) {
                rule = &coalesce->rules[i];
+               if (!rule)
+                       continue;
                for (j = 0; j < rule->n_patterns; j++)
                        kfree(rule->patterns[j].mask);
                kfree(rule->patterns);
        }
-       kfree(coalesce->rules);
        kfree(coalesce);
-       rdev->coalesce = NULL;
 }
 
 static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
@@ -14012,17 +14011,16 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
-       struct cfg80211_coalesce new_coalesce = {};
-       struct cfg80211_coalesce *n_coalesce;
-       int err, rem_rule, n_rules = 0, i, j;
+       struct cfg80211_coalesce *new_coalesce;
+       int err, rem_rule, n_rules = 0, i;
        struct nlattr *rule;
-       struct cfg80211_coalesce_rules *tmp_rule;
 
        if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce)
                return -EOPNOTSUPP;
 
        if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) {
-               cfg80211_rdev_free_coalesce(rdev);
+               cfg80211_free_coalesce(rdev->coalesce);
+               rdev->coalesce = NULL;
                rdev_set_coalesce(rdev, NULL);
                return 0;
        }
@@ -14033,47 +14031,34 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
        if (n_rules > coalesce->n_rules)
                return -EINVAL;
 
-       new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]),
-                                    GFP_KERNEL);
-       if (!new_coalesce.rules)
+       new_coalesce = kzalloc(struct_size(new_coalesce, rules, n_rules),
+                              GFP_KERNEL);
+       if (!new_coalesce)
                return -ENOMEM;
 
-       new_coalesce.n_rules = n_rules;
+       new_coalesce->n_rules = n_rules;
        i = 0;
 
        nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE],
                            rem_rule) {
                err = nl80211_parse_coalesce_rule(rdev, rule,
-                                                 &new_coalesce.rules[i]);
+                                                 &new_coalesce->rules[i]);
                if (err)
                        goto error;
 
                i++;
        }
 
-       err = rdev_set_coalesce(rdev, &new_coalesce);
+       err = rdev_set_coalesce(rdev, new_coalesce);
        if (err)
                goto error;
 
-       n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL);
-       if (!n_coalesce) {
-               err = -ENOMEM;
-               goto error;
-       }
-       cfg80211_rdev_free_coalesce(rdev);
-       rdev->coalesce = n_coalesce;
+       cfg80211_free_coalesce(rdev->coalesce);
+       rdev->coalesce = new_coalesce;
 
        return 0;
 error:
-       for (i = 0; i < new_coalesce.n_rules; i++) {
-               tmp_rule = &new_coalesce.rules[i];
-               if (!tmp_rule)
-                       continue;
-               for (j = 0; j < tmp_rule->n_patterns; j++)
-                       kfree(tmp_rule->patterns[j].mask);
-               kfree(tmp_rule->patterns);
-       }
-       kfree(new_coalesce.rules);
+       cfg80211_free_coalesce(new_coalesce);
 
        return err;
 }
index 6376f3a87f8abf6e2007c06c287c111f65d499b2..ffaab9a92e5bc75ddbce5fddec81e3a26a05f32b 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Portions of this file
- * Copyright (C) 2018, 2020-2022 Intel Corporation
+ * Copyright (C) 2018, 2020-2024 Intel Corporation
  */
 #ifndef __NET_WIRELESS_NL80211_H
 #define __NET_WIRELESS_NL80211_H
@@ -119,7 +119,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 
 void nl80211_send_ap_stopped(struct wireless_dev *wdev, unsigned int link_id);
 
-void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
+void cfg80211_free_coalesce(struct cfg80211_coalesce *coalesce);
 
 /* peer measurement */
 int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info);