mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 03:27:03 +02:00
Merge "android: abi_gki_aarch64_qcom: Add flush_delayed_fput"
This commit is contained in:
commit
4166c80b23
|
|
@ -539,6 +539,7 @@
|
|||
flow_rule_match_ports
|
||||
flow_rule_match_vlan
|
||||
flush_dcache_page
|
||||
flush_delayed_fput
|
||||
flush_delayed_work
|
||||
flush_work
|
||||
__flush_workqueue
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ CONFIG_QCOM_MDT_LOADER=m
|
|||
CONFIG_QCOM_MEMORY_DUMP_V2=m
|
||||
CONFIG_QCOM_MEM_BUF=m
|
||||
CONFIG_QCOM_MEM_BUF_DEV=m
|
||||
# CONFIG_QCOM_MEM_BUF_GH is not set
|
||||
CONFIG_QCOM_MEM_BUF_DEV_GH=y
|
||||
CONFIG_QCOM_MEM_BUF_GH=y
|
||||
CONFIG_QCOM_MEM_BUF_MSGQ=m
|
||||
# CONFIG_QCOM_MINIDUMP is not set
|
||||
# CONFIG_QCOM_MSM_IPCC is not set
|
||||
CONFIG_QCOM_PANIC_ON_NOTIF_TIMEOUT=y
|
||||
|
|
|
|||
|
|
@ -27,6 +27,20 @@ config QCOM_MEM_BUF_DEV
|
|||
config QCOM_MEM_BUF_DEV_GH
|
||||
bool
|
||||
|
||||
config QCOM_MEM_BUF_UPDATE_S1
|
||||
tristate "Map imported memory into the S1 logical kernel mapping for cache maintenance"
|
||||
depends on QCOM_MEM_BUF_DEV_GH
|
||||
help
|
||||
When mapping memory into a VM, we must add it to the logical mapping in Linux in
|
||||
order to perform cache maintenance on the memory. The default functions used for
|
||||
adding memory, add_memory(), only maps memory at 128 MB chunks and has a 256 KB
|
||||
overhead in the page table space it consumes (assuming the logical mapping is not
|
||||
using block mappings). We accordingly use a downstream functions instead -
|
||||
add_memory_subsection() - that adds memory on a section-size granularity
|
||||
(currently 4 MB). Select this config option to enable the usage of these functions
|
||||
on VMs, where these functions will be available using our downstream kernels.
|
||||
If unsure, say N.
|
||||
|
||||
config QCOM_MEM_BUF_MSGQ
|
||||
tristate "Qualcomm Technologies, Inc. Memory Buffer Message Queue Support"
|
||||
depends on GH_MSGQ && QCOM_MEM_BUF_DEV_GH
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ EXPORT_TRACEPOINT_SYMBOL(receive_relinquish_msg);
|
|||
EXPORT_TRACEPOINT_SYMBOL(send_alloc_resp_msg);
|
||||
EXPORT_TRACEPOINT_SYMBOL(receive_alloc_resp_msg);
|
||||
EXPORT_TRACEPOINT_SYMBOL(mem_buf_alloc_info);
|
||||
EXPORT_TRACEPOINT_SYMBOL(send_relinquish_resp_msg);
|
||||
EXPORT_TRACEPOINT_SYMBOL(receive_relinquish_resp_msg);
|
||||
|
||||
struct gh_acl_desc *mem_buf_vmid_perm_list_to_gh_acl(int *vmids, int *perms,
|
||||
unsigned int nr_acl_entries)
|
||||
|
|
@ -131,6 +133,24 @@ struct sg_table *dup_gh_sgl_desc_to_sgt(struct gh_sgl_desc *sgl_desc)
|
|||
}
|
||||
EXPORT_SYMBOL(dup_gh_sgl_desc_to_sgt);
|
||||
|
||||
struct gh_sgl_desc *dup_gh_sgl_desc(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
size_t size;
|
||||
struct gh_sgl_desc *copy;
|
||||
|
||||
if (!sgl_desc)
|
||||
return NULL;
|
||||
|
||||
size = offsetof(struct gh_sgl_desc, sgl_entries[sgl_desc->n_sgl_entries]);
|
||||
copy = kvmalloc(size, GFP_KERNEL);
|
||||
if (!copy)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(copy, sgl_desc, size);
|
||||
return copy;
|
||||
}
|
||||
EXPORT_SYMBOL(dup_gh_sgl_desc);
|
||||
|
||||
size_t mem_buf_get_sgl_buf_size(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
|
@ -176,13 +196,17 @@ static int mem_buf_hyp_assign_table_gh(struct gh_sgl_desc *sgl_desc, int src_vmi
|
|||
/*
|
||||
* @memparcel_hdl:
|
||||
* GH_RM_TRANS_TYPE_DONATE - memparcel_hdl will be set to MEM_BUF_MEMPARCEL_INVALID
|
||||
on success, and (possibly) set to a different valid memparcel on error. This is
|
||||
because accepting a donated memparcel handle destroys that handle.
|
||||
GH_RM_TRANS_TYPE_LEND - unmodified.
|
||||
GH_RM_TRANS_TYPE_SHARE - unmodified.
|
||||
* on success, and (possibly) set to a different valid memparcel on error. This is
|
||||
* because accepting a donated memparcel handle destroys that handle.
|
||||
* GH_RM_TRANS_TYPE_LEND - unmodified.
|
||||
* GH_RM_TRANS_TYPE_SHARE - unmodified.
|
||||
* @sgl_desc:
|
||||
* If *sgl_desc is not NULL, request specific IPA address(es). Otherwise, hypervisor
|
||||
* will choose the IPA address, and return it here.
|
||||
*/
|
||||
struct gh_sgl_desc *mem_buf_map_mem_s2(int op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, int src_vmid)
|
||||
int mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, struct gh_sgl_desc **__sgl_desc,
|
||||
int src_vmid)
|
||||
{
|
||||
int ret, ret2;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
|
|
@ -190,24 +214,24 @@ struct gh_sgl_desc *mem_buf_map_mem_s2(int op, gh_memparcel_handle_t *__memparce
|
|||
GH_RM_MEM_ACCEPT_DONE;
|
||||
gh_memparcel_handle_t memparcel_hdl = *__memparcel_hdl;
|
||||
|
||||
if (!acl_desc)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (!acl_desc || !__sgl_desc)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* memory returns to its original IPA address when accepted by HLOS. For example,
|
||||
* scattered memory returns to being scattered memory.
|
||||
*/
|
||||
if (current_vmid != VMID_HLOS)
|
||||
if (current_vmid != VMID_HLOS || (*__sgl_desc && (*__sgl_desc)->n_sgl_entries == 1))
|
||||
flags |= GH_RM_MEM_ACCEPT_MAP_IPA_CONTIGUOUS;
|
||||
|
||||
pr_debug("%s: adding CPU MMU stage 2 mappings\n", __func__);
|
||||
sgl_desc = gh_rm_mem_accept(memparcel_hdl, GH_RM_MEM_TYPE_NORMAL, op,
|
||||
flags, 0, acl_desc, NULL,
|
||||
flags, 0, acl_desc, *__sgl_desc,
|
||||
NULL, 0);
|
||||
if (IS_ERR(sgl_desc)) {
|
||||
pr_err("%s failed to map memory in stage 2 rc: %d\n", __func__,
|
||||
PTR_ERR(sgl_desc));
|
||||
return sgl_desc;
|
||||
return PTR_ERR(sgl_desc);
|
||||
}
|
||||
|
||||
if (op == GH_RM_TRANS_TYPE_DONATE)
|
||||
|
|
@ -218,7 +242,8 @@ struct gh_sgl_desc *mem_buf_map_mem_s2(int op, gh_memparcel_handle_t *__memparce
|
|||
goto err_relinquish;
|
||||
|
||||
trace_map_mem_s2(memparcel_hdl, sgl_desc);
|
||||
return sgl_desc;
|
||||
*__sgl_desc = sgl_desc;
|
||||
return 0;
|
||||
|
||||
err_relinquish:
|
||||
if (op == GH_RM_TRANS_TYPE_DONATE)
|
||||
|
|
@ -226,12 +251,18 @@ struct gh_sgl_desc *mem_buf_map_mem_s2(int op, gh_memparcel_handle_t *__memparce
|
|||
__memparcel_hdl);
|
||||
else
|
||||
ret2 = mem_buf_unmap_mem_s2(memparcel_hdl);
|
||||
kvfree(sgl_desc);
|
||||
|
||||
/*
|
||||
* Only free sgl_desc if caller passed NULL in *__sgl_desc to request
|
||||
* gh_rm_mem_accept to allocate new IPA/sgl_desc.
|
||||
*/
|
||||
if (sgl_desc != *__sgl_desc)
|
||||
kvfree(sgl_desc);
|
||||
if (ret2) {
|
||||
pr_err("%s failed to recover\n", __func__);
|
||||
return ERR_PTR(-EADDRNOTAVAIL);
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
return ERR_PTR(ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_map_mem_s2);
|
||||
|
||||
|
|
@ -252,6 +283,7 @@ int mem_buf_unmap_mem_s2(gh_memparcel_handle_t memparcel_hdl)
|
|||
}
|
||||
EXPORT_SYMBOL(mem_buf_unmap_mem_s2);
|
||||
|
||||
#ifdef CONFIG_QCOM_MEM_BUF_UPDATE_S1
|
||||
int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
u64 base, size;
|
||||
|
|
@ -300,6 +332,7 @@ int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_unmap_mem_s1);
|
||||
#endif /* CONFIG_QCOM_MEM_BUF_UPDATE_S1 */
|
||||
|
||||
static int mem_buf_hyp_assign_table_gh(struct gh_sgl_desc *sgl_desc, int src_vmid,
|
||||
struct gh_acl_desc *acl_desc)
|
||||
|
|
@ -326,7 +359,7 @@ static int mem_buf_hyp_assign_table_gh(struct gh_sgl_desc *sgl_desc, int src_vmi
|
|||
return ret;
|
||||
}
|
||||
|
||||
int mem_buf_assign_mem_gunyah(int op, struct sg_table *sgt,
|
||||
int mem_buf_assign_mem_gunyah(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg)
|
||||
{
|
||||
int ret, i;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ int mem_buf_hyp_assign_table(struct sg_table *sgt, u32 *src_vmid, int source_nel
|
|||
return ret;
|
||||
}
|
||||
|
||||
int mem_buf_assign_mem(int op, struct sg_table *sgt,
|
||||
int mem_buf_assign_mem(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg)
|
||||
{
|
||||
int src_vmid[] = {current_vmid};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ extern unsigned char mem_buf_capability;
|
|||
extern struct device *mem_buf_dev;
|
||||
|
||||
/* Hypervisor Interface */
|
||||
int mem_buf_assign_mem(int op, struct sg_table *sgt,
|
||||
int mem_buf_assign_mem(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg);
|
||||
int mem_buf_unassign_mem(struct sg_table *sgt, int *src_vmids,
|
||||
unsigned int nr_acl_entries,
|
||||
|
|
@ -31,19 +31,35 @@ int mem_buf_hyp_assign_table(struct sg_table *sgt, u32 *src_vmid, int source_nel
|
|||
int *dest_vmids, int *dest_perms, int dest_nelems);
|
||||
|
||||
#ifdef CONFIG_QCOM_MEM_BUF_DEV_GH
|
||||
|
||||
#ifdef CONFIG_QCOM_MEM_BUF_UPDATE_S1
|
||||
int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc);
|
||||
int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc);
|
||||
#else
|
||||
static inline int mem_buf_map_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_QCOM_MEM_BUF_UPDATE_S1 */
|
||||
|
||||
struct gh_acl_desc *mem_buf_vmid_perm_list_to_gh_acl(int *vmids, int *perms,
|
||||
unsigned int nr_acl_entries);
|
||||
struct gh_sgl_desc *mem_buf_sgt_to_gh_sgl_desc(struct sg_table *sgt);
|
||||
struct gh_sgl_desc *mem_buf_map_mem_s2(int op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, int src_vmid);
|
||||
int mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, struct gh_sgl_desc **sgl_desc,
|
||||
int src_vmid);
|
||||
int mem_buf_unmap_mem_s2(gh_memparcel_handle_t memparcel_hdl);
|
||||
int mem_buf_gh_acl_desc_to_vmid_perm_list(struct gh_acl_desc *acl_desc,
|
||||
int **vmids, int **perms);
|
||||
size_t mem_buf_get_sgl_buf_size(struct gh_sgl_desc *sgl_desc);
|
||||
struct sg_table *dup_gh_sgl_desc_to_sgt(struct gh_sgl_desc *sgl_desc);
|
||||
int mem_buf_assign_mem_gunyah(int op, struct sg_table *sgt,
|
||||
struct gh_sgl_desc *dup_gh_sgl_desc(struct gh_sgl_desc *sgl_desc);
|
||||
int mem_buf_assign_mem_gunyah(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg);
|
||||
int mem_buf_unassign_mem_gunyah(gh_memparcel_handle_t memparcel_hdl);
|
||||
#else
|
||||
|
|
@ -68,10 +84,11 @@ static inline struct gh_sgl_desc *mem_buf_sgt_to_gh_sgl_desc(struct sg_table *sg
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline struct gh_sgl_desc *mem_buf_map_mem_s2(int op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, int src_vmid)
|
||||
static inline int mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, struct gh_sgl_desc **__sgl_desc,
|
||||
int src_vmid)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int mem_buf_unmap_mem_s2(gh_memparcel_handle_t memparcel_hdl)
|
||||
|
|
@ -95,7 +112,12 @@ static inline struct sg_table *dup_gh_sgl_desc_to_sgt(struct gh_sgl_desc *sgl_de
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline int mem_buf_assign_mem_gunyah(int op, struct sg_table *sgt,
|
||||
static inline struct gh_sgl_desc *dup_gh_sgl_desc(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline int mem_buf_assign_mem_gunyah(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg)
|
||||
{
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ struct mem_buf_rmt_msg {
|
|||
* @secure_alloc: Denotes if the memory was assigned to the targeted VMs as part
|
||||
* of the allocation step
|
||||
* @hdl: The memparcel handle associated with the memory
|
||||
* @gh_rm_trans_type: The type of memory transfer associated with the memory (donation,
|
||||
* @trans_type: The type of memory transfer associated with the memory (donation,
|
||||
* share, lend).
|
||||
* @entry: List entry for maintaining a list of memory buffers that are lent
|
||||
* out.
|
||||
|
|
@ -64,7 +64,7 @@ struct mem_buf_rmt_msg {
|
|||
* memory
|
||||
* @dst_vmids: The VMIDs that have access to the memory
|
||||
* @dst_perms: The access permissions for the VMIDs that can access the memory
|
||||
* @txn_id: The transaction ID that corresponds to this memory buffer
|
||||
* @obj_id: Uniquely identifies this object.
|
||||
*/
|
||||
struct mem_buf_xfer_mem {
|
||||
size_t size;
|
||||
|
|
@ -72,13 +72,13 @@ struct mem_buf_xfer_mem {
|
|||
void *mem_type_data;
|
||||
struct sg_table *mem_sgt;
|
||||
bool secure_alloc;
|
||||
int gh_rm_trans_type;
|
||||
u32 trans_type;
|
||||
gh_memparcel_handle_t hdl;
|
||||
struct list_head entry;
|
||||
u32 nr_acl_entries;
|
||||
int *dst_vmids;
|
||||
int *dst_perms;
|
||||
u32 txn_id;
|
||||
u32 obj_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -91,7 +91,7 @@ struct mem_buf_xfer_mem {
|
|||
* associated with the memory buffer that was allocated from another VM.
|
||||
* @memparcel_hdl: The handle associated with the memparcel that represents the
|
||||
* memory buffer.
|
||||
* @gh_rm_trans_type: The type of memory transfer associated with the memory (donation,
|
||||
* @trans_type: The type of memory transfer associated with the memory (donation,
|
||||
* share, lend).
|
||||
* @src_mem_type: The type of memory that was allocated on the remote VM
|
||||
* @src_data: Memory type specific data used by the remote VM when performing
|
||||
|
|
@ -102,22 +102,24 @@ struct mem_buf_xfer_mem {
|
|||
* @filp: Pointer to the file structure for the membuf
|
||||
* @entry: List head for maintaing a list of memory buffers that have been
|
||||
* provided by remote VMs.
|
||||
* @txn: The transaction associated with a memory buffer
|
||||
* @obj_id: Uniquely identifies this object.
|
||||
*/
|
||||
struct mem_buf_desc {
|
||||
size_t size;
|
||||
struct gh_acl_desc *acl_desc;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
gh_memparcel_handle_t memparcel_hdl;
|
||||
int gh_rm_trans_type;
|
||||
u32 trans_type;
|
||||
enum mem_buf_mem_type src_mem_type;
|
||||
void *src_data;
|
||||
enum mem_buf_mem_type dst_mem_type;
|
||||
void *dst_data;
|
||||
struct file *filp;
|
||||
struct list_head entry;
|
||||
void *txn;
|
||||
u32 obj_id;
|
||||
};
|
||||
static DEFINE_IDR(mem_buf_obj_idr);
|
||||
static DEFINE_MUTEX(mem_buf_idr_mutex);
|
||||
|
||||
struct mem_buf_xfer_dmaheap_mem {
|
||||
char name[MEM_BUF_MAX_DMAHEAP_NAME_LEN];
|
||||
|
|
@ -125,6 +127,28 @@ struct mem_buf_xfer_dmaheap_mem {
|
|||
struct dma_buf_attachment *attachment;
|
||||
};
|
||||
|
||||
static int mem_buf_alloc_obj_id(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&mem_buf_idr_mutex);
|
||||
ret = idr_alloc_cyclic(&mem_buf_obj_idr, NULL, 0, INT_MAX, GFP_KERNEL);
|
||||
mutex_unlock(&mem_buf_idr_mutex);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: failed to allocate obj id rc: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mem_buf_destroy_obj_id(u32 obj_id)
|
||||
{
|
||||
mutex_lock(&mem_buf_idr_mutex);
|
||||
idr_remove(&mem_buf_obj_idr, obj_id);
|
||||
mutex_unlock(&mem_buf_idr_mutex);
|
||||
}
|
||||
|
||||
/* Functions invoked when treating allocation requests from other VMs. */
|
||||
static int mem_buf_rmt_alloc_dmaheap_mem(struct mem_buf_xfer_mem *xfer_mem)
|
||||
{
|
||||
|
|
@ -272,7 +296,13 @@ struct mem_buf_xfer_mem *mem_buf_prep_xfer_mem(void *req_msg)
|
|||
if (!xfer_mem)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
xfer_mem->txn_id = get_alloc_req_txn_id(req_msg);
|
||||
ret = mem_buf_alloc_obj_id();
|
||||
if (ret < 0) {
|
||||
pr_err("%s failed to allocate obj_id: %d\n", __func__, ret);
|
||||
goto err_idr_alloc;
|
||||
}
|
||||
xfer_mem->obj_id = ret;
|
||||
|
||||
xfer_mem->size = get_alloc_req_size(req_msg);
|
||||
xfer_mem->mem_type = mem_type;
|
||||
xfer_mem->nr_acl_entries = nr_acl_entries;
|
||||
|
|
@ -282,21 +312,27 @@ struct mem_buf_xfer_mem *mem_buf_prep_xfer_mem(void *req_msg)
|
|||
if (ret) {
|
||||
pr_err("%s failed to create VMID and permissions list: %d\n",
|
||||
__func__, ret);
|
||||
kfree(xfer_mem);
|
||||
return ERR_PTR(ret);
|
||||
goto err_alloc_vmid_perm_list;
|
||||
}
|
||||
mem_type_data = mem_buf_alloc_xfer_mem_type_data(mem_type, arb_payload);
|
||||
if (IS_ERR(mem_type_data)) {
|
||||
pr_err("%s: failed to allocate mem type specific data: %d\n",
|
||||
__func__, PTR_ERR(mem_type_data));
|
||||
kfree(xfer_mem->dst_vmids);
|
||||
kfree(xfer_mem->dst_perms);
|
||||
kfree(xfer_mem);
|
||||
return ERR_CAST(mem_type_data);
|
||||
ret = PTR_ERR(mem_type_data);
|
||||
goto err_alloc_xfer_mem_type_data;
|
||||
}
|
||||
xfer_mem->mem_type_data = mem_type_data;
|
||||
INIT_LIST_HEAD(&xfer_mem->entry);
|
||||
return xfer_mem;
|
||||
|
||||
err_alloc_xfer_mem_type_data:
|
||||
kfree(xfer_mem->dst_vmids);
|
||||
kfree(xfer_mem->dst_perms);
|
||||
err_alloc_vmid_perm_list:
|
||||
mem_buf_destroy_obj_id(xfer_mem->obj_id);
|
||||
err_idr_alloc:
|
||||
kfree(xfer_mem);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void mem_buf_free_xfer_mem(struct mem_buf_xfer_mem *xfer_mem)
|
||||
|
|
@ -305,6 +341,7 @@ static void mem_buf_free_xfer_mem(struct mem_buf_xfer_mem *xfer_mem)
|
|||
xfer_mem->mem_type_data);
|
||||
kfree(xfer_mem->dst_vmids);
|
||||
kfree(xfer_mem->dst_perms);
|
||||
mem_buf_destroy_obj_id(xfer_mem->obj_id);
|
||||
kfree(xfer_mem);
|
||||
}
|
||||
|
||||
|
|
@ -339,46 +376,10 @@ static int mem_buf_get_mem_xfer_type_gh(struct gh_acl_desc *acl_desc, int owner_
|
|||
return GH_RM_TRANS_TYPE_LEND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether donate operation is supported. If not, use
|
||||
* lend instead. Share is not supported for remotealloc.
|
||||
*/
|
||||
static int get_alloc_req_xfer_type(struct mem_buf_xfer_mem *xfer_mem)
|
||||
{
|
||||
static bool initialized;
|
||||
static int alloc_req_xfer_type;
|
||||
struct mem_buf_lend_kernel_arg arg;
|
||||
int vmids[] = {VMID_TUIVM};
|
||||
int perms[] = {PERM_READ | PERM_WRITE | PERM_EXEC};
|
||||
int ret;
|
||||
|
||||
if (initialized)
|
||||
return alloc_req_xfer_type;
|
||||
|
||||
arg.nr_acl_entries = ARRAY_SIZE(vmids);
|
||||
arg.vmids = vmids;
|
||||
arg.perms = perms;
|
||||
arg.flags = 0;
|
||||
arg.label = 0;
|
||||
|
||||
ret = mem_buf_assign_mem(GH_RM_TRANS_TYPE_DONATE, xfer_mem->mem_sgt, &arg);
|
||||
if (ret) {
|
||||
initialized = true;
|
||||
alloc_req_xfer_type = GH_RM_TRANS_TYPE_LEND;
|
||||
} else {
|
||||
initialized = true;
|
||||
alloc_req_xfer_type = GH_RM_TRANS_TYPE_DONATE;
|
||||
|
||||
mem_buf_unassign_mem(xfer_mem->mem_sgt, vmids, ARRAY_SIZE(vmids),
|
||||
arg.memparcel_hdl);
|
||||
}
|
||||
pr_info("%s: xfer_type set to %d\n", __func__, alloc_req_xfer_type);
|
||||
return alloc_req_xfer_type;
|
||||
}
|
||||
|
||||
static struct mem_buf_xfer_mem *mem_buf_process_alloc_req(void *req)
|
||||
{
|
||||
int ret, xfer_type;
|
||||
int ret;
|
||||
u32 xfer_type;
|
||||
struct mem_buf_xfer_mem *xfer_mem;
|
||||
struct mem_buf_lend_kernel_arg arg = {0};
|
||||
|
||||
|
|
@ -391,7 +392,7 @@ static struct mem_buf_xfer_mem *mem_buf_process_alloc_req(void *req)
|
|||
goto err_rmt_alloc;
|
||||
|
||||
if (!xfer_mem->secure_alloc) {
|
||||
xfer_type = get_alloc_req_xfer_type(xfer_mem);
|
||||
xfer_type = get_alloc_req_xfer_type(req);
|
||||
|
||||
arg.nr_acl_entries = xfer_mem->nr_acl_entries;
|
||||
arg.vmids = xfer_mem->dst_vmids;
|
||||
|
|
@ -401,7 +402,7 @@ static struct mem_buf_xfer_mem *mem_buf_process_alloc_req(void *req)
|
|||
goto err_assign_mem;
|
||||
|
||||
xfer_mem->hdl = arg.memparcel_hdl;
|
||||
xfer_mem->gh_rm_trans_type = xfer_type;
|
||||
xfer_mem->trans_type = xfer_type;
|
||||
}
|
||||
|
||||
mutex_lock(&mem_buf_xfer_mem_list_lock);
|
||||
|
|
@ -432,7 +433,7 @@ static void mem_buf_cleanup_alloc_req(struct mem_buf_xfer_mem *xfer_mem,
|
|||
if (ret < 0)
|
||||
return;
|
||||
} else {
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
struct gh_sgl_desc *sgl_desc = NULL;
|
||||
struct gh_acl_desc *acl_desc;
|
||||
size_t size;
|
||||
|
||||
|
|
@ -445,9 +446,9 @@ static void mem_buf_cleanup_alloc_req(struct mem_buf_xfer_mem *xfer_mem,
|
|||
acl_desc->acl_entries[0].vmid = VMID_HLOS;
|
||||
acl_desc->acl_entries[0].perms = GH_RM_ACL_X | GH_RM_ACL_W | GH_RM_ACL_R;
|
||||
|
||||
sgl_desc = mem_buf_map_mem_s2(GH_RM_TRANS_TYPE_DONATE, &memparcel_hdl,
|
||||
acl_desc, VMID_TUIVM);
|
||||
if (IS_ERR(sgl_desc)) {
|
||||
ret = mem_buf_map_mem_s2(GH_RM_TRANS_TYPE_DONATE, &memparcel_hdl,
|
||||
acl_desc, &sgl_desc, VMID_TUIVM);
|
||||
if (ret) {
|
||||
kfree(acl_desc);
|
||||
return;
|
||||
}
|
||||
|
|
@ -466,7 +467,7 @@ static void mem_buf_alloc_req_work(struct work_struct *work)
|
|||
void *resp_msg;
|
||||
struct mem_buf_xfer_mem *xfer_mem;
|
||||
gh_memparcel_handle_t hdl = 0;
|
||||
int trans_type = 0;
|
||||
u32 obj_id = 0;
|
||||
int ret;
|
||||
|
||||
trace_receive_alloc_req(req_msg);
|
||||
|
|
@ -479,10 +480,11 @@ static void mem_buf_alloc_req_work(struct work_struct *work)
|
|||
} else {
|
||||
ret = 0;
|
||||
hdl = xfer_mem->hdl;
|
||||
trans_type = xfer_mem->gh_rm_trans_type;
|
||||
obj_id = xfer_mem->obj_id;
|
||||
}
|
||||
|
||||
resp_msg = mem_buf_construct_alloc_resp(req_msg, ret, hdl, trans_type);
|
||||
resp_msg = mem_buf_construct_alloc_resp(req_msg, ret, hdl, obj_id);
|
||||
|
||||
kfree(rmt_msg->msg);
|
||||
kfree(rmt_msg);
|
||||
if (IS_ERR(resp_msg))
|
||||
|
|
@ -517,13 +519,14 @@ static void mem_buf_relinquish_work(struct work_struct *work)
|
|||
struct mem_buf_xfer_mem *xfer_mem_iter, *tmp, *xfer_mem = NULL;
|
||||
struct mem_buf_rmt_msg *rmt_msg = to_rmt_msg(work);
|
||||
struct mem_buf_alloc_relinquish *relinquish_msg = rmt_msg->msg;
|
||||
u32 relinquish_txn_id = get_relinquish_req_txn_id(relinquish_msg);
|
||||
u32 obj_id = get_relinquish_req_obj_id(relinquish_msg);
|
||||
void *resp_msg;
|
||||
|
||||
trace_receive_relinquish_msg(relinquish_msg);
|
||||
mutex_lock(&mem_buf_xfer_mem_list_lock);
|
||||
list_for_each_entry_safe(xfer_mem_iter, tmp, &mem_buf_xfer_mem_list,
|
||||
entry)
|
||||
if (xfer_mem_iter->txn_id == relinquish_txn_id) {
|
||||
if (xfer_mem_iter->obj_id == obj_id) {
|
||||
xfer_mem = xfer_mem_iter;
|
||||
list_del(&xfer_mem->entry);
|
||||
break;
|
||||
|
|
@ -533,8 +536,15 @@ static void mem_buf_relinquish_work(struct work_struct *work)
|
|||
if (xfer_mem)
|
||||
mem_buf_cleanup_alloc_req(xfer_mem, relinquish_msg->hdl);
|
||||
else
|
||||
pr_err("%s: transferred memory with txn_id 0x%x not found\n",
|
||||
__func__, relinquish_txn_id);
|
||||
pr_err("%s: transferred memory with obj_id 0x%x not found\n",
|
||||
__func__, obj_id);
|
||||
|
||||
resp_msg = mem_buf_construct_relinquish_resp(relinquish_msg);
|
||||
if (!IS_ERR(resp_msg)) {
|
||||
trace_send_relinquish_resp_msg(resp_msg);
|
||||
mem_buf_msgq_send(mem_buf_msgq_hdl, resp_msg);
|
||||
kfree(resp_msg);
|
||||
}
|
||||
|
||||
kfree(rmt_msg->msg);
|
||||
kfree(rmt_msg);
|
||||
|
|
@ -548,7 +558,6 @@ static int mem_buf_alloc_resp_hdlr(void *hdlr_data, void *msg_buf, size_t size,
|
|||
|
||||
trace_receive_alloc_resp_msg(alloc_resp);
|
||||
if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER)) {
|
||||
kfree(msg_buf);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
|
@ -557,26 +566,29 @@ static int mem_buf_alloc_resp_hdlr(void *hdlr_data, void *msg_buf, size_t size,
|
|||
pr_err("%s remote allocation failed rc: %d\n", __func__, ret);
|
||||
} else {
|
||||
membuf->memparcel_hdl = get_alloc_resp_hdl(alloc_resp);
|
||||
membuf->gh_rm_trans_type = get_alloc_resp_trans_type(alloc_resp);
|
||||
membuf->obj_id = get_alloc_resp_obj_id(alloc_resp);
|
||||
}
|
||||
|
||||
kfree(msg_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Functions invoked when treating allocation requests to other VMs. */
|
||||
static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *buf, size_t size)
|
||||
static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *_buf, size_t size)
|
||||
{
|
||||
struct mem_buf_rmt_msg *rmt_msg;
|
||||
void *buf;
|
||||
|
||||
if (!(mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) {
|
||||
kfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL);
|
||||
if (!rmt_msg) {
|
||||
kfree(buf);
|
||||
if (!rmt_msg)
|
||||
return;
|
||||
|
||||
buf = kmemdup(_buf, size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
kfree(rmt_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -586,18 +598,22 @@ static void mem_buf_alloc_req_hdlr(void *hdlr_data, void *buf, size_t size)
|
|||
queue_work(mem_buf_wq, &rmt_msg->work);
|
||||
}
|
||||
|
||||
static void mem_buf_relinquish_hdlr(void *hdlr_data, void *buf, size_t size)
|
||||
static void mem_buf_relinquish_hdlr(void *hdlr_data, void *_buf, size_t size)
|
||||
{
|
||||
struct mem_buf_rmt_msg *rmt_msg;
|
||||
void *buf;
|
||||
|
||||
if (!(mem_buf_capability & MEM_BUF_CAP_SUPPLIER)) {
|
||||
kfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
rmt_msg = kmalloc(sizeof(*rmt_msg), GFP_KERNEL);
|
||||
if (!rmt_msg) {
|
||||
kfree(buf);
|
||||
if (!rmt_msg)
|
||||
return;
|
||||
|
||||
buf = kmemdup(_buf, size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
kfree(rmt_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -609,11 +625,17 @@ static void mem_buf_relinquish_hdlr(void *hdlr_data, void *buf, size_t size)
|
|||
|
||||
static int mem_buf_request_mem(struct mem_buf_desc *membuf)
|
||||
{
|
||||
struct mem_buf_txn *txn;
|
||||
void *alloc_req_msg;
|
||||
int ret;
|
||||
|
||||
alloc_req_msg = mem_buf_construct_alloc_req(membuf->txn, membuf->size, membuf->acl_desc,
|
||||
membuf->src_mem_type, membuf->src_data);
|
||||
txn = mem_buf_init_txn(mem_buf_msgq_hdl, membuf);
|
||||
if (IS_ERR(txn))
|
||||
return PTR_ERR(txn);
|
||||
|
||||
alloc_req_msg = mem_buf_construct_alloc_req(txn, membuf->size, membuf->acl_desc,
|
||||
membuf->src_mem_type, membuf->src_data,
|
||||
membuf->trans_type);
|
||||
if (IS_ERR(alloc_req_msg)) {
|
||||
ret = PTR_ERR(alloc_req_msg);
|
||||
goto out;
|
||||
|
|
@ -630,23 +652,28 @@ static int mem_buf_request_mem(struct mem_buf_desc *membuf)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = mem_buf_txn_wait(membuf->txn);
|
||||
ret = mem_buf_txn_wait(txn);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
mem_buf_destroy_txn(mem_buf_msgq_hdl, txn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __mem_buf_relinquish_mem(u32 txn_id, u32 memparcel_hdl)
|
||||
static void __mem_buf_relinquish_mem(u32 obj_id, u32 memparcel_hdl)
|
||||
{
|
||||
void *relinquish_msg;
|
||||
void *relinquish_msg, *txn;
|
||||
int ret;
|
||||
|
||||
relinquish_msg = mem_buf_construct_relinquish_msg(txn_id, memparcel_hdl);
|
||||
if (IS_ERR(relinquish_msg))
|
||||
txn = mem_buf_init_txn(mem_buf_msgq_hdl, NULL);
|
||||
if (IS_ERR(txn))
|
||||
return;
|
||||
|
||||
relinquish_msg = mem_buf_construct_relinquish_msg(txn, obj_id, memparcel_hdl);
|
||||
if (IS_ERR(relinquish_msg))
|
||||
goto err_construct_relinquish_msg;
|
||||
|
||||
trace_send_relinquish_msg(relinquish_msg);
|
||||
ret = mem_buf_msgq_send(mem_buf_msgq_hdl, relinquish_msg);
|
||||
|
||||
|
|
@ -661,6 +688,12 @@ static void __mem_buf_relinquish_mem(u32 txn_id, u32 memparcel_hdl)
|
|||
__func__, ret);
|
||||
else
|
||||
pr_debug("%s: allocation relinquish message sent\n", __func__);
|
||||
|
||||
/* Wait for response */
|
||||
mem_buf_txn_wait(txn);
|
||||
|
||||
err_construct_relinquish_msg:
|
||||
mem_buf_destroy_txn(mem_buf_msgq_hdl, txn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -673,16 +706,15 @@ static void mem_buf_relinquish_mem(struct mem_buf_desc *membuf)
|
|||
int perms[] = {PERM_READ | PERM_WRITE | PERM_EXEC};
|
||||
struct sg_table *sgt;
|
||||
struct mem_buf_lend_kernel_arg arg;
|
||||
u32 txn_id = mem_buf_retrieve_txn_id(membuf->txn);
|
||||
|
||||
if (membuf->memparcel_hdl != MEM_BUF_MEMPARCEL_INVALID) {
|
||||
if (membuf->gh_rm_trans_type != GH_RM_TRANS_TYPE_DONATE) {
|
||||
if (membuf->trans_type != GH_RM_TRANS_TYPE_DONATE) {
|
||||
ret = mem_buf_unmap_mem_s2(membuf->memparcel_hdl);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
return __mem_buf_relinquish_mem(txn_id, membuf->memparcel_hdl);
|
||||
return __mem_buf_relinquish_mem(membuf->obj_id, membuf->memparcel_hdl);
|
||||
}
|
||||
|
||||
sgt = dup_gh_sgl_desc_to_sgt(membuf->sgl_desc);
|
||||
|
|
@ -700,15 +732,15 @@ static void mem_buf_relinquish_mem(struct mem_buf_desc *membuf)
|
|||
goto err_free_sgt;
|
||||
|
||||
membuf->memparcel_hdl = arg.memparcel_hdl;
|
||||
__mem_buf_relinquish_mem(txn_id, membuf->memparcel_hdl);
|
||||
__mem_buf_relinquish_mem(membuf->obj_id, membuf->memparcel_hdl);
|
||||
err_free_sgt:
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
}
|
||||
|
||||
static void mem_buf_relinquish_memparcel_hdl(void *hdlr_data, u32 txn_id, gh_memparcel_handle_t hdl)
|
||||
static void mem_buf_relinquish_memparcel_hdl(void *hdlr_data, u32 obj_id, gh_memparcel_handle_t hdl)
|
||||
{
|
||||
__mem_buf_relinquish_mem(txn_id, hdl);
|
||||
__mem_buf_relinquish_mem(obj_id, hdl);
|
||||
}
|
||||
|
||||
static int get_mem_buf(void *membuf_desc);
|
||||
|
|
@ -894,7 +926,6 @@ static int mem_buf_buffer_release(struct inode *inode, struct file *filp)
|
|||
mem_buf_relinquish_mem(membuf);
|
||||
|
||||
out_free_mem:
|
||||
mem_buf_destroy_txn(mem_buf_msgq_hdl, membuf->txn);
|
||||
mem_buf_free_mem_type_data(membuf->dst_mem_type, membuf->dst_data);
|
||||
mem_buf_free_mem_type_data(membuf->src_mem_type, membuf->src_data);
|
||||
kvfree(membuf->sgl_desc);
|
||||
|
|
@ -917,8 +948,6 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
int ret;
|
||||
struct file *filp;
|
||||
struct mem_buf_desc *membuf;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
int op;
|
||||
int perms = PERM_READ | PERM_WRITE | PERM_EXEC;
|
||||
|
||||
if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER))
|
||||
|
|
@ -936,6 +965,8 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
|
||||
pr_debug("%s: mem buf alloc begin\n", __func__);
|
||||
membuf->size = ALIGN(alloc_data->size, MEM_BUF_MHP_ALIGNMENT);
|
||||
|
||||
/* Create copies of data structures from alloc_data as they may be on-stack */
|
||||
membuf->acl_desc = mem_buf_vmid_perm_list_to_gh_acl(
|
||||
alloc_data->vmids, &perms,
|
||||
alloc_data->nr_acl_entries);
|
||||
|
|
@ -943,6 +974,16 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
ret = PTR_ERR(membuf->acl_desc);
|
||||
goto err_alloc_acl_list;
|
||||
}
|
||||
|
||||
if (alloc_data->sgl_desc) {
|
||||
membuf->sgl_desc = dup_gh_sgl_desc(alloc_data->sgl_desc);
|
||||
if (IS_ERR(membuf->sgl_desc)) {
|
||||
ret = PTR_ERR(membuf->sgl_desc);
|
||||
goto err_alloc_sgl_desc;
|
||||
}
|
||||
}
|
||||
|
||||
membuf->trans_type = alloc_data->trans_type;
|
||||
membuf->src_mem_type = alloc_data->src_mem_type;
|
||||
membuf->dst_mem_type = alloc_data->dst_mem_type;
|
||||
|
||||
|
|
@ -962,23 +1003,16 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
goto err_alloc_dst_data;
|
||||
}
|
||||
|
||||
membuf->txn = mem_buf_init_txn(mem_buf_msgq_hdl, membuf);
|
||||
if (IS_ERR(membuf->txn)) {
|
||||
ret = PTR_ERR(membuf->txn);
|
||||
goto err_init_txn;
|
||||
}
|
||||
|
||||
trace_mem_buf_alloc_info(membuf->size, membuf->src_mem_type,
|
||||
membuf->dst_mem_type, membuf->acl_desc);
|
||||
ret = mem_buf_request_mem(membuf);
|
||||
if (ret)
|
||||
goto err_mem_req;
|
||||
|
||||
op = membuf->gh_rm_trans_type;
|
||||
sgl_desc = mem_buf_map_mem_s2(op, &membuf->memparcel_hdl, membuf->acl_desc, VMID_HLOS);
|
||||
if (IS_ERR(sgl_desc))
|
||||
ret = mem_buf_map_mem_s2(membuf->trans_type, &membuf->memparcel_hdl,
|
||||
membuf->acl_desc, &membuf->sgl_desc, VMID_HLOS);
|
||||
if (ret)
|
||||
goto err_map_mem_s2;
|
||||
membuf->sgl_desc = sgl_desc;
|
||||
|
||||
ret = mem_buf_map_mem_s1(membuf->sgl_desc);
|
||||
if (ret)
|
||||
|
|
@ -1013,14 +1047,14 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
err_map_mem_s1:
|
||||
err_map_mem_s2:
|
||||
mem_buf_relinquish_mem(membuf);
|
||||
kvfree(membuf->sgl_desc);
|
||||
err_mem_req:
|
||||
mem_buf_destroy_txn(mem_buf_msgq_hdl, membuf->txn);
|
||||
err_init_txn:
|
||||
mem_buf_free_mem_type_data(membuf->dst_mem_type, membuf->dst_data);
|
||||
err_alloc_dst_data:
|
||||
mem_buf_free_mem_type_data(membuf->src_mem_type, membuf->src_data);
|
||||
err_alloc_src_data:
|
||||
if (membuf->sgl_desc)
|
||||
kvfree(membuf->sgl_desc);
|
||||
err_alloc_sgl_desc:
|
||||
kfree(membuf->acl_desc);
|
||||
err_alloc_acl_list:
|
||||
kfree(membuf);
|
||||
|
|
@ -1115,7 +1149,8 @@ struct dma_buf *mem_buf_retrieve(struct mem_buf_retrieve_kernel_arg *arg)
|
|||
int ret, op;
|
||||
struct qcom_sg_buffer *buffer;
|
||||
struct gh_acl_desc *acl_desc;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
/* Hypervisor picks the IPA address */
|
||||
struct gh_sgl_desc *sgl_desc = NULL;
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct dma_buf *dmabuf;
|
||||
struct sg_table *sgt;
|
||||
|
|
@ -1138,11 +1173,10 @@ struct dma_buf *mem_buf_retrieve(struct mem_buf_retrieve_kernel_arg *arg)
|
|||
}
|
||||
|
||||
op = mem_buf_get_mem_xfer_type_gh(acl_desc, arg->sender_vmid);
|
||||
sgl_desc = mem_buf_map_mem_s2(op, &arg->memparcel_hdl, acl_desc, arg->sender_vmid);
|
||||
if (IS_ERR(sgl_desc)) {
|
||||
ret = PTR_ERR(sgl_desc);
|
||||
ret = mem_buf_map_mem_s2(op, &arg->memparcel_hdl, acl_desc, &sgl_desc,
|
||||
arg->sender_vmid);
|
||||
if (ret)
|
||||
goto err_map_s2;
|
||||
}
|
||||
|
||||
ret = mem_buf_map_mem_s1(sgl_desc);
|
||||
if (ret < 0)
|
||||
|
|
@ -1210,6 +1244,8 @@ static int mem_buf_prep_alloc_data(struct mem_buf_allocation_data *alloc_data,
|
|||
if (ret)
|
||||
goto err_acl;
|
||||
|
||||
/* alloc_data->trans_type set later according to src&dest_mem_type */
|
||||
alloc_data->sgl_desc = NULL;
|
||||
alloc_data->src_mem_type = allocation_args->src_mem_type;
|
||||
alloc_data->dst_mem_type = allocation_args->dst_mem_type;
|
||||
|
||||
|
|
@ -1272,6 +1308,8 @@ int mem_buf_alloc_fd(struct mem_buf_alloc_ioctl_arg *allocation_args)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Only donate is supported currently */
|
||||
alloc_data.trans_type = GH_RM_TRANS_TYPE_DONATE;
|
||||
membuf = mem_buf_alloc(&alloc_data);
|
||||
if (IS_ERR(membuf)) {
|
||||
ret = PTR_ERR(membuf);
|
||||
|
|
|
|||
|
|
@ -88,10 +88,12 @@ static void mem_buf_populate_alloc_req_arb_payload(void *dst, void *src,
|
|||
* with what permissions.
|
||||
* @src_mem_type: The type of memory that will be used to satisfy the allocation.
|
||||
* @src_data: A pointer to auxiliary data required to satisfy the allocation.
|
||||
* @trans_type: One of GH_RM_TRANS_TYPE_DONATE/LEND/SHARE
|
||||
*/
|
||||
void *mem_buf_construct_alloc_req(void *mem_buf_txn, size_t alloc_size,
|
||||
struct gh_acl_desc *acl_desc,
|
||||
enum mem_buf_mem_type src_mem_type, void *src_data)
|
||||
enum mem_buf_mem_type src_mem_type, void *src_data,
|
||||
u32 trans_type)
|
||||
{
|
||||
size_t tot_size, alloc_req_size, acl_desc_size;
|
||||
void *req_buf, *arb_payload;
|
||||
|
|
@ -116,6 +118,7 @@ void *mem_buf_construct_alloc_req(void *mem_buf_txn, size_t alloc_size,
|
|||
req->hdr.msg_size = tot_size;
|
||||
req->size = alloc_size;
|
||||
req->src_mem_type = src_mem_type;
|
||||
req->trans_type = trans_type;
|
||||
acl_desc_size = offsetof(struct gh_acl_desc,
|
||||
acl_entries[nr_acl_entries]);
|
||||
memcpy(&req->acl_desc, acl_desc, acl_desc_size);
|
||||
|
|
@ -134,11 +137,11 @@ EXPORT_SYMBOL(mem_buf_construct_alloc_req);
|
|||
* @req_msg: The request message that is being replied to.
|
||||
* @alloc_ret: The return code of the allocation.
|
||||
* @memparcel_hdl: The memparcel handle that corresponds to the memory that was allocated.
|
||||
* @gh_rm_trans_type: The type of memory transfer associated with the response (i.e. donation,
|
||||
* sharing, or lending).
|
||||
*/
|
||||
void *mem_buf_construct_alloc_resp(void *req_msg, s32 alloc_ret,
|
||||
gh_memparcel_handle_t memparcel_hdl, int gh_rm_trans_type)
|
||||
gh_memparcel_handle_t memparcel_hdl,
|
||||
u32 obj_id)
|
||||
{
|
||||
struct mem_buf_alloc_req *req = req_msg;
|
||||
struct mem_buf_alloc_resp *resp_msg = kzalloc(sizeof(*resp_msg), GFP_KERNEL);
|
||||
|
|
@ -151,7 +154,7 @@ void *mem_buf_construct_alloc_resp(void *req_msg, s32 alloc_ret,
|
|||
resp_msg->hdr.msg_size = sizeof(*resp_msg);
|
||||
resp_msg->ret = alloc_ret;
|
||||
resp_msg->hdl = memparcel_hdl;
|
||||
resp_msg->gh_rm_trans_type = gh_rm_trans_type;
|
||||
resp_msg->obj_id = obj_id;
|
||||
|
||||
return resp_msg;
|
||||
}
|
||||
|
|
@ -159,12 +162,15 @@ EXPORT_SYMBOL(mem_buf_construct_alloc_resp);
|
|||
|
||||
/*
|
||||
* mem_buf_construct_relinquish_msg: Construct a relinquish message.
|
||||
* @txn_id: The transaction ID that corresponds to the memory that is being relinquished.
|
||||
* @mem_buf_txn: The transaction object.
|
||||
* @obj_id: Uniquely identifies an object.
|
||||
* @memparcel_hdl: The memparcel that corresponds to the memory that is being relinquished.
|
||||
*/
|
||||
void *mem_buf_construct_relinquish_msg(u32 txn_id, gh_memparcel_handle_t memparcel_hdl)
|
||||
void *mem_buf_construct_relinquish_msg(void *mem_buf_txn, u32 obj_id,
|
||||
gh_memparcel_handle_t memparcel_hdl)
|
||||
{
|
||||
struct mem_buf_alloc_relinquish *relinquish_msg;
|
||||
struct mem_buf_txn *txn = mem_buf_txn;
|
||||
|
||||
relinquish_msg = kzalloc(sizeof(*relinquish_msg), GFP_KERNEL);
|
||||
if (!relinquish_msg)
|
||||
|
|
@ -172,13 +178,35 @@ void *mem_buf_construct_relinquish_msg(u32 txn_id, gh_memparcel_handle_t memparc
|
|||
|
||||
relinquish_msg->hdr.msg_type = MEM_BUF_ALLOC_RELINQUISH;
|
||||
relinquish_msg->hdr.msg_size = sizeof(*relinquish_msg);
|
||||
relinquish_msg->hdr.txn_id = txn_id;
|
||||
relinquish_msg->hdr.txn_id = txn->txn_id;
|
||||
relinquish_msg->obj_id = obj_id;
|
||||
relinquish_msg->hdl = memparcel_hdl;
|
||||
|
||||
return relinquish_msg;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_construct_relinquish_msg);
|
||||
|
||||
/*
|
||||
* mem_buf_construct_relinquish_resp: Construct a relinquish resp message.
|
||||
* @msg: The msg to reply to.
|
||||
*/
|
||||
void *mem_buf_construct_relinquish_resp(void *_msg)
|
||||
{
|
||||
struct mem_buf_alloc_relinquish *msg = _msg;
|
||||
struct mem_buf_alloc_relinquish *resp;
|
||||
|
||||
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
||||
if (!resp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
resp->hdr.msg_type = MEM_BUF_ALLOC_RELINQUISH_RESP;
|
||||
resp->hdr.msg_size = sizeof(*resp);
|
||||
resp->hdr.txn_id = msg->hdr.txn_id;
|
||||
|
||||
return resp;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_construct_relinquish_resp);
|
||||
|
||||
int mem_buf_retrieve_txn_id(void *mem_buf_txn)
|
||||
{
|
||||
struct mem_buf_txn *txn = mem_buf_txn;
|
||||
|
|
@ -307,9 +335,9 @@ static void mem_buf_process_alloc_resp(struct mem_buf_msgq_desc *desc, void *buf
|
|||
* it can be reclaimed.
|
||||
*/
|
||||
if (!alloc_resp->ret) {
|
||||
desc->msgq_ops->relinquish_memparcel_hdl(desc->hdlr_data, hdr->txn_id,
|
||||
desc->msgq_ops->relinquish_memparcel_hdl(desc->hdlr_data,
|
||||
alloc_resp->obj_id,
|
||||
alloc_resp->hdl);
|
||||
kfree(buf);
|
||||
}
|
||||
} else {
|
||||
txn->txn_ret = desc->msgq_ops->alloc_resp_hdlr(desc->hdlr_data, buf, size,
|
||||
|
|
@ -319,6 +347,29 @@ static void mem_buf_process_alloc_resp(struct mem_buf_msgq_desc *desc, void *buf
|
|||
mutex_unlock(&desc->idr_mutex);
|
||||
}
|
||||
|
||||
static void mem_buf_process_relinquish_resp(struct mem_buf_msgq_desc *desc,
|
||||
void *buf, size_t size)
|
||||
{
|
||||
struct mem_buf_txn *txn;
|
||||
struct mem_buf_alloc_relinquish *relinquish_resp_msg = buf;
|
||||
|
||||
if (size != sizeof(*relinquish_resp_msg)) {
|
||||
pr_err("%s response received is not of correct size\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
trace_receive_relinquish_resp_msg(relinquish_resp_msg);
|
||||
|
||||
mutex_lock(&desc->idr_mutex);
|
||||
txn = idr_find(&desc->txn_idr, relinquish_resp_msg->hdr.txn_id);
|
||||
if (!txn)
|
||||
pr_err("%s no txn associated with id: %d\n", __func__,
|
||||
relinquish_resp_msg->hdr.txn_id);
|
||||
else
|
||||
complete(&txn->txn_done);
|
||||
mutex_unlock(&desc->idr_mutex);
|
||||
}
|
||||
|
||||
static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_t size)
|
||||
{
|
||||
struct mem_buf_msg_hdr *hdr = buf;
|
||||
|
|
@ -327,7 +378,6 @@ static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_
|
|||
if (size < sizeof(*hdr) || hdr->msg_size != size) {
|
||||
pr_err("%s: message received is not of a proper size: 0x%lx\n",
|
||||
__func__, size);
|
||||
kfree(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -341,10 +391,12 @@ static void mem_buf_process_msg(struct mem_buf_msgq_desc *desc, void *buf, size_
|
|||
case MEM_BUF_ALLOC_RELINQUISH:
|
||||
desc->msgq_ops->relinquish_hdlr(desc->hdlr_data, buf, size);
|
||||
break;
|
||||
case MEM_BUF_ALLOC_RELINQUISH_RESP:
|
||||
mem_buf_process_relinquish_resp(desc, buf, size);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: received message of unknown type: %d\n", __func__,
|
||||
hdr->msg_type);
|
||||
kfree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -366,20 +418,20 @@ static int mem_buf_msgq_recv_fn(void *data)
|
|||
size_t size;
|
||||
int ret;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
|
||||
if (!buf)
|
||||
continue;
|
||||
buf = kzalloc(GH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
ret = gh_msgq_recv(desc->msgq_hdl, buf, GH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0);
|
||||
if (ret < 0) {
|
||||
kfree(buf);
|
||||
pr_err_ratelimited("%s failed to receive message rc: %d\n", __func__, ret);
|
||||
} else {
|
||||
mem_buf_process_msg(desc, buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,13 @@
|
|||
* allocation request issued by the receiving VM
|
||||
* @MEM_BUF_ALLOC_RELINQUISH: The message is a notification from another VM
|
||||
* that the receiving VM can reclaim the memory.
|
||||
* @MEM_BUF_ALLOC_RELINQUISH_RESP: Indicates completion of MEM_BUF_ALLOC_RELINQUISH.
|
||||
*/
|
||||
enum mem_buf_msg_type {
|
||||
MEM_BUF_ALLOC_REQ,
|
||||
MEM_BUF_ALLOC_RESP,
|
||||
MEM_BUF_ALLOC_RELINQUISH,
|
||||
MEM_BUF_ALLOC_RELINQUISH_RESP,
|
||||
MEM_BUF_ALLOC_REQ_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -46,6 +48,7 @@ struct mem_buf_msg_hdr {
|
|||
* @hdr: Message header
|
||||
* @size: The size of the memory allocation to be performed on the remote VM.
|
||||
* @src_mem_type: The type of memory that the remote VM should allocate.
|
||||
* @trans_type: One of GH_RM_TRANS_TYPE_DONATE/SHARE/LEND
|
||||
* @acl_desc: A GH ACL descriptor that describes the VMIDs that will be
|
||||
* accessing the memory, as well as what permissions each VMID will have.
|
||||
*
|
||||
|
|
@ -59,6 +62,7 @@ struct mem_buf_alloc_req {
|
|||
struct mem_buf_msg_hdr hdr;
|
||||
u64 size;
|
||||
u32 src_mem_type;
|
||||
u32 trans_type;
|
||||
struct gh_acl_desc acl_desc;
|
||||
} __packed;
|
||||
|
||||
|
|
@ -70,14 +74,14 @@ struct mem_buf_alloc_req {
|
|||
* @hdl: The memparcel handle associated with the memory allocated to the
|
||||
* receiving VM. This field is only meaningful if the allocation on the remote
|
||||
* VM was carried out successfully, as denoted by @ret.
|
||||
* @gh_rm_trans_type: Denotes the type of memory transfer associated with the response
|
||||
* (i.e. memory donation, sharing, or lending).
|
||||
* @obj_id: Unique identifier for the memory object associated with handle.
|
||||
*/
|
||||
struct mem_buf_alloc_resp {
|
||||
struct mem_buf_msg_hdr hdr;
|
||||
s32 ret;
|
||||
u32 hdl;
|
||||
int gh_rm_trans_type;
|
||||
u32 obj_id;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
|
|
@ -86,10 +90,12 @@ struct mem_buf_alloc_resp {
|
|||
* another VM.
|
||||
* @hdr: Message header
|
||||
* @hdl: The memparcel handle associated with the memory.
|
||||
* @obj_id: Unique identifier for the memory object associated with handle.
|
||||
*/
|
||||
struct mem_buf_alloc_relinquish {
|
||||
struct mem_buf_msg_hdr hdr;
|
||||
u32 hdl;
|
||||
u32 obj_id;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
|
@ -111,7 +117,7 @@ struct mem_buf_msgq_ops {
|
|||
void (*alloc_req_hdlr)(void *hdlr_data, void *msg, size_t size);
|
||||
int (*alloc_resp_hdlr)(void *hdlr_data, void *msg, size_t size, void *resp_buf);
|
||||
void (*relinquish_hdlr)(void *hdlr_data, void *msg, size_t size);
|
||||
void (*relinquish_memparcel_hdl)(void *hdlr_data, u32 txn_id,
|
||||
void (*relinquish_memparcel_hdl)(void *hdlr_data, u32 obj_id,
|
||||
gh_memparcel_handle_t memparcel_hdl);
|
||||
};
|
||||
|
||||
|
|
@ -140,6 +146,11 @@ static inline u64 get_alloc_req_size(struct mem_buf_alloc_req *req)
|
|||
return req->size;
|
||||
}
|
||||
|
||||
static inline u64 get_alloc_req_xfer_type(struct mem_buf_alloc_req *req)
|
||||
{
|
||||
return req->trans_type;
|
||||
}
|
||||
|
||||
static inline void *get_alloc_req_arb_payload(struct mem_buf_alloc_req *req)
|
||||
{
|
||||
void *buf = req;
|
||||
|
|
@ -171,14 +182,14 @@ static inline u32 get_alloc_resp_hdl(struct mem_buf_alloc_resp *resp)
|
|||
return resp->hdl;
|
||||
}
|
||||
|
||||
static inline int get_alloc_resp_trans_type(struct mem_buf_alloc_resp *resp)
|
||||
static inline u32 get_alloc_resp_obj_id(struct mem_buf_alloc_resp *resp)
|
||||
{
|
||||
return resp->gh_rm_trans_type;
|
||||
return resp->obj_id;
|
||||
}
|
||||
|
||||
static inline u32 get_relinquish_req_txn_id(struct mem_buf_alloc_relinquish *relinquish_msg)
|
||||
static inline u32 get_relinquish_req_obj_id(struct mem_buf_alloc_relinquish *relinquish_msg)
|
||||
{
|
||||
return relinquish_msg->hdr.txn_id;
|
||||
return relinquish_msg->obj_id;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_MEM_BUF_MSGQ)
|
||||
|
|
@ -195,10 +206,14 @@ int mem_buf_retrieve_txn_id(void *mem_buf_txn);
|
|||
*/
|
||||
void *mem_buf_construct_alloc_req(void *mem_buf_txn, size_t alloc_size,
|
||||
struct gh_acl_desc *acl_desc,
|
||||
enum mem_buf_mem_type src_mem_type, void *src_data);
|
||||
enum mem_buf_mem_type src_mem_type, void *src_data,
|
||||
u32 trans_type);
|
||||
void *mem_buf_construct_alloc_resp(void *req_msg, s32 alloc_ret,
|
||||
gh_memparcel_handle_t memparcel_hdl, int gh_rm_trans_type);
|
||||
void *mem_buf_construct_relinquish_msg(u32 txn_id, gh_memparcel_handle_t memparcel_hdl);
|
||||
gh_memparcel_handle_t memparcel_hdl,
|
||||
u32 obj_id);
|
||||
void *mem_buf_construct_relinquish_msg(void *mem_buf_txn, u32 obj_id,
|
||||
gh_memparcel_handle_t memparcel_hdl);
|
||||
void *mem_buf_construct_relinquish_resp(void *_msg);
|
||||
#else
|
||||
static inline void *mem_buf_msgq_register(const char *msgq_name,
|
||||
struct mem_buf_msgq_hdlr_info *info)
|
||||
|
|
@ -231,20 +246,27 @@ static inline void mem_buf_destroy_txn(void *mem_buf_msgq_hdl, void *mem_buf_txn
|
|||
|
||||
static inline void *mem_buf_construct_alloc_req(void *mem_buf_txn, size_t alloc_size,
|
||||
struct gh_acl_desc *acl_desc,
|
||||
enum mem_buf_mem_type src_mem_type, void *src_data)
|
||||
enum mem_buf_mem_type src_mem_type, void *src_data,
|
||||
u32 trans_type)
|
||||
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline void *mem_buf_construct_alloc_resp(void *req_msg, s32 alloc_ret,
|
||||
gh_memparcel_handle_t memparcel_hdl, int gh_rm_trans_type)
|
||||
gh_memparcel_handle_t memparcel_hdl,
|
||||
u32 obj_id)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline void *mem_buf_construct_relinquish_msg(u32 txn_id,
|
||||
gh_memparcel_handle_t memparcel_hdl)
|
||||
static inline void *mem_buf_construct_relinquish_msg(void *mem_buf_txn, u32 obj_id,
|
||||
gh_memparcel_handle_t memparcel_hdl)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline void *mem_buf_construct_relinquish_resp(void *_msg)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ bool mem_buf_vmperm_can_vmap(struct mem_buf_vmperm *vmperm)
|
|||
EXPORT_SYMBOL(mem_buf_vmperm_can_vmap);
|
||||
|
||||
static int validate_lend_vmids(struct mem_buf_lend_kernel_arg *arg,
|
||||
int op)
|
||||
u32 op)
|
||||
{
|
||||
int i;
|
||||
bool found = false;
|
||||
|
|
@ -443,7 +443,7 @@ static bool validate_lend_mapcount(struct mem_buf_vmperm *vmperm,
|
|||
|
||||
static int mem_buf_lend_internal(struct dma_buf *dmabuf,
|
||||
struct mem_buf_lend_kernel_arg *arg,
|
||||
int op)
|
||||
u32 op)
|
||||
{
|
||||
struct mem_buf_vmperm *vmperm;
|
||||
struct sg_table *sgt;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ static char __maybe_unused *msg_type_to_str(enum mem_buf_msg_type type)
|
|||
return "MEM_BUF_ALLOC_RESP";
|
||||
else if (type == MEM_BUF_ALLOC_RELINQUISH)
|
||||
return "MEM_BUF_ALLOC_RELINQUISH";
|
||||
else if (type == MEM_BUF_ALLOC_RELINQUISH_RESP)
|
||||
return "MEM_BUF_ALLOC_RELINQUISH_RESP";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -223,6 +225,41 @@ DEFINE_EVENT(alloc_resp_class, receive_alloc_resp_msg,
|
|||
TP_ARGS(resp)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(relinquish_resp_class,
|
||||
|
||||
TP_PROTO(struct mem_buf_alloc_relinquish *resp),
|
||||
|
||||
TP_ARGS(resp),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, txn_id)
|
||||
__string(msg_type, msg_type_to_str(resp->hdr.msg_type))
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->txn_id = resp->hdr.txn_id;
|
||||
__assign_str(msg_type, msg_type_to_str(resp->hdr.msg_type));
|
||||
),
|
||||
|
||||
TP_printk("txn_id: %d msg_type: %s",
|
||||
__entry->txn_id, __get_str(msg_type)
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(relinquish_resp_class, send_relinquish_resp_msg,
|
||||
|
||||
TP_PROTO(struct mem_buf_alloc_relinquish *resp),
|
||||
|
||||
TP_ARGS(resp)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(relinquish_resp_class, receive_relinquish_resp_msg,
|
||||
|
||||
TP_PROTO(struct mem_buf_alloc_relinquish *resp),
|
||||
|
||||
TP_ARGS(resp)
|
||||
);
|
||||
|
||||
TRACE_EVENT(lookup_sgl,
|
||||
|
||||
TP_PROTO(struct gh_sgl_desc *sgl_desc, int ret,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MEM_BUF_H
|
||||
|
|
@ -38,6 +39,8 @@ int mem_buf_dma_buf_set_destructor(struct dma_buf *dmabuf,
|
|||
* @nr_acl_entries: The number of ACL entries in @acl_list
|
||||
* @acl_list: A list of VMID and permission pairs that describe what VMIDs will
|
||||
* have access to the memory, and with what permissions
|
||||
* @trans_type: One of GH_RM_TRANS_TYPE_DONATE/LEND/SHARE
|
||||
* @sgl_desc: Optional. Requests a specific set of IPA addresses.
|
||||
* @src_mem_type: The type of memory that the remote VM should allocate
|
||||
* (e.g. ION memory)
|
||||
* @src_data: A pointer to memory type specific data that the remote VM may need
|
||||
|
|
@ -52,6 +55,8 @@ struct mem_buf_allocation_data {
|
|||
unsigned int nr_acl_entries;
|
||||
int *vmids;
|
||||
int *perms;
|
||||
u32 trans_type;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
enum mem_buf_mem_type src_mem_type;
|
||||
void *src_data;
|
||||
enum mem_buf_mem_type dst_mem_type;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user