Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d3b6fc0 authored by Kiran Gunda's avatar Kiran Gunda Committed by Gerrit - the friendly Code Review server
Browse files

msm: msm_bus: fix memory allocation issues



Memory for some of the fields in the rule structure
is not allocated during the rule registration time.
This patch addresses these memeory allocation issues
and frees the same during the un-registration.

Change-Id: I62e437d6c2cfa57d9f4b4afa86b99ecf383b36aa
Signed-off-by: default avatarKiran Gunda <kgunda@codeaurora.org>
parent 4031d505
Loading
Loading
Loading
Loading
+77 −16
Original line number Diff line number Diff line
@@ -501,17 +501,58 @@ static int copy_rule(struct bus_rule_type *src, struct rules_def *node_rule,
					__func__);
		return -ENOMEM;
	}
	memcpy(node_rule->rule_ops.src_id, src->src_id,
				sizeof(int) * src->num_src);

	node_rule->rule_ops.thresh = kzalloc(
			(sizeof(u64) * node_rule->rule_ops.num_thresh),
							GFP_KERNEL);
	if (!node_rule->rule_ops.thresh) {
		pr_err("%s:Failed to allocate for thresh",
					__func__);
		kfree(node_rule->rule_ops.src_id);
		return -ENOMEM;
	}
	node_rule->rule_ops.src_field = kzalloc(
			(sizeof(int) * node_rule->rule_ops.num_thresh),
							GFP_KERNEL);
	if (!node_rule->rule_ops.src_field) {
		pr_err("%s:Failed to allocate for src_field",
					__func__);
		kfree(node_rule->rule_ops.src_id);
		kfree(node_rule->rule_ops.thresh);
		return -ENOMEM;
	}
	node_rule->rule_ops.op = kzalloc(
				(sizeof(int) * node_rule->rule_ops.num_thresh),
							GFP_KERNEL);

	if (!node_rule->rule_ops.op) {
		pr_err("%s:Failed to allocate for OP",
					__func__);
		kfree(node_rule->rule_ops.src_id);
		kfree(node_rule->rule_ops.thresh);
		kfree(node_rule->rule_ops.src_field);
		return -ENOMEM;
	}

	memcpy(node_rule->rule_ops.thresh, src->thresh,
				sizeof(u64) * src->num_thresh);
	memcpy(node_rule->rule_ops.src_field, src->src_field,
				sizeof(int) * src->num_thresh);
	memcpy(node_rule->rule_ops.op, src->op,
				sizeof(int) * src->num_thresh);
	memcpy(node_rule->rule_ops.src_id, src->src_id,
				sizeof(int) * src->num_src);
	if (!nb) {
		node_rule->rule_ops.dst_node = kzalloc(
			(sizeof(int) * node_rule->rule_ops.num_dst),
						GFP_KERNEL);
		if (!node_rule->rule_ops.dst_node) {
			pr_err("%s:Failed to allocate for src_id",
			pr_err("%s:Failed to allocate for dst_node",
							__func__);
			kfree(node_rule->rule_ops.src_id);
			kfree(node_rule->rule_ops.thresh);
			kfree(node_rule->rule_ops.src_field);
			kfree(node_rule->rule_ops.op);
			return -ENOMEM;
		}
		memcpy(node_rule->rule_ops.dst_node, src->dst_node,
@@ -523,8 +564,14 @@ static int copy_rule(struct bus_rule_type *src, struct rules_def *node_rule,
		(sizeof(struct node_vote_info) * node_rule->rule_ops.num_src),
							GFP_KERNEL);
	if (!node_rule->src_info) {
		pr_err("%s:Failed to allocate for src_id",
		pr_err("%s:Failed to allocate for src_info",
						__func__);
		kfree(node_rule->rule_ops.src_id);
		kfree(node_rule->rule_ops.thresh);
		kfree(node_rule->rule_ops.src_field);
		kfree(node_rule->rule_ops.op);
		if (!nb)
			kfree(node_rule->rule_ops.dst_node);
		return -ENOMEM;
	}
	for (i = 0; i < src->num_src; i++)
@@ -587,6 +634,7 @@ static bool __rule_register(int num_rules, struct bus_rule_type *rule,
			list_add_tail(&node_rule->link, &node->node_rules);
		}
	}
	if (!nb)
		list_sort(NULL, &node->node_rules, node_rules_compare);
	if (nb && nb != node->rule_notify_list.head)
		raw_notifier_chain_register(&node->rule_notify_list, nb);
@@ -628,6 +676,20 @@ void msm_rule_register(int num_rules, struct bus_rule_type *rule,
	mutex_unlock(&msm_bus_rules_lock);
}

static void free_rule_params(struct rules_def *node_rule)
{
	struct bus_rule_type *rule = &node_rule->rule_ops;

	kfree(rule->src_id);
	kfree(rule->src_field);
	kfree(rule->op);
	kfree(rule->thresh);
	kfree(rule->dst_node);
	kfree(node_rule->src_info);

	list_del(&node_rule->link);
}

static bool __rule_unregister(int num_rules, struct bus_rule_type *rule,
					struct notifier_block *nb)
{
@@ -647,21 +709,20 @@ static bool __rule_unregister(int num_rules, struct bus_rule_type *rule,
			pr_err("%s: Can't find node", __func__);
			goto exit_unregister_rule;
		}
		match_found = true;

		for (i = 0; i < num_rules; i++) {
			list_for_each_entry_safe(node_rule, node_rule_tmp,
					&node->node_rules, link) {
				if (comp_rules(&node_rule->rule_ops,
					&rule[i]) == 0) {
				list_del(&node_rule->link);
					free_rule_params(node_rule);
					kfree(node_rule);
					match_found = true;
					node->num_rules--;
				list_sort(NULL,
					&node->node_rules,
					node_rules_compare);
					break;
				}
			}
		}
		if (!node->num_rules)
			raw_notifier_chain_unregister(
					&node->rule_notify_list, nb);
+6 −6
Original line number Diff line number Diff line
@@ -39,18 +39,18 @@ struct rule_apply_rcm_info {

struct bus_rule_type {
	int num_src;
	int *src_id;
	int *src_field;
	int *op;
	int combo_op;
	int num_thresh;
	u64 *thresh;
	int num_dst;
	int *dst_node;
	u64 dst_bw;
	int mode;
	void *client_data;
	u64 curr_bw;
	void *client_data;
	int *src_id;
	int *src_field;
	int *op;
	u64 *thresh;
	int *dst_node;
};

#if (defined(CONFIG_BUS_TOPOLOGY_ADHOC))