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

Commit ec0a3b61 authored by Skylar Chang's avatar Skylar Chang Committed by Mohammed Javid
Browse files

msm: ipa: support ipacm cleanup



Support header/filter, routing rules
cleanup when user-space module
crashed like ipacm and also cached
the wlan client connect messages
for ipacm to query.

Change-Id: Ib09cbe0e9114aa5a5673898ff796de7e7944af35
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent f4eb57c3
Loading
Loading
Loading
Loading
+152 −86
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -561,8 +561,28 @@ int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs)
EXPORT_SYMBOL(ipa_add_hdr);

/**
 * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them
 * to IPA HW
 * ipa_add_hdr_usr() - add the specified headers to SW and optionally
 * commit them to IPA HW
 * @hdrs:		[inout] set of headers to add
 * @user_only:	[in] indicate rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_add_hdr_usr, hdrs, user_only);

	return ret;
}
EXPORT_SYMBOL(ipa_add_hdr_usr);

/**
 * ipa_del_hdr() - Remove the specified headers from SW and optionally
 * commit them to IPA HW
 * @hdls:	[inout] set of headers to delete
 *
 * Returns:	0 on success, negative on failure
@@ -600,15 +620,16 @@ EXPORT_SYMBOL(ipa_commit_hdr);
 * ipa_reset_hdr() - reset the current header table in SW (does not commit to
 * HW)
 *
 * @user_only:	[in] indicate delete rules installed by userspace
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_reset_hdr(void)
int ipa_reset_hdr(bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_reset_hdr);
	IPA_API_DISPATCH_RETURN(ipa_reset_hdr, user_only);

	return ret;
}
@@ -678,16 +699,18 @@ EXPORT_SYMBOL(ipa_copy_hdr);
 * ipa_add_hdr_proc_ctx() - add the specified headers to SW
 * and optionally commit them to IPA HW
 * @proc_ctxs:	[inout] set of processing context headers to add
 * @user_only:	[in] indicate rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs)
int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
							bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs);
	IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs, user_only);

	return ret;
}
@@ -732,6 +755,26 @@ int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules)
}
EXPORT_SYMBOL(ipa_add_rt_rule);

/**
 * ipa_add_rt_rule_usr() - Add the specified routing rules to SW and optionally
 * commit to IPA HW
 * @rules:	[inout] set of routing rules to add
 * @user_only:	[in] indicate rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_add_rt_rule_usr, rules, user_only);

	return ret;
}
EXPORT_SYMBOL(ipa_add_rt_rule_usr);

/**
 * ipa_del_rt_rule() - Remove the specified routing rules to SW and optionally
 * commit to IPA HW
@@ -774,16 +817,17 @@ EXPORT_SYMBOL(ipa_commit_rt);
 * ipa_reset_rt() - reset the current SW routing table of specified type
 * (does not commit to HW)
 * @ip:	The family of routing tables
 * @user_only:	[in] indicate delete rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_reset_rt(enum ipa_ip_type ip)
int ipa_reset_rt(enum ipa_ip_type ip, bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip);
	IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip, user_only);

	return ret;
}
@@ -866,6 +910,7 @@ EXPORT_SYMBOL(ipa_mdfy_rt_rule);
/**
 * ipa_add_flt_rule() - Add the specified filtering rules to SW and optionally
 * commit to IPA HW
 * @rules:	[inout] set of filtering rules to add
 *
 * Returns:	0 on success, negative on failure
 *
@@ -881,6 +926,26 @@ int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules)
}
EXPORT_SYMBOL(ipa_add_flt_rule);

/**
 * ipa_add_flt_rule_usr() - Add the specified filtering rules to
 * SW and optionally commit to IPA HW
 * @rules:		[inout] set of filtering rules to add
 * @user_only:	[in] indicate rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_add_flt_rule_usr, rules, user_only);

	return ret;
}
EXPORT_SYMBOL(ipa_add_flt_rule_usr);

/**
 * ipa_del_flt_rule() - Remove the specified filtering rules from SW and
 * optionally commit to IPA HW
@@ -940,16 +1005,17 @@ EXPORT_SYMBOL(ipa_commit_flt);
 * ipa_reset_flt() - Reset the current SW filtering table of specified type
 * (does not commit to HW)
 * @ip:			[in] the family of routing tables
 * @user_only:	[in] indicate delete rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_reset_flt(enum ipa_ip_type ip)
int ipa_reset_flt(enum ipa_ip_type ip, bool user_only)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip);
	IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip, user_only);

	return ret;
}
@@ -2502,7 +2568,7 @@ static int ipa_generic_plat_drv_probe(struct platform_device *pdev_p)
{
	int result;

	/*
/**
 * IPA probe function can be called for multiple times as the same probe
 * function handles multiple compatibilities
 */
+14 −5
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -70,11 +70,13 @@ struct ipa_api_controller {

	int (*ipa_add_hdr)(struct ipa_ioc_add_hdr *hdrs);

	int (*ipa_add_hdr_usr)(struct ipa_ioc_add_hdr *hdrs, bool user_only);

	int (*ipa_del_hdr)(struct ipa_ioc_del_hdr *hdls);

	int (*ipa_commit_hdr)(void);

	int (*ipa_reset_hdr)(void);
	int (*ipa_reset_hdr)(bool user_only);

	int (*ipa_get_hdr)(struct ipa_ioc_get_hdr *lookup);

@@ -82,17 +84,21 @@ struct ipa_api_controller {

	int (*ipa_copy_hdr)(struct ipa_ioc_copy_hdr *copy);

	int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
	int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
								bool user_only);

	int (*ipa_del_hdr_proc_ctx)(struct ipa_ioc_del_hdr_proc_ctx *hdls);

	int (*ipa_add_rt_rule)(struct ipa_ioc_add_rt_rule *rules);

	int (*ipa_add_rt_rule_usr)(struct ipa_ioc_add_rt_rule *rules,
							bool user_only);

	int (*ipa_del_rt_rule)(struct ipa_ioc_del_rt_rule *hdls);

	int (*ipa_commit_rt)(enum ipa_ip_type ip);

	int (*ipa_reset_rt)(enum ipa_ip_type ip);
	int (*ipa_reset_rt)(enum ipa_ip_type ip, bool user_only);

	int (*ipa_get_rt_tbl)(struct ipa_ioc_get_rt_tbl *lookup);

@@ -104,13 +110,16 @@ struct ipa_api_controller {

	int (*ipa_add_flt_rule)(struct ipa_ioc_add_flt_rule *rules);

	int (*ipa_add_flt_rule_usr)(struct ipa_ioc_add_flt_rule *rules,
								bool user_only);

	int (*ipa_del_flt_rule)(struct ipa_ioc_del_flt_rule *hdls);

	int (*ipa_mdfy_flt_rule)(struct ipa_ioc_mdfy_flt_rule *rules);

	int (*ipa_commit_flt)(enum ipa_ip_type ip);

	int (*ipa_reset_flt)(enum ipa_ip_type ip);
	int (*ipa_reset_flt)(enum ipa_ip_type ip, bool user_only);

	int (*allocate_nat_device)(struct ipa_ioc_nat_alloc_mem *mem);

+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -334,11 +334,13 @@ struct ipa_mhi_connect_params_internal {
 * @link: entry's link in global header offset entries list
 * @offset: the offset
 * @bin: bin
 * @ipacm_installed: indicate if installed by ipacm
 */
struct ipa_hdr_offset_entry {
	struct list_head link;
	u32 offset;
	u32 bin;
	bool ipacm_installed;
};

extern const char *ipa_clients_strings[];
+53 −9
Original line number Diff line number Diff line
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -280,6 +280,28 @@ int ipa2_active_clients_log_print_table(char *buf, int size)
	return cnt;
}


static int ipa2_clean_modem_rule(void)
{
	struct ipa_install_fltr_rule_req_msg_v01 *req;
	int val = 0;

	req = kzalloc(
		sizeof(struct ipa_install_fltr_rule_req_msg_v01),
		GFP_KERNEL);
	if (!req) {
		IPAERR("mem allocated failed!\n");
		return -ENOMEM;
	}
	req->filter_spec_list_valid = false;
	req->filter_spec_list_len = 0;
	req->source_pipe_index_valid = 0;
	val = qmi_filter_request_send(req);
	kfree(req);

	return val;
}

static int ipa2_active_clients_panic_notifier(struct notifier_block *this,
		unsigned long event, void *ptr)
{
@@ -718,7 +740,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			retval = -EINVAL;
			break;
		}
		if (ipa2_add_hdr((struct ipa_ioc_add_hdr *)param)) {
		if (ipa2_add_hdr_usr((struct ipa_ioc_add_hdr *)param,
			true)) {
			retval = -EFAULT;
			break;
		}
@@ -798,7 +821,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			retval = -EINVAL;
			break;
		}
		if (ipa2_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) {
		if (ipa2_add_rt_rule_usr((struct ipa_ioc_add_rt_rule *)param,
				true)) {
			retval = -EFAULT;
			break;
		}
@@ -917,7 +941,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			retval = -EINVAL;
			break;
		}
		if (ipa2_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) {
		if (ipa2_add_flt_rule_usr((struct ipa_ioc_add_flt_rule *)param,
				true)) {
			retval = -EFAULT;
			break;
		}
@@ -1011,19 +1036,19 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		retval = ipa2_commit_hdr();
		break;
	case IPA_IOC_RESET_HDR:
		retval = ipa2_reset_hdr();
		retval = ipa2_reset_hdr(false);
		break;
	case IPA_IOC_COMMIT_RT:
		retval = ipa2_commit_rt(arg);
		break;
	case IPA_IOC_RESET_RT:
		retval = ipa2_reset_rt(arg);
		retval = ipa2_reset_rt(arg, false);
		break;
	case IPA_IOC_COMMIT_FLT:
		retval = ipa2_commit_flt(arg);
		break;
	case IPA_IOC_RESET_FLT:
		retval = ipa2_reset_flt(arg);
		retval = ipa2_reset_flt(arg, false);
		break;
	case IPA_IOC_GET_RT_TBL:
		if (copy_from_user(header, (u8 *)arg,
@@ -1403,7 +1428,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			break;
		}
		if (ipa2_add_hdr_proc_ctx(
			(struct ipa_ioc_add_hdr_proc_ctx *)param)) {
			(struct ipa_ioc_add_hdr_proc_ctx *)param, true)) {
			retval = -EFAULT;
			break;
		}
@@ -1467,7 +1492,22 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		}
		break;

	default:        /* redundant, as cmd was checked against MAXNR */
	case IPA_IOC_CLEANUP:
		/*Route and filter rules will also be clean*/
		IPADBG("Got IPA_IOC_CLEANUP\n");
		retval = ipa2_reset_hdr(true);
		memset(&nat_del, 0, sizeof(nat_del));
		nat_del.table_index = 0;
		retval = ipa2_nat_del_cmd(&nat_del);
		retval = ipa2_clean_modem_rule();
		break;

	case IPA_IOC_QUERY_WLAN_CLIENT:
		IPADBG("Got IPA_IOC_QUERY_WLAN_CLIENT\n");
		retval = ipa2_resend_wlan_msg();
		break;

	default:
		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
		return -ENOTTY;
	}
@@ -4202,6 +4242,10 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p,
	init_waitqueue_head(&ipa_ctx->msg_waitq);
	mutex_init(&ipa_ctx->msg_lock);

	/* store wlan client-connect-msg-list */
	INIT_LIST_HEAD(&ipa_ctx->msg_wlan_client_list);
	mutex_init(&ipa_ctx->msg_wlan_client_lock);

	mutex_init(&ipa_ctx->lock);
	mutex_init(&ipa_ctx->nat_mem.lock);
	mutex_init(&ipa_ctx->ipa_cne_evt_lock);
+55 −28
Original line number Diff line number Diff line
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -1008,7 +1008,7 @@ fail_desc:

static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip,
			      const struct ipa_flt_rule *rule, u8 add_rear,
			      u32 *rule_hdl)
			      u32 *rule_hdl, bool user)
{
	struct ipa_flt_entry *entry;
	struct ipa_rt_tbl *rt_tbl = NULL;
@@ -1076,6 +1076,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip,
	}
	*rule_hdl = id;
	entry->id = id;
	entry->ipacm_installed = user;
	IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt);

	return 0;
@@ -1198,12 +1199,12 @@ static int __ipa_add_global_flt_rule(enum ipa_ip_type ip,
	tbl = &ipa_ctx->glob_flt_tbl[ip];
	IPADBG_LOW("add global flt rule ip=%d\n", ip);

	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl);
	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, false);
}

static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep,
				 const struct ipa_flt_rule *rule, u8 add_rear,
				 u32 *rule_hdl)
				 u32 *rule_hdl, bool user)
{
	struct ipa_flt_tbl *tbl;
	int ipa_ep_idx;
@@ -1225,18 +1226,34 @@ static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep,
	tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][ip];
	IPADBG_LOW("add ep flt rule ip=%d ep=%d\n", ip, ep);

	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl);
	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, user);
}

/**
 * ipa2_add_flt_rule() - Add the specified filtering rules to SW and optionally
 * commit to IPA HW
 * @rules:	[inout] set of filtering rules to add
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules)
{
	return ipa2_add_flt_rule_usr(rules, false);
}

/**
 * ipa2_add_flt_rule_usr() - Add the specified filtering rules
 * to SW and optionally commit to IPA HW
 * @rules:	[inout] set of filtering rules to add
 * @user_only:	[in] indicate rules installed by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa2_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only)
{
	int i;
	int result;
@@ -1259,7 +1276,8 @@ int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules)
			result = __ipa_add_ep_flt_rule(rules->ip, rules->ep,
					&rules->rules[i].rule,
					rules->rules[i].at_rear,
					&rules->rules[i].flt_rule_hdl);
					&rules->rules[i].flt_rule_hdl,
					user_only);
		if (result) {
			IPAERR_RL("failed to add flt rule %d\n", i);
			rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED;
@@ -1397,12 +1415,13 @@ bail:
 * ipa2_reset_flt() - Reset the current SW filtering table of specified type
 * (does not commit to HW)
 * @ip:			[in] the family of routing tables
 * @user_only:	[in] indicate rules deleted by userspace
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa2_reset_flt(enum ipa_ip_type ip)
int ipa2_reset_flt(enum ipa_ip_type ip, bool user_only)
{
	struct ipa_flt_tbl *tbl;
	struct ipa_flt_entry *entry;
@@ -1435,6 +1454,8 @@ int ipa2_reset_flt(enum ipa_ip_type ip)
		      IPA_INVALID_L4_PROTOCOL))
			continue;

		if (!user_only ||
				entry->ipacm_installed) {
			list_del(&entry->link);
			entry->tbl->rule_cnt--;
			if (entry->rt_tbl)
@@ -1446,6 +1467,7 @@ int ipa2_reset_flt(enum ipa_ip_type ip)
			/* remove the handle from the database */
			ipa_id_remove(id);
		}
	}

	for (i = 0; i < ipa_ctx->ipa_num_pipes; i++) {
		tbl = &ipa_ctx->flt_tbl[i][ip];
@@ -1456,18 +1478,23 @@ int ipa2_reset_flt(enum ipa_ip_type ip)
				mutex_unlock(&ipa_ctx->lock);
				return -EFAULT;
			}

			if (!user_only ||
				entry->ipacm_installed) {
				list_del(&entry->link);
				entry->tbl->rule_cnt--;
				if (entry->rt_tbl)
					entry->rt_tbl->ref_cnt--;
				entry->cookie = 0;
				id = entry->id;
			kmem_cache_free(ipa_ctx->flt_rule_cache, entry);
				kmem_cache_free(ipa_ctx->flt_rule_cache,
					entry);

				/* remove the handle from the database */
				ipa_id_remove(id);
			}
		}
	}
	mutex_unlock(&ipa_ctx->lock);

	return 0;
@@ -1485,14 +1512,14 @@ void ipa_install_dflt_flt_rules(u32 ipa_ep_idx)
	tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4];
	rule.action = IPA_PASS_TO_EXCEPTION;
	__ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true,
			&ep->dflt_flt4_rule_hdl);
			&ep->dflt_flt4_rule_hdl, false);
	ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v4);
	tbl->sticky_rear = true;

	tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6];
	rule.action = IPA_PASS_TO_EXCEPTION;
	__ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true,
			&ep->dflt_flt6_rule_hdl);
			&ep->dflt_flt6_rule_hdl, false);
	ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v6);
	tbl->sticky_rear = true;
	mutex_unlock(&ipa_ctx->lock);
Loading