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

Commit 1c9dc296 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: crypto: Add support for map and unmap ioctls"

parents 0b5a4b47 9b03c1ea
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
* QCEDEV (QTI Crypto Engine Device)

[Root level node]
Crypto Engine
============
Required properties:
  - compatible : should be "qcom,qcedev"
  - reg : should contain crypto, BAM register map.
@@ -24,6 +27,19 @@ Optional properties:
  - iommus : A list of phandle and IOMMU specifier pairs that describe the IOMMU master interfaces of the device.
  - qcom,no-clock-support : indicates clocks are not handled by hlos crypto driver.


[Second level nodes]
Context banks
=============
Required properties:
  - compatible : should be "qcom,qcedev,context-bank"
  - iommus : A phandle parsed by smmu driver. Number of entries will vary across targets.

Optional properties:
  - label - string describing iommu domain usage.
  - virtual-addr : start of virtual address pool.
  - virtual-size : size of virtual address pool.

Example:

	qcom,qcedev@fd440000 {
@@ -43,4 +59,15 @@ Example:
				<56 512 0 0>,
				<56 512 3936000 393600>,
		qcom,ce-opp-freq = <100000000>;

		qcom_cedev_ns_cb {
			compatible = "qcom,qcedev,context-bank";
			label = "ns_context";
			iommus = <&anoc2_smmu 0x1878>,
				<&anoc2_smmu 0x1879>,
				<&anoc2_smmu 0x187c>,
				<&anoc2_smmu 0x187f>;
			virtual-addr = <0x60000000>;
			virtual-size = <0x00200000>;
		};
	};
+1 −0
Original line number Diff line number Diff line
obj-$(CONFIG_CRYPTO_DEV_QCOM_MSM_QCE) += qce50.o
obj-$(CONFIG_CRYPTO_DEV_QCEDEV) += qcedev.o
obj-$(CONFIG_CRYPTO_DEV_QCEDEV) += qcedev_smmu.o
obj-$(CONFIG_CRYPTO_DEV_QCRYPTO) += qcrypto.o
obj-$(CONFIG_CRYPTO_DEV_OTA_CRYPTO) += ota_crypto.o
obj-$(CONFIG_CRYPTO_DEV_QCOM_ICE) += ice.o
+113 −0
Original line number Diff line number Diff line
@@ -254,6 +254,75 @@ static int compat_put_qcedev_cipher_op_req(
	return err;
}

static int compat_xfer_qcedev_map_buf_req(
			struct compat_qcedev_map_buf_req __user *data32,
			struct qcedev_map_buf_req __user *data, bool to_get)
{
	int rc = 0, i = 0, fd = -1;
	uint32_t fd_size, fd_offset, num_fds, buf_vaddr;

	if (to_get) {
		/* copy from compat struct */
		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
			rc |= get_user(fd, &data32->fd[i]);
			rc |= put_user(fd, &data->fd[i]);
			rc |= get_user(fd_size, &data32->fd_size[i]);
			rc |= put_user(fd_size, &data->fd_size[i]);
			rc |= get_user(fd_offset, &data32->fd_offset[i]);
			rc |= put_user(fd_offset, &data->fd_offset[i]);
			rc |= get_user(buf_vaddr, &data32->buf_vaddr[i]);
			rc |= put_user(buf_vaddr, &data->buf_vaddr[i]);
		}

		rc |= get_user(num_fds, &data32->num_fds);
		rc |= put_user(num_fds, &data->num_fds);
	} else {
		/* copy to compat struct */
		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
			rc |= get_user(fd, &data->fd[i]);
			rc |= put_user(fd, &data32->fd[i]);
			rc |= get_user(fd_size, &data->fd_size[i]);
			rc |= put_user(fd_size, &data32->fd_size[i]);
			rc |= get_user(fd_offset, &data->fd_offset[i]);
			rc |= put_user(fd_offset, &data32->fd_offset[i]);
			rc |= get_user(buf_vaddr, &data->buf_vaddr[i]);
			rc |= put_user(buf_vaddr, &data32->buf_vaddr[i]);
		}
		rc |= get_user(num_fds, &data->num_fds);
		rc |= put_user(num_fds, &data32->num_fds);
	}

	return rc;
}

static int compat_xfer_qcedev_unmap_buf_req(
			struct compat_qcedev_unmap_buf_req __user *data32,
			struct qcedev_unmap_buf_req __user *data, bool to_get)
{
	int i = 0, rc = 0, fd = -1;
	uint32_t num_fds;

	if (to_get) {
		/* copy from compat struct */
		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
			rc |= get_user(fd, &data32->fd[i]);
			rc |= put_user(fd, &data->fd[i]);
		}
		rc |= get_user(num_fds, &data32->num_fds);
		rc |= put_user(num_fds, &data->num_fds);
	} else {
		/* copy to compat struct */
		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
			rc |= get_user(fd, &data->fd[i]);
			rc |= put_user(fd, &data32->fd[i]);
		}
		rc |= get_user(num_fds, &data->num_fds);
		rc |= put_user(num_fds, &data32->num_fds);
	}
	return rc;
}


static int compat_get_qcedev_sha_op_req(
		struct compat_qcedev_sha_op_req __user *data32,
		struct qcedev_sha_op_req __user *data)
@@ -359,6 +428,10 @@ static unsigned int convert_cmd(unsigned int cmd)
		return QCEDEV_IOCTL_GET_SHA_REQ;
	case COMPAT_QCEDEV_IOCTL_GET_CMAC_REQ:
		return QCEDEV_IOCTL_GET_CMAC_REQ;
	case COMPAT_QCEDEV_IOCTL_MAP_BUF_REQ:
		return QCEDEV_IOCTL_MAP_BUF_REQ;
	case COMPAT_QCEDEV_IOCTL_UNMAP_BUF_REQ:
		return QCEDEV_IOCTL_UNMAP_BUF_REQ;
	default:
		return cmd;
	}
@@ -412,6 +485,46 @@ long compat_qcedev_ioctl(struct file *file,
		err = compat_put_qcedev_sha_op_req(data32, data);
		return ret ? ret : err;
	}
	case COMPAT_QCEDEV_IOCTL_MAP_BUF_REQ: {
		struct compat_qcedev_map_buf_req __user *data32;
		struct qcedev_map_buf_req __user *data;
		int err;

		data32 = compat_ptr(arg);
		data = compat_alloc_user_space(sizeof(*data));
		if (!data)
			return -EINVAL;

		err = compat_xfer_qcedev_map_buf_req(data32, data, true);
		if (err)
			return err;

		ret = qcedev_ioctl(file, convert_cmd(cmd), (unsigned long)data);
		err = compat_xfer_qcedev_map_buf_req(data32, data, false);
		return ret ? ret : err;

		break;
	}
	case COMPAT_QCEDEV_IOCTL_UNMAP_BUF_REQ: {
		struct compat_qcedev_unmap_buf_req __user *data32;
		struct qcedev_unmap_buf_req __user *data;
		int err;

		data32 = compat_ptr(arg);
		data = compat_alloc_user_space(sizeof(*data));
		if (!data)
			return -EINVAL;

		err = compat_xfer_qcedev_unmap_buf_req(data32, data, true);
		if (err)
			return err;

		ret = qcedev_ioctl(file, convert_cmd(cmd), (unsigned long)data);
		err = compat_xfer_qcedev_unmap_buf_req(data32, data, false);
		return ret ? ret : err;

		break;
	}
	default:
		return -ENOIOCTLCMD;
	}
+31 −1
Original line number Diff line number Diff line
@@ -151,6 +151,33 @@ struct compat_qcedev_sha_op_req {
	enum qcedev_sha_alg_enum		alg;
};

/**
 * struct compact_qcedev_map_buf_req - Holds the mapping request information
 * fd (IN):            Array of fds.
 * num_fds (IN):       Number of fds in fd[].
 * fd_size (IN):       Array of sizes corresponding to each fd in fd[].
 * fd_offset (IN):     Array of offset corresponding to each fd in fd[].
 * vaddr (OUT):        Array of mapped virtual address corresponding to
 *                     each fd in fd[].
 */
struct compat_qcedev_map_buf_req {
	compat_long_t	fd[QCEDEV_MAX_BUFFERS];
	compat_ulong_t	num_fds;
	compat_ulong_t	fd_size[QCEDEV_MAX_BUFFERS];
	compat_ulong_t	fd_offset[QCEDEV_MAX_BUFFERS];
	compat_u64      buf_vaddr[QCEDEV_MAX_BUFFERS];
};

/**
 * struct compat_qcedev_unmap_buf_req - Holds the hashing request information
 * fd (IN):	       Array of fds to unmap
 * num_fds (IN):       Number of fds in fd[].
 */
struct	compat_qcedev_unmap_buf_req {
	compat_long_t	fd[QCEDEV_MAX_BUFFERS];
	compat_ulong_t	num_fds;
};

struct file;
extern long compat_qcedev_ioctl(struct file *file,
			unsigned int cmd, unsigned long arg);
@@ -173,6 +200,9 @@ extern long compat_qcedev_ioctl(struct file *file,
	_IO(QCEDEV_IOC_MAGIC, 8)
#define COMPAT_QCEDEV_IOCTL_GET_CMAC_REQ	\
	_IOWR(QCEDEV_IOC_MAGIC, 9, struct compat_qcedev_sha_op_req)

#define COMPAT_QCEDEV_IOCTL_MAP_BUF_REQ	\
	_IOWR(QCEDEV_IOC_MAGIC, 10, struct compat_qcedev_map_buf_req)
#define COMPAT_QCEDEV_IOCTL_UNMAP_BUF_REQ \
	_IOWR(QCEDEV_IOC_MAGIC, 11, struct compat_qcedev_unmap_buf_req)
#endif /* CONFIG_COMPAT */
#endif /* _UAPI_COMPAT_QCEDEV__H */
+106 −7
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <crypto/hash.h>
#include "qcedevi.h"
#include "qce.h"
#include "qcedev_smmu.h"

#include <linux/compat.h>
#include "compat_qcedev.h"
@@ -64,6 +65,14 @@ static dev_t qcedev_device_no;
static struct class *driver_class;
static struct device *class_dev;

MODULE_DEVICE_TABLE(of, qcedev_match);

static const struct of_device_id qcedev_match[] = {
	{	.compatible = "qcom,qcedev"},
	{	.compatible = "qcom,qcedev,context-bank"},
	{}
};

static int qcedev_control_clocks(struct qcedev_control *podev, bool enable)
{
	unsigned int control_flag;
@@ -259,6 +268,9 @@ static int qcedev_open(struct inode *inode, struct file *file)
	file->private_data = handle;
	if (podev->platform_support.bus_scale_table != NULL)
		qcedev_ce_high_bw_req(podev, true);

	mutex_init(&handle->registeredbufs.lock);
	INIT_LIST_HEAD(&handle->registeredbufs.list);
	return 0;
}

@@ -1856,6 +1868,62 @@ static inline long qcedev_ioctl(struct file *file,
		}
		break;

	case QCEDEV_IOCTL_MAP_BUF_REQ:
		{
			unsigned long long vaddr = 0;
			struct qcedev_map_buf_req map_buf = { {0} };
			int i = 0;

			if (copy_from_user(&map_buf,
					(void __user *)arg, sizeof(map_buf)))
				return -EFAULT;

			for (i = 0; i < map_buf.num_fds; i++) {
				err = qcedev_check_and_map_buffer(handle,
						map_buf.fd[i],
						map_buf.fd_offset[i],
						map_buf.fd_size[i],
						&vaddr);
				if (err) {
					pr_err(
						"%s: err: failed to map fd(%d) - %d\n",
						__func__, map_buf.fd[i], err);
					return err;
				}
				map_buf.buf_vaddr[i] = vaddr;
				pr_info("%s: info: vaddr = %llx\n",
					__func__, vaddr);
			}

			if (copy_to_user((void __user *)arg, &map_buf,
					sizeof(map_buf)))
				return -EFAULT;
			break;
		}

	case QCEDEV_IOCTL_UNMAP_BUF_REQ:
		{
			struct qcedev_unmap_buf_req unmap_buf = { { 0 } };
			int i = 0;

			if (copy_from_user(&unmap_buf,
					(void __user *)arg, sizeof(unmap_buf)))
				return -EFAULT;

			for (i = 0; i < unmap_buf.num_fds; i++) {
				err = qcedev_check_and_unmap_buffer(handle,
						unmap_buf.fd[i]);
				if (err) {
					pr_err(
						"%s: err: failed to unmap fd(%d) - %d\n",
						 __func__,
						unmap_buf.fd[i], err);
					return err;
				}
			}
			break;
		}

	default:
		return -ENOTTY;
	}
@@ -1863,7 +1931,7 @@ static inline long qcedev_ioctl(struct file *file,
	return err;
}

static int qcedev_probe(struct platform_device *pdev)
static int qcedev_probe_device(struct platform_device *pdev)
{
	void *handle = NULL;
	int rc = 0;
@@ -1907,6 +1975,8 @@ static int qcedev_probe(struct platform_device *pdev)
	INIT_LIST_HEAD(&podev->ready_commands);
	podev->active_command = NULL;

	INIT_LIST_HEAD(&podev->context_banks);

	spin_lock_init(&podev->lock);

	tasklet_init(&podev->done_tasklet, req_done, (unsigned long)podev);
@@ -1965,8 +2035,27 @@ static int qcedev_probe(struct platform_device *pdev)
		podev->platform_support.sha_hmac = platform_support->sha_hmac;
	}

	podev->mem_client = qcedev_mem_new_client(MEM_ION);
	if (!podev->mem_client) {
		pr_err("%s: err: qcedev_mem_new_client failed\n", __func__);
		goto exit_qce_close;
	}

	rc = of_platform_populate(pdev->dev.of_node, qcedev_match,
			NULL, &pdev->dev);
	if (rc) {
		pr_err("%s: err: of_platform_populate failed: %d\n",
			__func__, rc);
		goto exit_mem_new_client;
	}

	return 0;

exit_mem_new_client:
	if (podev->mem_client)
		qcedev_mem_delete_client(podev->mem_client);
	podev->mem_client = NULL;

exit_qce_close:
	if (handle)
		qce_close(handle);
@@ -1984,7 +2073,23 @@ static int qcedev_probe(struct platform_device *pdev)
exit_unreg_chrdev_region:
	unregister_chrdev_region(qcedev_device_no, 1);

	podev->bus_scale_handle = 0;
	platform_set_drvdata(pdev, NULL);
	podev->pdev = NULL;
	podev->qce = NULL;

	return rc;
}

static int qcedev_probe(struct platform_device *pdev)
{
	if (of_device_is_compatible(pdev->dev.of_node, "qcom,qcedev"))
		return qcedev_probe_device(pdev);
	else if (of_device_is_compatible(pdev->dev.of_node,
		"qcom,qcedev,context-bank"))
		return qcedev_parse_context_bank(pdev);

	return -EINVAL;
};

static int qcedev_remove(struct platform_device *pdev)
@@ -2055,12 +2160,6 @@ static int qcedev_resume(struct platform_device *pdev)
	return 0;
}

static const struct of_device_id qcedev_match[] = {
	{	.compatible = "qcom,qcedev",
	},
	{}
};

static struct platform_driver qcedev_plat_driver = {
	.probe = qcedev_probe,
	.remove = qcedev_remove,
Loading