Commit 8526f8c8 authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: nl80211: clean up coalescing rule handling



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: default avatarMiriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240523120213.48a40cfb96f9.Ia02bf8f8fefbf533c64c5fa26175848d4a3a7899@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 6322e0e7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
};

/**
+2 −1
Original line number Diff line number Diff line
@@ -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);

+16 −31
Original line number Diff line number Diff line
@@ -13897,9 +13897,8 @@ static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info)
	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]),
	new_coalesce = kzalloc(struct_size(new_coalesce, rules, n_rules),
			       GFP_KERNEL);
	if (!new_coalesce.rules)
	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;
}
+2 −2
Original line number Diff line number Diff line
/* 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);