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

Commit 3e41bc8b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: add support to modify filter rules"

parents e6c3f4d0 07f4b6b4
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -127,6 +127,9 @@
#define IPA_IOC_WRITE_QMAPID32  _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_WRITE_QMAPID, \
				compat_uptr_t)
#define IPA_IOC_MDFY_FLT_RULE32 _IOWR(IPA_IOC_MAGIC, \
					IPA_IOCTL_MDFY_FLT_RULE, \
					compat_uptr_t)

/**
 * struct ipa_ioc_nat_alloc_mem32 - nat table memory allocation
@@ -441,6 +444,35 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		}
		break;

	case IPA_IOC_MDFY_FLT_RULE:
		if (copy_from_user(header, (u8 *)arg,
					sizeof(struct ipa_ioc_mdfy_flt_rule))) {
			retval = -EFAULT;
			break;
		}
		pyld_sz =
		   sizeof(struct ipa_ioc_mdfy_flt_rule) +
		   ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules *
		   sizeof(struct ipa_flt_rule_mdfy);
		param = kzalloc(pyld_sz, GFP_KERNEL);
		if (!param) {
			retval = -ENOMEM;
			break;
		}
		if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		if (ipa_mdfy_flt_rule((struct ipa_ioc_mdfy_flt_rule *)param)) {
			retval = -EFAULT;
			break;
		}
		if (copy_to_user((u8 *)arg, param, pyld_sz)) {
			retval = -EFAULT;
			break;
		}
		break;

	case IPA_IOC_COMMIT_HDR:
		retval = ipa_commit_hdr();
		break;
@@ -1378,6 +1410,9 @@ ret:
	case IPA_IOC_WRITE_QMAPID32:
		cmd = IPA_IOC_WRITE_QMAPID;
		break;
	case IPA_IOC_MDFY_FLT_RULE32:
		cmd = IPA_IOC_MDFY_FLT_RULE;
		break;
	case IPA_IOC_COMMIT_HDR:
	case IPA_IOC_RESET_HDR:
	case IPA_IOC_COMMIT_RT:
+103 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define IPA_FLT_TABLE_INDEX_NOT_FOUND		(-1)
#define IPA_FLT_STATUS_OF_ADD_FAILED		(-1)
#define IPA_FLT_STATUS_OF_DEL_FAILED		(-1)
#define IPA_FLT_STATUS_OF_MDFY_FAILED		(-1)

static int ipa_generate_hw_rule_from_eq(
		const struct ipa_ipfltri_rule_eq *attrib, u8 **buf)
@@ -1068,6 +1069,65 @@ static int __ipa_del_flt_rule(u32 rule_hdl)
	return 0;
}

static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule,
		enum ipa_ip_type ip)
{
	struct ipa_flt_entry *entry;
	struct ipa_rt_tbl *rt_tbl = NULL;

	entry = ipa_id_find(frule->rule_hdl);
	if (entry == NULL) {
		IPAERR("lookup failed\n");
		goto error;
	}

	if (entry->cookie != IPA_COOKIE) {
		IPAERR("bad params\n");
		goto error;
	}

	if (entry->rt_tbl)
		entry->rt_tbl->ref_cnt--;

	if (frule->rule.action != IPA_PASS_TO_EXCEPTION) {
		if (!frule->rule.eq_attrib_type) {
			if (!frule->rule.rt_tbl_hdl) {
				IPAERR("invalid RT tbl\n");
				goto error;
			}

			rt_tbl = ipa_id_find(frule->rule.rt_tbl_hdl);
			if (rt_tbl == NULL) {
				IPAERR("RT tbl not found\n");
				goto error;
			}

			if (rt_tbl->cookie != IPA_COOKIE) {
				IPAERR("RT table cookie is invalid\n");
				goto error;
			}
		} else {
			if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ?
					IPA_v2_V4_MODEM_RT_INDEX_HI :
					IPA_v2_V6_MODEM_RT_INDEX_HI)) {
				IPAERR("invalid RT tbl\n");
				goto error;
			}
		}
	}

	entry->rule = frule->rule;
	entry->rt_tbl = rt_tbl;
	if (entry->rt_tbl)
		entry->rt_tbl->ref_cnt++;
	entry->hw_len = 0;

	return 0;

error:
	return -EPERM;
}

static int __ipa_add_global_flt_rule(enum ipa_ip_type ip,
		const struct ipa_flt_rule *rule, u8 add_rear, u32 *rule_hdl)
{
@@ -1207,6 +1267,49 @@ bail:
}
EXPORT_SYMBOL(ipa_del_flt_rule);

/**
 * ipa_mdfy_flt_rule() - Modify the specified filtering rules in SW and optionally
 * commit to IPA HW
 *
 * Returns:	0 on success, negative on failure
 *
 * Note:	Should not be called from atomic context
 */
int ipa_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *hdls)
{
	int i;
	int result;

	if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) {
		IPAERR("bad parm\n");
		return -EINVAL;
	}

	mutex_lock(&ipa_ctx->lock);
	for (i = 0; i < hdls->num_rules; i++) {
		if (__ipa_mdfy_flt_rule(&hdls->rules[i], hdls->ip)) {
			IPAERR("failed to mdfy rt rule %i\n", i);
			hdls->rules[i].status = IPA_FLT_STATUS_OF_MDFY_FAILED;
		} else {
			hdls->rules[i].status = 0;
		}
	}

	if (hdls->commit)
		if (ipa_ctx->ctrl->ipa_commit_flt(hdls->ip)) {
			mutex_unlock(&ipa_ctx->lock);
			result = -EPERM;
			goto bail;
		}
	result = 0;
bail:
	mutex_unlock(&ipa_ctx->lock);

	return result;
}
EXPORT_SYMBOL(ipa_mdfy_flt_rule);


/**
 * ipa_commit_flt() - Commit the current SW filtering table of specified type to
 * IPA HW
+7 −0
Original line number Diff line number Diff line
@@ -821,6 +821,8 @@ int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules);

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);
@@ -1143,6 +1145,11 @@ static inline int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls)
	return -EPERM;
}

static inline int ipa_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules)
{
	return -EPERM;
}

static inline int ipa_commit_flt(enum ipa_ip_type ip)
{
	return -EPERM;
+36 −1
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@
#define IPA_IOCTL_QUERY_EP_MAPPING 33
#define IPA_IOCTL_QUERY_RT_TBL_INDEX 34
#define IPA_IOCTL_WRITE_QMAPID 35
#define IPA_IOCTL_MAX            36
#define IPA_IOCTL_MDFY_FLT_RULE 36
#define IPA_IOCTL_MAX            37

/**
 * max size of the header to be inserted
@@ -671,6 +672,37 @@ struct ipa_ioc_add_flt_rule {
	struct ipa_flt_rule_add rules[0];
};

/**
 * struct ipa_flt_rule_mdfy - filtering rule descriptor includes
 * in and out parameters
 * @rule: actual rule to be added
 * @flt_rule_hdl: handle to rule
 * @status:	output parameter, status of filtering rule modify  operation,
 *		0 for success,
 *		-1 for failure
 *
 */
struct ipa_flt_rule_mdfy {
	struct ipa_flt_rule rule;
	uint32_t rule_hdl;
	int status;
};

/**
 * struct ipa_ioc_mdfy_flt_rule - filtering rule modify parameters (supports
 * multiple rules and commit)
 * @commit: should rules be written to IPA HW also?
 * @ip: IP family of rule
 * @num_rules: number of filtering rules that follow
 * @rules: all rules need to go back to back here, no pointers
 */
struct ipa_ioc_mdfy_flt_rule {
	uint8_t commit;
	enum ipa_ip_type ip;
	uint8_t num_rules;
	struct ipa_flt_rule_mdfy rules[0];
};

/**
 * struct ipa_flt_rule_del - filtering rule descriptor includes
 * in and out parameters
@@ -1112,6 +1144,9 @@ struct ipa_ioc_write_qmapid {
#define IPA_IOC_WRITE_QMAPID  _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_WRITE_QMAPID, \
				struct ipa_ioc_write_qmapid *)
#define IPA_IOC_MDFY_FLT_RULE _IOWR(IPA_IOC_MAGIC, \
					IPA_IOCTL_MDFY_FLT_RULE, \
					struct ipa_ioc_mdfy_flt_rule *)

/*
 * unique magic number of the Tethering bridge ioctls