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

Commit 8ab8f8f2 authored by Karthik Anantha Ram's avatar Karthik Anantha Ram
Browse files

msm: camera: Memory allocation using cma



For large contiguous memory allocations cma_alloc is
to be used over kzalloc to avoid higher order page
allocation failures.

Change-Id: Iedb2ce8e6e7a9bf936f3f1b5bdbd2634ad25697c
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
parent 3a2bdc26
Loading
Loading
Loading
Loading
+25 −11
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 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
@@ -299,6 +299,7 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
	uint16_t                           total_bytes = 0;
	uint8_t                           *ptr = NULL;
	int32_t                            rc = 0, cnt;
	uint32_t                           fw_size;
	const struct firmware             *fw = NULL;
	const char                        *fw_name_prog = NULL;
	const char                        *fw_name_coeff = NULL;
@@ -306,6 +307,7 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
	char                               name_coeff[32] = {0};
	struct device                     *dev = &(o_ctrl->pdev->dev);
	struct cam_sensor_i2c_reg_setting  i2c_reg_setting;
	struct page                       *page = NULL;

	if (!o_ctrl) {
		CAM_ERR(CAM_OIS, "Invalid Args");
@@ -331,15 +333,19 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
	i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.size = total_bytes;
	i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)
		kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes,
		GFP_KERNEL);
	if (!i2c_reg_setting.reg_setting) {
	fw_size = PAGE_ALIGN(sizeof(struct cam_sensor_i2c_reg_array) *
		total_bytes) >> PAGE_SHIFT;
	page = cma_alloc(dev_get_cma_area((o_ctrl->soc_info.dev)),
		fw_size, 0);
	if (!page) {
		CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
		release_firmware(fw);
		return -ENOMEM;
	}

	i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)(
		page_address(page));

	for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
		cnt++, ptr++) {
		i2c_reg_setting.reg_setting[cnt].reg_addr =
@@ -355,7 +361,10 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
		CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
		goto release_firmware;
	}
	kfree(i2c_reg_setting.reg_setting);
	cma_release(dev_get_cma_area((o_ctrl->soc_info.dev)),
		page, fw_size);
	page = NULL;
	fw_size = 0;
	release_firmware(fw);

	rc = request_firmware(&fw, fw_name_coeff, dev);
@@ -368,15 +377,19 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
	i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
	i2c_reg_setting.size = total_bytes;
	i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)
		kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes,
		GFP_KERNEL);
	if (!i2c_reg_setting.reg_setting) {
	fw_size = PAGE_ALIGN(sizeof(struct cam_sensor_i2c_reg_array) *
		total_bytes) >> PAGE_SHIFT;
	page = cma_alloc(dev_get_cma_area((o_ctrl->soc_info.dev)),
		fw_size, 0);
	if (!page) {
		CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
		release_firmware(fw);
		return -ENOMEM;
	}

	i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)(
		page_address(page));

	for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
		cnt++, ptr++) {
		i2c_reg_setting.reg_setting[cnt].reg_addr =
@@ -392,7 +405,8 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
		CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);

release_firmware:
	kfree(i2c_reg_setting.reg_setting);
	cma_release(dev_get_cma_area((o_ctrl->soc_info.dev)),
		page, fw_size);
	release_firmware(fw);

	return rc;
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 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
@@ -12,6 +12,8 @@
#ifndef _CAM_OIS_CORE_H_
#define _CAM_OIS_CORE_H_

#include <linux/cma.h>
#include <linux/dma-contiguous.h>
#include "cam_ois_dev.h"

/**
+25 −7
Original line number Diff line number Diff line
@@ -112,31 +112,49 @@ static int32_t cam_spi_tx_helper(struct camera_io_master *client,
{
	int32_t rc = -EINVAL;
	struct spi_device *spi = client->spi_client->spi_master;
	struct device *dev = NULL;
	char *ctx = NULL, *crx = NULL;
	uint32_t len, hlen;
	uint8_t retries = client->spi_client->retries;
	uint32_t txr = 0, rxr = 0;
	struct page *page_tx = NULL, *page_rx = NULL;

	hlen = cam_camera_spi_get_hlen(inst);
	len = hlen + num_byte;
	dev = &(spi->dev);

	if (!dev) {
		CAM_ERR(CAM_SENSOR, "Invalid arguments");
		return -EINVAL;
	}

	if (tx) {
		ctx = tx;
	} else {
		ctx = kzalloc(len, GFP_KERNEL | GFP_DMA);
		if (!ctx)
		txr = PAGE_ALIGN(len) >> PAGE_SHIFT;
		page_tx = cma_alloc(dev_get_cma_area(dev),
			txr, 0);
		if (!page_tx)
			return -ENOMEM;

		ctx = page_address(page_tx);
	}

	if (num_byte) {
		if (rx) {
			crx = rx;
		} else {
			crx = kzalloc(len, GFP_KERNEL | GFP_DMA);
			if (!crx) {
			rxr = PAGE_ALIGN(len) >> PAGE_SHIFT;
			page_rx = cma_alloc(dev_get_cma_area(dev),
				rxr, 0);
			if (!page_rx) {
				if (!tx)
					kfree(ctx);
					cma_release(dev_get_cma_area(dev),
						page_tx, txr);

				return -ENOMEM;
			}
			crx = page_address(page_rx);
		}
	} else {
		crx = NULL;
@@ -157,9 +175,9 @@ static int32_t cam_spi_tx_helper(struct camera_io_master *client,

out:
	if (!tx)
		kfree(ctx);
		cma_release(dev_get_cma_area(dev), page_tx, txr);
	if (!rx)
		kfree(crx);
		cma_release(dev_get_cma_area(dev), page_rx, rxr);
	return rc;
}

+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#define _CAM_SENSOR_SPI_H_

#include <linux/spi/spi.h>
#include <linux/cma.h>
#include <linux/dma-contiguous.h>
#include <media/cam_sensor.h>
#include "cam_sensor_i2c.h"