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

Commit d3d92fb2 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: send NOP write register command before NAT_INIT imm cm0064"

parents de3f351e 4b595252
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, 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
@@ -698,6 +698,9 @@ struct ipa_nat_mem {
	u32 size_base_tables;
	u32 size_expansion_tables;
	u32 public_ip_addr;
	void *tmp_vaddr;
	dma_addr_t tmp_dma_handle;
	bool is_tmp_mem;
};

/**
+112 −26
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, 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
@@ -23,6 +23,7 @@

#define IPA_NAT_SYSTEM_MEMORY  0
#define IPA_NAT_SHARED_MEMORY  1
#define IPA_NAT_TEMP_MEM_SIZE 128

static int ipa_nat_vma_fault_remap(
	 struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -113,6 +114,31 @@ static const struct file_operations ipa_nat_fops = {
	.mmap = ipa_nat_mmap
};

/**
 * allocate_temp_nat_memory() - Allocates temp nat memory
 *
 * Called during nat table delete
 */
void allocate_temp_nat_memory(void)
{
	struct ipa_nat_mem *nat_ctx = &(ipa_ctx->nat_mem);
	int gfp_flags = GFP_KERNEL | __GFP_ZERO;

	nat_ctx->tmp_vaddr =
		dma_alloc_coherent(ipa_ctx->pdev, IPA_NAT_TEMP_MEM_SIZE,
				&nat_ctx->tmp_dma_handle, gfp_flags);

	if (nat_ctx->tmp_vaddr == NULL) {
		IPAERR("Temp Memory alloc failed\n");
		nat_ctx->is_tmp_mem = false;
		return;
	}

	nat_ctx->is_tmp_mem = true;
	IPADBG("IPA NAT allocated temp memory successfully\n");
	return;
}

/**
 * create_nat_device() - Create the NAT device
 *
@@ -167,6 +193,7 @@ int create_nat_device(void)
			MINOR(nat_ctx->dev_num));

	nat_ctx->is_dev = true;
	allocate_temp_nat_memory();
	IPADBG("IPA NAT device created successfully\n");
	result = 0;
	goto bail;
@@ -225,6 +252,12 @@ int allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem)
		goto bail;
	}

	if (nat_ctx->is_dev_init == true) {
		IPAERR("Device already init\n");
		result = 0;
		goto bail;
	}

	if (mem->size <= 0 ||
			nat_ctx->is_dev_init == true) {
		IPAERR("Invalid Parameters or device is already init\n");
@@ -270,7 +303,8 @@ bail:
 */
int ipa_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
{
	struct ipa_desc desc = { 0 };
	struct ipa_register_write *reg_write_nop;
	struct ipa_desc desc[2];
	struct ipa_ip_v4_nat_init *cmd;
	u16 size = sizeof(struct ipa_ip_v4_nat_init);
	int result;
@@ -292,11 +326,31 @@ int ipa_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		goto bail;
	}

	memset(&desc, 0, sizeof(desc));
	/* NO-OP IC for ensuring that IPA pipeline is empty */
	reg_write_nop = kzalloc(sizeof(*reg_write_nop), GFP_KERNEL);
	if (!reg_write_nop) {
		IPAERR("no mem\n");
		result = -ENOMEM;
		goto bail;
	}

	reg_write_nop->skip_pipeline_clear = 0;
	reg_write_nop->value_mask = 0x0;

	desc[0].opcode = IPA_REGISTER_WRITE;
	desc[0].type = IPA_IMM_CMD_DESC;
	desc[0].callback = NULL;
	desc[0].user1 = NULL;
	desc[0].user2 = 0;
	desc[0].pyld = (void *)reg_write_nop;
	desc[0].len = sizeof(*reg_write_nop);

	cmd = kmalloc(size, GFP_KERNEL);
	if (!cmd) {
		IPAERR("Failed to alloc immediate command object\n");
		result = -ENOMEM;
		goto bail;
		goto free_nop;
	}
	if (ipa_ctx->nat_mem.vaddr) {
		IPADBG("using system memory for nat table\n");
@@ -323,7 +377,7 @@ int ipa_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
			IPAERR("index_expn_offset: 0x%x\n",
				init->index_expn_offset);
			result = -EPERM;
			goto free_cmd;
			goto free_mem;
		}
		cmd->ipv4_rules_addr =
			ipa_ctx->nat_mem.dma_handle + init->ipv4_rules_offset;
@@ -367,18 +421,18 @@ int ipa_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	IPADBG("Expansion Table size:0x%x\n", cmd->size_expansion_tables);
	cmd->public_ip_addr = init->ip_addr;
	IPADBG("Public ip address:0x%x\n", cmd->public_ip_addr);
	desc.opcode = IPA_IP_V4_NAT_INIT;
	desc.type = IPA_IMM_CMD_DESC;
	desc.callback = NULL;
	desc.user1 = NULL;
	desc.user2 = 0;
	desc.pyld = (void *)cmd;
	desc.len = size;
	desc[1].opcode = IPA_IP_V4_NAT_INIT;
	desc[1].type = IPA_IMM_CMD_DESC;
	desc[1].callback = NULL;
	desc[1].user1 = NULL;
	desc[1].user2 = 0;
	desc[1].pyld = (void *)cmd;
	desc[1].len = size;
	IPADBG("posting v4 init command\n");
	if (ipa_send_cmd(1, &desc)) {
	if (ipa_send_cmd(2, desc)) {
		IPAERR("Fail to send immediate command\n");
		result = -EPERM;
		goto free_cmd;
		goto free_mem;
	}

	ipa_ctx->nat_mem.public_ip_addr = init->ip_addr;
@@ -412,8 +466,10 @@ int ipa_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)

	IPADBG("return\n");
	result = 0;
free_cmd:
free_mem:
	kfree(cmd);
free_nop:
	kfree(reg_write_nop);
bail:
	return result;
}
@@ -518,7 +574,8 @@ void ipa_nat_free_mem_and_device(struct ipa_nat_mem *nat_ctx)
 */
int ipa_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)
{
	struct ipa_desc desc = { 0 };
	struct ipa_register_write *reg_write_nop;
	struct ipa_desc desc[2];
	struct ipa_ip_v4_nat_init *cmd;
	u16 size = sizeof(struct ipa_ip_v4_nat_init);
	u8 mem_type = IPA_NAT_SHARED_MEMORY;
@@ -526,16 +583,43 @@ int ipa_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)
	int result;

	IPADBG("\n");
	if (ipa_ctx->nat_mem.is_tmp_mem) {
		IPAERR("using temp memory during nat del\n");
		mem_type = IPA_NAT_SYSTEM_MEMORY;
		base_addr = ipa_ctx->nat_mem.tmp_dma_handle;
	}

	if (del->public_ip_addr == 0) {
		IPADBG("Bad Parameter\n");
		result = -EPERM;
		goto bail;
	}

	memset(&desc, 0, sizeof(desc));
	/* NO-OP IC for ensuring that IPA pipeline is empty */
	reg_write_nop = kzalloc(sizeof(*reg_write_nop), GFP_KERNEL);
	if (!reg_write_nop) {
		IPAERR("no mem\n");
		result = -ENOMEM;
		goto bail;
	}

	reg_write_nop->skip_pipeline_clear = 0;
	reg_write_nop->value_mask = 0x0;

	desc[0].opcode = IPA_REGISTER_WRITE;
	desc[0].type = IPA_IMM_CMD_DESC;
	desc[0].callback = NULL;
	desc[0].user1 = NULL;
	desc[0].user2 = 0;
	desc[0].pyld = (void *)reg_write_nop;
	desc[0].len = sizeof(*reg_write_nop);

	cmd = kmalloc(size, GFP_KERNEL);
	if (cmd == NULL) {
		IPAERR("Failed to alloc immediate command object\n");
		result = -ENOMEM;
		goto bail;
		goto free_nop;
	}
	cmd->table_index = del->table_index;
	cmd->ipv4_rules_addr = base_addr;
@@ -548,16 +632,16 @@ int ipa_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)
	cmd->index_table_expansion_addr_type = mem_type;
	cmd->size_base_tables = 0;
	cmd->size_expansion_tables = 0;
	cmd->public_ip_addr = del->public_ip_addr;

	desc.opcode = IPA_IP_V4_NAT_INIT;
	desc.type = IPA_IMM_CMD_DESC;
	desc.callback = NULL;
	desc.user1 = NULL;
	desc.user2 = 0;
	desc.pyld = (void *)cmd;
	desc.len = size;
	if (ipa_send_cmd(1, &desc)) {
	cmd->public_ip_addr = 0;

	desc[1].opcode = IPA_IP_V4_NAT_INIT;
	desc[1].type = IPA_IMM_CMD_DESC;
	desc[1].callback = NULL;
	desc[1].user1 = NULL;
	desc[1].user2 = 0;
	desc[1].pyld = (void *)cmd;
	desc[1].len = size;
	if (ipa_send_cmd(2, desc)) {
		IPAERR("Fail to send immediate command\n");
		result = -EPERM;
		goto free_mem;
@@ -576,6 +660,8 @@ int ipa_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)
	result = 0;
free_mem:
	kfree(cmd);
free_nop:
	kfree(reg_write_nop);
bail:
	return result;
}