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

Commit 409a43db authored by Amir Levy's avatar Amir Levy
Browse files

msm: ipa3: fix compatibility with ipa user space



Implement several IOCTLs to allow IPA user space work.

Change-Id: I726f665ada12c5524dabeab1b89cdc8db4dc6f1e
Acked-by: default avatarDmitry Kogan <dmitryk@qti.qualcomm.com>
Signed-off-by: default avatarAmir Levy <alevy@codeaurora.org>
parent 27501237
Loading
Loading
Loading
Loading
+86 −0
Original line number Diff line number Diff line
@@ -142,6 +142,9 @@
#define IPA_IOC_ALLOC_NAT_MEM32 _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_ALLOC_NAT_MEM, \
				compat_uptr_t)
#define IPA_IOC_ALLOC_NAT_TABLE32 _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_ALLOC_NAT_TABLE, \
				compat_uptr_t)
#define IPA_IOC_V4_INIT_NAT32 _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_V4_INIT_NAT, \
				compat_uptr_t)
@@ -151,6 +154,9 @@
#define IPA_IOC_V4_DEL_NAT32 _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_V4_DEL_NAT, \
				compat_uptr_t)
#define IPA_IOC_DEL_NAT_TABLE32 _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_DEL_NAT_TABLE, \
				compat_uptr_t)
#define IPA_IOC_GET_NAT_OFFSET32 _IOWR(IPA_IOC_MAGIC, \
				IPA_IOCTL_GET_NAT_OFFSET, \
				compat_uptr_t)
@@ -206,6 +212,18 @@ struct ipa3_ioc_nat_alloc_mem32 {
	compat_size_t size;
	compat_off_t offset;
};

/**
* struct ipa_ioc_nat_ipv6ct_table_alloc32 - table memory allocation
* properties
* @size: input parameter, size of table in bytes
* @offset: output parameter, offset into page in case of system memory
*/
struct ipa_ioc_nat_ipv6ct_table_alloc32 {
	compat_size_t size;
	compat_off_t offset;
};

#endif

#define IPA_TZ_UNLOCK_ATTRIBUTE 0xDEADBEEF
@@ -703,8 +721,10 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
	u8 header[128] = { 0 };
	u8 *param = NULL;
	struct ipa_ioc_nat_alloc_mem nat_mem;
	struct ipa_ioc_nat_ipv6ct_table_alloc table_alloc;
	struct ipa_ioc_v4_nat_init nat_init;
	struct ipa_ioc_v4_nat_del nat_del;
	struct ipa_ioc_nat_ipv6ct_table_del table_del;
	struct ipa_ioc_rm_dependency rm_depend;
	size_t sz;
	int pre_entry;
@@ -743,6 +763,26 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			break;
		}
		break;

	case IPA_IOC_ALLOC_NAT_TABLE:
		if (copy_from_user(&table_alloc, (const void __user *)arg,
			sizeof(struct ipa_ioc_nat_ipv6ct_table_alloc))) {
			retval = -EFAULT;
			break;
		}

		if (ipa3_allocate_nat_table(&table_alloc)) {
			retval = -EFAULT;
			break;
		}
		if (table_alloc.offset &&
			copy_to_user((void __user *)arg, &table_alloc, sizeof(
				struct ipa_ioc_nat_ipv6ct_table_alloc))) {
			retval = -EFAULT;
			break;
		}
		break;

	case IPA_IOC_V4_INIT_NAT:
		if (copy_from_user((u8 *)&nat_init, (u8 *)arg,
					sizeof(struct ipa_ioc_v4_nat_init))) {
@@ -803,6 +843,18 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		}
		break;

	case IPA_IOC_DEL_NAT_TABLE:
		if (copy_from_user(&table_del, (const void __user *)arg,
			sizeof(struct ipa_ioc_nat_ipv6ct_table_del))) {
			retval = -EFAULT;
			break;
		}
		if (ipa3_del_nat_table(&table_del)) {
			retval = -EFAULT;
			break;
		}
		break;

	case IPA_IOC_ADD_HDR:
		if (copy_from_user(header, (u8 *)arg,
					sizeof(struct ipa_ioc_add_hdr))) {
@@ -3285,6 +3337,34 @@ static void ipa3_teardown_apps_pipes(void)
}

#ifdef CONFIG_COMPAT
static long compat_ipa3_nat_ipv6ct_alloc_table(unsigned long arg,
	int (alloc_func)(struct ipa_ioc_nat_ipv6ct_table_alloc *))
{
	long retval;
	struct ipa_ioc_nat_ipv6ct_table_alloc32 table_alloc32;
	struct ipa_ioc_nat_ipv6ct_table_alloc table_alloc;

	retval = copy_from_user(&table_alloc32, (const void __user *)arg,
		sizeof(struct ipa_ioc_nat_ipv6ct_table_alloc32));
	if (retval)
		return retval;

	table_alloc.size = (size_t)table_alloc32.size;
	table_alloc.offset = (off_t)table_alloc32.offset;

	retval = alloc_func(&table_alloc);
	if (retval)
		return retval;

	if (table_alloc.offset) {
		table_alloc32.offset = (compat_off_t)table_alloc.offset;
		retval = copy_to_user((void __user *)arg, &table_alloc32,
			sizeof(struct ipa_ioc_nat_ipv6ct_table_alloc32));
	}

	return retval;
}

long compat_ipa3_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int retval = 0;
@@ -3356,6 +3436,9 @@ long compat_ipa3_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
		}
ret:
		return retval;
	case IPA_IOC_ALLOC_NAT_TABLE32:
		return compat_ipa3_nat_ipv6ct_alloc_table(arg,
			ipa3_allocate_nat_table);
	case IPA_IOC_V4_INIT_NAT32:
		cmd = IPA_IOC_V4_INIT_NAT;
		break;
@@ -3365,6 +3448,9 @@ ret:
	case IPA_IOC_V4_DEL_NAT32:
		cmd = IPA_IOC_V4_DEL_NAT;
		break;
	case IPA_IOC_DEL_NAT_TABLE32:
		cmd = IPA_IOC_DEL_NAT_TABLE;
		break;
	case IPA_IOC_GET_NAT_OFFSET32:
		cmd = IPA_IOC_GET_NAT_OFFSET;
		break;
+3 −1
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@
#include "ipa_uc_offload_i.h"

#define DRV_NAME "ipa"
#define NAT_DEV_NAME "ipaNatTable"
#define IPA_COOKIE 0x57831603
#define IPA_RT_RULE_COOKIE 0x57831604
#define IPA_RT_TBL_COOKIE 0x57831605
@@ -1628,12 +1627,15 @@ int ipa3_reset_flt(enum ipa_ip_type ip);
 * NAT
 */
int ipa3_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem);
int ipa3_allocate_nat_table(
	struct ipa_ioc_nat_ipv6ct_table_alloc *table_alloc);

int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init);

int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma);

int ipa3_nat_del_cmd(struct ipa_ioc_v4_nat_del *del);
int ipa3_del_nat_table(struct ipa_ioc_nat_ipv6ct_table_del *del);

/*
 * Messaging
+53 −6
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ enum nat_table_type {
#define NAT_TABLE_ENTRY_SIZE_BYTE 32
#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4


static int ipa3_nat_vma_fault_remap(
	 struct vm_area_struct *vma, struct vm_fault *vmf)
{
@@ -167,7 +166,7 @@ int ipa3_create_nat_device(void)
	IPADBG("\n");

	mutex_lock(&nat_ctx->lock);
	nat_ctx->class = class_create(THIS_MODULE, NAT_DEV_NAME);
	nat_ctx->class = class_create(THIS_MODULE, IPA_NAT_DEV_NAME);
	if (IS_ERR(nat_ctx->class)) {
		IPAERR("unable to create the class\n");
		result = -ENODEV;
@@ -176,7 +175,7 @@ int ipa3_create_nat_device(void)
	result = alloc_chrdev_region(&nat_ctx->dev_num,
					0,
					1,
					NAT_DEV_NAME);
					IPA_NAT_DEV_NAME);
	if (result) {
		IPAERR("alloc_chrdev_region err.\n");
		result = -ENODEV;
@@ -185,7 +184,7 @@ int ipa3_create_nat_device(void)

	nat_ctx->dev =
	   device_create(nat_ctx->class, NULL, nat_ctx->dev_num, nat_ctx,
			"%s", NAT_DEV_NAME);
			"%s", IPA_NAT_DEV_NAME);

	if (IS_ERR(nat_ctx->dev)) {
		IPAERR("device_create err:%ld\n", PTR_ERR(nat_ctx->dev));
@@ -253,9 +252,10 @@ int ipa3_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem)
	IPADBG("passed memory size %zu\n", mem->size);

	mutex_lock(&nat_ctx->lock);
	if (strcmp(mem->dev_name, NAT_DEV_NAME)) {
	if (strcmp(IPA_NAT_DEV_NAME, mem->dev_name)) {
		IPAERR_RL("Nat device name mismatch\n");
		IPAERR_RL("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name);
		IPAERR_RL("Expect: %s Recv: %s\n",
			IPA_NAT_DEV_NAME, mem->dev_name);
		result = -EPERM;
		goto bail;
	}
@@ -306,6 +306,34 @@ bail:
	return result;
}

/**
* ipa3_allocate_nat_table() - Allocates memory for the NAT table
* @table_alloc: [in/out] memory parameters
*
* Called by NAT client to allocate memory for the table entries.
* Based on the request size either shared or system memory will be used.
*
* Returns:	0 on success, negative on failure
*/
int ipa3_allocate_nat_table(struct ipa_ioc_nat_ipv6ct_table_alloc *table_alloc)
{
	int result;
	struct ipa_ioc_nat_alloc_mem tmp;

	strlcpy(tmp.dev_name, IPA_NAT_DEV_NAME, IPA_RESOURCE_NAME_MAX);
	tmp.size = table_alloc->size;
	tmp.offset = 0;

	result = ipa3_allocate_nat_device(&tmp);
	if (result)
		goto bail;

	table_alloc->offset = tmp.offset;

bail:
	return result;
}

/* IOCTL function handlers */
/**
 * ipa3_nat_init_cmd() - Post IP_V4_NAT_INIT command to IPA HW
@@ -833,3 +861,22 @@ destroy_regwrt_imm_cmd:
bail:
	return result;
}

/**
* ipa3_del_nat_table() - Delete the NAT table
* @del:	[in] delete table parameters
*
* Called by NAT client to delete the table
*
* Returns:	0 on success, negative on failure
*/
int ipa3_del_nat_table(struct ipa_ioc_nat_ipv6ct_table_del *del)
{
	struct ipa_ioc_v4_nat_del tmp;

	tmp.table_index = del->table_index;
	tmp.public_ip_addr = ipa3_ctx->nat_mem.public_ip_addr;

	return ipa3_nat_del_cmd(&tmp);
}