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

Commit 6f5b99c0 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: hab: use dma buf as default implement of export/import"

parents 6881b071 253b79d2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ struct hab_driver hab_driver = {
	.devp = hab_devices,
	.uctx_list = LIST_HEAD_INIT(hab_driver.uctx_list),
	.drvlock = __SPIN_LOCK_UNLOCKED(hab_driver.drvlock),
	.imp_list = LIST_HEAD_INIT(hab_driver.imp_list),
	.imp_lock = __SPIN_LOCK_UNLOCKED(hab_driver.imp_lock),
};

struct uhab_context *hab_ctx_alloc(int kernel)
@@ -112,7 +114,8 @@ void hab_ctx_free(struct kref *ref)
	int i;
	struct uhab_context *ctxdel, *ctxtmp;
	struct hab_open_node *node;
	struct export_desc *exp, *exp_tmp;
	struct export_desc *exp = NULL,
			*exp_tmp = NULL;

	/* garbage-collect exp/imp buffers */
	write_lock_bh(&ctx->exp_lock);
+27 −8
Original line number Diff line number Diff line
@@ -305,6 +305,10 @@ struct hab_driver {
	int ctx_cnt;
	spinlock_t drvlock;

	struct list_head imp_list;
	int imp_cnt;
	spinlock_t imp_lock;

	struct local_vmid settings; /* parser results */

	int b_server_dom;
@@ -370,6 +374,13 @@ struct export_desc {
	unsigned char       payload[1];
} __packed;

struct export_desc_super {
	struct kref refcount;
	void *platform_data;
	unsigned long offset;
	struct export_desc  exp;
};

int hab_vchan_open(struct uhab_context *ctx,
		unsigned int mmid, int32_t *vcid,
		int32_t timeout, uint32_t flags);
@@ -396,32 +407,40 @@ int hab_mem_import(struct uhab_context *ctx,
		struct hab_import *param, int kernel);
int hab_mem_unexport(struct uhab_context *ctx,
		struct hab_unexport *param, int kernel);
void habmem_export_get(struct export_desc_super *exp_super);
int habmem_export_put(struct export_desc_super *exp_super);

int hab_mem_unimport(struct uhab_context *ctx,
		struct hab_unimport *param, int kernel);

void habmem_remove_export(struct export_desc *exp);

/* memory hypervisor framework plugin I/F */
void *habmm_hyp_allocate_grantable(int page_count,
		uint32_t *sizebytes);
struct export_desc_super *habmem_add_export(
		struct virtual_channel *vchan,
		int sizebytes,
		uint32_t flags);

int habmem_hyp_grant_user(unsigned long address,
int habmem_hyp_grant_user(struct virtual_channel *vchan,
		unsigned long address,
		int page_count,
		int flags,
		int remotedom,
		void *ppdata,
		int *compressed,
		int *compressed_size);
		int *compressed_size,
		int *export_id);

int habmem_hyp_grant(unsigned long address,
int habmem_hyp_grant(struct virtual_channel *vchan,
		unsigned long address,
		int page_count,
		int flags,
		int remotedom,
		void *ppdata,
		int *compressed,
		int *compressed_size);
		int *compressed_size,
		int *export_id);

int habmem_hyp_revoke(void *expdata, uint32_t count);
int habmem_exp_release(struct export_desc_super *exp_super);

void *habmem_imp_hyp_open(void);
void habmem_imp_hyp_close(void *priv, int kernel);
+384 −380

File changed.

Preview size limit exceeded, changes collapsed.

+79 −84
Original line number Diff line number Diff line
/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2019, 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
@@ -79,20 +79,23 @@ static int hab_export_ack_wait(struct uhab_context *ctx,
 * Once generated it will not be erased
 * assumptions: no handshake or memory map/unmap in this helper function
 */
static struct export_desc *habmem_add_export(struct virtual_channel *vchan,
struct export_desc_super *habmem_add_export(
		struct virtual_channel *vchan,
		int sizebytes,
		uint32_t flags)
{
	struct uhab_context *ctx;
	struct export_desc *exp;
	struct uhab_context *ctx = NULL;
	struct export_desc *exp = NULL;
	struct export_desc_super *exp_super = NULL;

	if (!vchan || !sizebytes)
		return NULL;

	exp = kzalloc(sizebytes, GFP_KERNEL);
	if (!exp)
	exp_super = kzalloc(sizebytes, GFP_KERNEL);
	if (!exp_super)
		return NULL;

	exp = &exp_super->exp;
	idr_preload(GFP_KERNEL);
	spin_lock(&vchan->pchan->expid_lock);
	exp->export_id =
@@ -115,18 +118,21 @@ static struct export_desc *habmem_add_export(struct virtual_channel *vchan,
	list_add_tail(&exp->node, &ctx->exp_whse);
	write_unlock(&ctx->exp_lock);

	return exp;
	return exp_super;
}

void habmem_remove_export(struct export_desc *exp)
{
	struct physical_channel *pchan;
	struct uhab_context *ctx;
	struct uhab_context *ctx = NULL;
	struct export_desc_super *exp_super =
			container_of(exp,
				struct export_desc_super,
				exp);

	if (!exp || !exp->ctx || !exp->pchan) {
	if (!exp || !exp->ctx) {
		if (exp)
			pr_err("invalid info in exp %pK ctx %pK pchan %pK\n",
			   exp, exp->ctx, exp->pchan);
			pr_err("invalid info in exp %pK ctx %pK\n",
			   exp, exp->ctx);
		else
			pr_err("invalid exp\n");
		return;
@@ -134,49 +140,44 @@ void habmem_remove_export(struct export_desc *exp)

	ctx = exp->ctx;
	ctx->export_total--;
	exp->ctx = NULL;

	pchan = exp->pchan;

	spin_lock(&pchan->expid_lock);
	idr_remove(&pchan->expid_idr, exp->export_id);
	spin_unlock(&pchan->expid_lock);

	kfree(exp);
	habmem_export_put(exp_super);
}

static int compress_pfns(void **pfns, int npages, unsigned int *data_size)
static void habmem_export_destroy(struct kref *refcount)
{
	int i, j = 0;
	struct grantable *item = (struct grantable *)*pfns;
	int region_size = 1;
	struct compressed_pfns *new_table =
		vmalloc(sizeof(struct compressed_pfns) +
			npages * sizeof(struct region));

	if (!new_table)
		return -ENOMEM;

	new_table->first_pfn = item[0].pfn;
	for (i = 1; i < npages; i++) {
		if (item[i].pfn-1 == item[i-1].pfn) {
			region_size++; /* continuous pfn */
		} else {
			new_table->region[j].size  = region_size;
			new_table->region[j].space = item[i].pfn -
							item[i-1].pfn - 1;
			j++;
			region_size = 1;
	struct physical_channel *pchan = NULL;
	struct export_desc_super *exp_super =
			container_of(
				refcount,
				struct export_desc_super,
				refcount);
	struct export_desc *exp = NULL;

	if (!exp_super) {
		pr_err("invalid exp_super\n");
		return;
	}

	exp = &exp_super->exp;
	if (!exp || !exp->pchan) {
		if (exp)
			pr_err("invalid info in exp %pK pchan %pK\n",
			   exp, exp->pchan);
		else
			pr_err("invalid exp\n");
		return;
	}
	new_table->region[j].size = region_size;
	new_table->region[j].space = 0;
	new_table->nregions = j+1;
	vfree(*pfns);

	*data_size = sizeof(struct compressed_pfns) +
		sizeof(struct region)*new_table->nregions;
	*pfns = new_table;
	return 0;
	pchan = exp->pchan;

	spin_lock(&pchan->expid_lock);
	idr_remove(&pchan->expid_idr, exp->export_id);
	spin_unlock(&pchan->expid_lock);

	habmem_exp_release(exp_super);
	kfree(exp_super);
}

/*
@@ -186,11 +187,9 @@ static int compress_pfns(void **pfns, int npages, unsigned int *data_size)
 */
static int habmem_export_vchan(struct uhab_context *ctx,
		struct virtual_channel *vchan,
		void *pdata,
		int payload_size,
		int nunits,
		uint32_t flags,
		uint32_t *export_id)
		uint32_t export_id)
{
	int ret;
	struct export_desc *exp;
@@ -198,13 +197,12 @@ static int habmem_export_vchan(struct uhab_context *ctx,
	struct hab_export_ack expected_ack = {0};
	struct hab_header header = HAB_HEADER_INITIALIZER;

	exp = habmem_add_export(vchan, sizebytes, flags);
	if (!exp)
		return -ENOMEM;

	 /* append the pdata to the export descriptor */
	exp->payload_count = nunits;
	memcpy(exp->payload, pdata, payload_size);
	exp = idr_find(&vchan->pchan->expid_idr, export_id);
	if (!exp) {
		pr_err("export vchan failed: exp_id %d, pchan %s\n",
				export_id, vchan->pchan->name);
		return -EINVAL;
	}

	HAB_HEADER_SET_SIZE(header, sizebytes);
	HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_EXPORT);
@@ -227,18 +225,25 @@ static int habmem_export_vchan(struct uhab_context *ctx,
		return ret;
	}

	*export_id = exp->export_id;

	return ret;
}

void habmem_export_get(struct export_desc_super *exp_super)
{
	kref_get(&exp_super->refcount);
}

int habmem_export_put(struct export_desc_super *exp_super)
{
	return kref_put(&exp_super->refcount, habmem_export_destroy);
}

int hab_mem_export(struct uhab_context *ctx,
		struct hab_export *param,
		int kernel)
{
	int ret = 0;
	void *pdata_exp = NULL;
	unsigned int pdata_size = 0;
	unsigned int payload_size = 0;
	uint32_t export_id = 0;
	struct virtual_channel *vchan;
	int page_count;
@@ -254,49 +259,39 @@ int hab_mem_export(struct uhab_context *ctx,
	}

	page_count = param->sizebytes/PAGE_SIZE;
	pdata_exp = habmm_hyp_allocate_grantable(page_count, &pdata_size);
	if (!pdata_exp) {
		ret = -ENOMEM;
		goto err;
	}

	if (kernel) {
		ret = habmem_hyp_grant((unsigned long)param->buffer,
		ret = habmem_hyp_grant(vchan,
			(unsigned long)param->buffer,
			page_count,
			param->flags,
			vchan->pchan->dom_id,
			pdata_exp,
			&compressed,
			&pdata_size);
			&payload_size,
			&export_id);
	} else {
		ret = habmem_hyp_grant_user((unsigned long)param->buffer,
		ret = habmem_hyp_grant_user(vchan,
			(unsigned long)param->buffer,
			page_count,
			param->flags,
			vchan->pchan->dom_id,
			pdata_exp,
			&compressed,
			&pdata_size);
			&payload_size,
			&export_id);
	}
	if (ret < 0) {
		pr_err("habmem_hyp_grant vc %x failed size=%d ret=%d\n",
			   param->vcid, pdata_size, ret);
			   param->vcid, payload_size, ret);
		goto err;
	}

	if (!compressed)
		compress_pfns(&pdata_exp, page_count, &pdata_size);

	ret = habmem_export_vchan(ctx,
		vchan,
		pdata_exp,
		pdata_size,
		page_count,
		payload_size,
		param->flags,
		&export_id);
		export_id);

	param->exportid = export_id;
err:
	vfree(pdata_exp);
	if (vchan)
		hab_vchan_put(vchan);
	return ret;
@@ -307,7 +302,7 @@ int hab_mem_unexport(struct uhab_context *ctx,
		int kernel)
{
	int ret = 0, found = 0;
	struct export_desc *exp, *tmp;
	struct export_desc *exp = NULL, *tmp = NULL;
	struct virtual_channel *vchan;

	if (!ctx || !param)