From 86eb047ba551b15d637fe2e7dbc0765358ba73ab Mon Sep 17 00:00:00 2001 From: Amir Levy Date: Tue, 29 Aug 2017 16:36:43 +0300 Subject: [PATCH] msm: ipa3: fix compatibility with ipa user space Implement several IOCTLs to allow IPA user space work. Change-Id: I726f665ada12c5524dabeab1b89cdc8db4dc6f1e Acked-by: Dmitry Kogan Signed-off-by: Amir Levy --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 86 +++++++++++++++++++++++ drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 4 +- drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 59 ++++++++++++++-- 3 files changed, 142 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 2615db4e9755..1aacfc8cf266 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -143,6 +143,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) @@ -152,6 +155,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) @@ -207,6 +213,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 0x0C0311 @@ -619,8 +637,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; @@ -659,6 +679,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))) { @@ -719,6 +759,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))) { @@ -2997,6 +3049,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; @@ -3068,6 +3148,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; @@ -3077,6 +3160,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; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index f12eb6ded556..7da78457f1b1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -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 @@ -1641,12 +1640,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 diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index 0256ff89ae24..a78a0a608cb4 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -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); +} +