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

Commit fd92093b authored by Utkarsh Saxena's avatar Utkarsh Saxena
Browse files

msm: ipa: Fix to use GFP_DMA flag



IPAv2 hardware works with 32 bit addressing,
so allocate a kernel memory using GFP_DMA flag
which is processed by IPA hardware. Added code
changes to free correct tx_pkt pointer in fail_dma_map condition.

Change-Id: I5f7005c3bf89275fd56af648ee5bf1b3d06afc38
Acked-by: default avatarAshok Vuyyuru <avuyyuru@qti.qualcomm.com>
Acked-by: default avatarMohammed Javid <mjavid@qti.qualcomm.com>
Signed-off-by: default avatarUtkarsh Saxena <usaxena@codeaurora.org>
parent 5404e350
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1836,6 +1836,7 @@ static int ipa_q6_clean_q6_tables(void)
	struct ipa_mem_buffer mem = { 0 };
	u32 *entry;
	u32 max_cmds = ipa_get_max_flt_rt_cmds(ipa_ctx->ipa_num_pipes);
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	mem.base = dma_alloc_coherent(ipa_ctx->pdev, 4, &mem.phys_base,
		GFP_ATOMIC);
@@ -1856,7 +1857,7 @@ static int ipa_q6_clean_q6_tables(void)
	}

	cmd = kcalloc(max_cmds, sizeof(struct ipa_hw_imm_cmd_dma_shared_mem),
		GFP_KERNEL);
		flag);
	if (!cmd) {
		IPAERR("failed to allocate memory\n");
		retval = -ENOMEM;
+25 −30
Original line number Diff line number Diff line
@@ -420,15 +420,17 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
	int i = 0;
	int j;
	int result;
	int fail_dma_wrap = 0;
	uint size = num_desc * sizeof(struct sps_iovec);
	u32 mem_flag = GFP_ATOMIC;
	gfp_t mem_flag = GFP_ATOMIC;
	struct sps_iovec iov;
	int ret;
	gfp_t flag;

	if (unlikely(!in_atomic))
		mem_flag = GFP_KERNEL;

	flag = mem_flag | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	if (num_desc == IPA_NUM_DESC_PER_SW_TX) {
		transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag,
				&dma_addr);
@@ -437,7 +439,7 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
			return -EFAULT;
		}
	} else {
		transfer.iovec = kmalloc(size, mem_flag);
		transfer.iovec = kmalloc(size, flag);
		if (!transfer.iovec) {
			IPAERR("fail to alloc mem for sps xfr buff ");
			IPAERR("num_desc = %d size = %d\n", num_desc, size);
@@ -457,7 +459,6 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
	spin_lock_bh(&sys->spinlock);

	for (i = 0; i < num_desc; i++) {
		fail_dma_wrap = 0;
		tx_pkt = kmem_cache_zalloc(ipa_ctx->tx_pkt_wrapper_cache,
					   mem_flag);
		if (!tx_pkt) {
@@ -493,15 +494,6 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
					tx_pkt->mem.base,
					tx_pkt->mem.size,
					DMA_TO_DEVICE);

				if (dma_mapping_error(ipa_ctx->pdev,
					tx_pkt->mem.phys_base)) {
					IPAERR("dma_map_single ");
					IPAERR("failed\n");
					fail_dma_wrap = 1;
					goto failure;
				}

			} else {
				tx_pkt->mem.phys_base = desc[i].dma_address;
				tx_pkt->no_unmap_dma = true;
@@ -522,10 +514,9 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
			}
		}

		if (!tx_pkt->mem.phys_base) {
			IPAERR("failed to alloc tx wrapper\n");
			fail_dma_wrap = 1;
			goto failure;
		if (dma_mapping_error(ipa_ctx->pdev, tx_pkt->mem.phys_base)) {
			IPAERR("dma_map_single failed\n");
			goto failure_dma_map;
		}

		tx_pkt->sys = sys;
@@ -580,27 +571,30 @@ int ipa_send(struct ipa_sys_context *sys, u32 num_desc, struct ipa_desc *desc,
	spin_unlock_bh(&sys->spinlock);
	return 0;

failure_dma_map:
	kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);

failure:
	tx_pkt = transfer.user;
	for (j = 0; j < i; j++) {
		next_pkt = list_next_entry(tx_pkt, link);
		list_del(&tx_pkt->link);
		if (!tx_pkt->no_unmap_dma) {
			if (desc[j].type != IPA_DATA_DESC_SKB_PAGED) {
			dma_unmap_single(ipa_ctx->pdev, tx_pkt->mem.phys_base,
				dma_unmap_single(ipa_ctx->pdev,
					tx_pkt->mem.phys_base,
					tx_pkt->mem.size,
					DMA_TO_DEVICE);
			} else {
			dma_unmap_page(ipa_ctx->pdev, tx_pkt->mem.phys_base,
				dma_unmap_page(ipa_ctx->pdev,
					tx_pkt->mem.phys_base,
					tx_pkt->mem.size,
					DMA_TO_DEVICE);
			}
		}
		kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
		tx_pkt = next_pkt;
	}
	if (j < num_desc)
		/* last desc failed */
		if (fail_dma_wrap)
			kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
	if (transfer.iovec_phys) {
		if (num_desc == IPA_NUM_DESC_PER_SW_TX) {
			dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
@@ -1659,6 +1653,7 @@ int ipa2_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
	struct ipa_sys_context *sys;
	int src_ep_idx;
	int num_frags, f;
	gfp_t flag = GFP_ATOMIC | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	if (unlikely(!ipa_ctx)) {
		IPAERR("IPA driver was not initialized\n");
@@ -1724,7 +1719,7 @@ int ipa2_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,

	if (dst_ep_idx != -1) {
		/* SW data path */
		cmd = kzalloc(sizeof(struct ipa_ip_packet_init), GFP_ATOMIC);
		cmd = kzalloc(sizeof(struct ipa_ip_packet_init), flag);
		if (!cmd) {
			IPAERR("failed to alloc immediate command object\n");
			goto fail_gen;
+4 −2
Original line number Diff line number Diff line
@@ -653,6 +653,7 @@ int __ipa_commit_flt_v1_1(enum ipa_ip_type ip)
	struct ipa_ip_v6_filter_init *v6;
	u16 avail;
	u16 size;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	mem = kmalloc(sizeof(struct ipa_mem_buffer), GFP_KERNEL);
	if (!mem) {
@@ -669,7 +670,7 @@ int __ipa_commit_flt_v1_1(enum ipa_ip_type ip)
			IPA_MEM_PART(v6_flt_size_ddr);
		size = sizeof(struct ipa_ip_v6_filter_init);
	}
	cmd = kmalloc(size, GFP_KERNEL);
	cmd = kmalloc(size, flag);
	if (!cmd) {
		IPAERR("failed to alloc immediate command object\n");
		goto fail_alloc_cmd;
@@ -842,6 +843,7 @@ int __ipa_commit_flt_v2(enum ipa_ip_type ip)
	int num_desc = 0;
	int i;
	u16 avail;
	gfp_t flag = GFP_ATOMIC | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	desc = kzalloc(16 * sizeof(*desc), GFP_ATOMIC);
	if (desc == NULL) {
@@ -850,7 +852,7 @@ int __ipa_commit_flt_v2(enum ipa_ip_type ip)
		goto fail_desc;
	}

	cmd = kzalloc(16 * sizeof(*cmd), GFP_ATOMIC);
	cmd = kzalloc(16 * sizeof(*cmd), flag);
	if (cmd == NULL) {
		IPAERR("fail to alloc cmd blob ip %d\n", ip);
		rc = -ENOMEM;
+4 −2
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@ int __ipa_commit_hdr_v1_1(void)
	struct ipa_mem_buffer *mem;
	struct ipa_hdr_init_local *cmd;
	u16 len;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	mem = kmalloc(sizeof(struct ipa_mem_buffer), GFP_KERNEL);
	if (!mem) {
@@ -190,7 +191,7 @@ int __ipa_commit_hdr_v1_1(void)
	 * we can use init_local ptr for init_system due to layout of the
	 * struct
	 */
	cmd = kmalloc(len, GFP_KERNEL);
	cmd = kmalloc(len, flag);
	if (!cmd) {
		IPAERR("failed to alloc immediate command object\n");
		goto fail_alloc_cmd;
@@ -663,6 +664,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr)
	struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl;
	int id;
	int mem_size;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	if (hdr->hdr_len == 0 || hdr->hdr_len > IPA_HDR_MAX_SIZE) {
		IPAERR("bad parm\n");
@@ -674,7 +676,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr)
		goto error;
	}

	entry = kmem_cache_zalloc(ipa_ctx->hdr_cache, GFP_KERNEL);
	entry = kmem_cache_zalloc(ipa_ctx->hdr_cache, flag);
	if (!entry) {
		IPAERR("failed to alloc hdr object\n");
		goto error;
+10 −7
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, 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
@@ -325,6 +325,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	int result;
	u32 offset = 0;
	size_t tmp;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	IPADBG("\n");
	if (init->table_entries == 0) {
@@ -406,7 +407,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)

	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);
	reg_write_nop = kzalloc(sizeof(*reg_write_nop), flag);
	if (!reg_write_nop) {
		IPAERR("no mem\n");
		result = -ENOMEM;
@@ -424,7 +425,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	desc[0].pyld = (void *)reg_write_nop;
	desc[0].len = sizeof(*reg_write_nop);

	cmd = kmalloc(size, GFP_KERNEL);
	cmd = kmalloc(size, flag);
	if (!cmd) {
		IPAERR("Failed to alloc immediate command object\n");
		result = -ENOMEM;
@@ -569,6 +570,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma)
	struct ipa_desc *desc = NULL;
	u16 size = 0, cnt = 0;
	int ret = 0;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	IPADBG("\n");
	if (dma->entries <= 0) {
@@ -652,7 +654,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma)
	}

	size = sizeof(struct ipa_nat_dma);
	cmd = kzalloc(size, GFP_KERNEL);
	cmd = kzalloc(size, flag);
	if (cmd == NULL) {
		IPAERR("Failed to alloc memory\n");
		ret = -ENOMEM;
@@ -660,7 +662,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma)
	}

	/* NO-OP IC for ensuring that IPA pipeline is empty */
	reg_write_nop = kzalloc(sizeof(*reg_write_nop), GFP_KERNEL);
	reg_write_nop = kzalloc(sizeof(*reg_write_nop), flag);
	if (!reg_write_nop) {
		IPAERR("Failed to alloc memory\n");
		ret = -ENOMEM;
@@ -754,6 +756,7 @@ int ipa2_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)
	u8 mem_type = IPA_NAT_SHARED_MEMORY;
	u32 base_addr = IPA_NAT_PHYS_MEM_OFFSET;
	int result;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);

	IPADBG("\n");
	if (ipa_ctx->nat_mem.is_tmp_mem) {
@@ -770,7 +773,7 @@ int ipa2_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)

	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);
	reg_write_nop = kzalloc(sizeof(*reg_write_nop), flag);
	if (!reg_write_nop) {
		IPAERR("no mem\n");
		result = -ENOMEM;
@@ -788,7 +791,7 @@ int ipa2_nat_del_cmd(struct ipa_ioc_v4_nat_del *del)
	desc[0].pyld = (void *)reg_write_nop;
	desc[0].len = sizeof(*reg_write_nop);

	cmd = kmalloc(size, GFP_KERNEL);
	cmd = kmalloc(size, flag);
	if (cmd == NULL) {
		IPAERR("Failed to alloc immediate command object\n");
		result = -ENOMEM;
Loading