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

Commit 8efdb49a authored by Vikram Mulukutla's avatar Vikram Mulukutla Committed by Stephen Boyd
Browse files

msm: peripheral_loader: Use the new request_firmware_direct API



The request_firmware_direct API is more suited to devices
with memory constraints. Replace the call to request_firmware
with this new API.

Change-Id: I7e23c7b1f0728126b2b285addf81beee4d80a2b0
Signed-off-by: default avatarVikram Mulukutla <markivx@codeaurora.org>
parent 5c808655
Loading
Loading
Loading
Loading
+29 −36
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/of_gpio.h>
#include <linux/io.h>

#include <asm/uaccess.h>
#include <asm/setup.h>
@@ -285,6 +286,12 @@ static struct pil_seg *pil_init_seg(const struct pil_desc *desc,
		return ERR_PTR(-EPERM);
	}

	if (phdr->p_filesz > phdr->p_memsz) {
		pil_err(desc, "Segment %d: file size (%u) is greater than mem size (%u).\n",
			num, phdr->p_filesz, phdr->p_memsz);
		return ERR_PTR(-EINVAL);
	}

	seg = kmalloc(sizeof(*seg), GFP_KERNEL);
	if (!seg)
		return ERR_PTR(-ENOMEM);
@@ -508,56 +515,45 @@ static void pil_release_mmap(struct pil_desc *desc)

#define IOMAP_SIZE SZ_4M

static void *map_fw_mem(phys_addr_t paddr, size_t size)
{
	return ioremap(paddr, size);
}

static void unmap_fw_mem(void *vaddr)
{
	iounmap(vaddr);
}

static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg)
{
	int ret = 0, count;
	phys_addr_t paddr;
	char fw_name[30];
	const struct firmware *fw = NULL;
	const u8 *data;
	int num = seg->num;

	if (seg->filesz) {
		snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d",
				desc->name, num);
		ret = request_firmware(&fw, fw_name, desc->dev);
		if (ret) {
			pil_err(desc, "Failed to locate blob %s\n", fw_name);
		ret = request_firmware_direct(fw_name, desc->dev, seg->paddr,
					      seg->filesz, map_fw_mem,
					      unmap_fw_mem);
		if (ret < 0) {
			pil_err(desc, "Failed to locate blob %s or blob is too big.\n",
				fw_name);
			return ret;
		}

		if (fw->size != seg->filesz) {
		if (ret != seg->filesz) {
			pil_err(desc, "Blob size %u doesn't match %lu\n",
					fw->size, seg->filesz);
			ret = -EPERM;
			goto release_fw;
					ret, seg->filesz);
			return -EPERM;
		}
	}

	/* Load the segment into memory */
	count = seg->filesz;
	paddr = seg->paddr;
	data = fw ? fw->data : NULL;
	while (count > 0) {
		int size;
		u8 __iomem *buf;

		size = min_t(size_t, IOMAP_SIZE, count);
		buf = ioremap(paddr, size);
		if (!buf) {
			pil_err(desc, "Failed to map memory\n");
			ret = -ENOMEM;
			goto release_fw;
		}
		memcpy(buf, data, size);
		iounmap(buf);

		count -= size;
		paddr += size;
		data += size;
		ret = 0;
	}

	/* Zero out trailing memory */
	paddr = seg->paddr + seg->filesz;
	count = seg->sz - seg->filesz;
	while (count > 0) {
		int size;
@@ -567,8 +563,7 @@ static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg)
		buf = ioremap(paddr, size);
		if (!buf) {
			pil_err(desc, "Failed to map memory\n");
			ret = -ENOMEM;
			goto release_fw;
			return -ENOMEM;
		}
		memset(buf, 0, size);
		iounmap(buf);
@@ -583,8 +578,6 @@ static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg)
			pil_err(desc, "Blob%u failed verification\n", num);
	}

release_fw:
	release_firmware(fw);
	return ret;
}