mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 18:09:56 +00:00
vcsm: VideoCore shared memory service for BCM2835
Add experimental support for the VideoCore shared memory service. This allows user processes to allocate memory from VideoCore's GPU relocatable heap and mmap the buffers. Additionally, the memory handles can passed to other VideoCore services such as MMAL, OpenMax and DispmanX TODO * This driver was originally released for BCM28155 which has a different cache architecture to BCM2835. Consequently, in this release only uncached mappings are supported. However, there's no fundamental reason which cached mappings cannot be support or BCM2835 * More refactoring is required to remove the typedefs. * Re-enable the some of the commented out debug-fs statistics which were disabled when migrating code from proc-fs. * There's a lot of code to support sharing of VCSM in order to support Android. This could probably done more cleanly or perhaps just removed. Signed-off-by: Tim Gover <timgover@gmail.com> config: Disable VC_SM for now to fix hang with cutdown kernel vcsm: Use boolean as it cannot be built as module On building the bcm_vc_sm as a module we get the following error: v7_dma_flush_range and do_munmap are undefined in vc-sm.ko. Fix by making it not an option to build as module vcsm: Add ioctl for custom cache flushing vc-sm: Move headers out of arch directory Signed-off-by: Noralf Trønnes <noralf@tronnes.org> vcsm: Treat EBUSY as success rather than SIGBUS Currently if two cores access the same page concurrently one will return VM_FAULT_NOPAGE and the other VM_FAULT_SIGBUS crashing the user code. Also report when mapping fails. Signed-off-by: popcornmix <popcornmix@gmail.com> vcsm: Provide new ioctl to clean/invalidate a 2D block vcsm: Convert to loading via device tree. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org> VCSM: New option to import a DMABUF for VPU use Takes a dmabuf, and then calls over to the VPU to wrap it into a suitable handle. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org> vcsm: fix multi-platform build vcsm: add macros for cache functions vcsm: use dma APIs for cache functions * Will handle multi-platform builds vcsm: Fix up macros to avoid breaking numbers used by existing apps vcsm: Define cache operation constants in user header Without this change, users have to use raw values (1, 2, 3) to specify cache operation. Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Support for finding user/vc handle in memory pool vmcs_sm_{usr,vc}_handle_from_pid_and_address() were failing to find handle if specified user pointer is not exactly the one that the memory locking call returned even if the pointer is in range of map/resource. So fixed the functions to match the range. Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Unify cache manipulating functions Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Fix obscure conditions Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Fix memory leaking on clean_invalid2 ioctl handler Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Describe the use of cache operation constants Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Fix obscure conditions again Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Add no-op cache operation constant Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Revert to do page-table-walk-based cache manipulating on some ioctl calls On FLUSH, INVALID, CLEAN_INVALID ioctl calls, cache operations based on page table walk were used in case that the buffer of the cache is not pinned. So reverted to do page-table-based cache manipulating. Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Define cache operation constants in user header Without this change, users have to use raw values (1, 2, 3) to specify cache operation. Signed-off-by: Sugizaki Yukimasa <i.can.speak.c.and.basic@gmail.com> vcsm: Updates for changed vchiq interface vcsm: Fix an NULL dereference in the import_dmabuf error path resource was dereferenced even though it was NULL. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org> vcsm: Use struct service_creation vcsm: Fix makefile include on out-of-tree builds The vc_sm module tries to include the 'fs' directory from the $(srctree). $(srctree) is already provided by the build system, and causes the include path to be duplicated. With -Werror this fails to compile. Remove the unnecessary variable. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> vcsm: Remove set but unused variable The 'success' variable is set by the call to vchi_service_close() but never checked. Remove it, keeping the call in place. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> vcsm: Reduce scope of local functions The functions: vc_vchi_sm_send_msg vc_sm_ioctl_alloc vc_sm_ioctl_alloc_share vc_sm_ioctl_import_dmabuf Are declared without a prototype. They are not used outside of this module, thus - convert them to static functions. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> vc_sm: Let it support to build in the non-src folder If we build the kernel with "-O=$non-src-folder", this driver will introdcue a building error because of the header's location. Signed-off-by: Hui Wang <hui.wang@canonical.com>
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
|
||||
menu "Character devices"
|
||||
|
||||
source "drivers/char/broadcom/Kconfig"
|
||||
|
||||
source "drivers/tty/Kconfig"
|
||||
|
||||
config DEVMEM
|
||||
|
||||
@@ -52,3 +52,4 @@ js-rtc-y = rtc.o
|
||||
obj-$(CONFIG_XILLYBUS) += xillybus/
|
||||
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
|
||||
obj-$(CONFIG_ADI) += adi.o
|
||||
obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/
|
||||
|
||||
@@ -16,3 +16,13 @@ config BCM2708_VCMEM
|
||||
Helper for videocore memory access and total size allocation.
|
||||
|
||||
endif
|
||||
|
||||
config BCM_VC_SM
|
||||
bool "VMCS Shared Memory"
|
||||
depends on BCM2835_VCHIQ
|
||||
select BCM2708_VCMEM
|
||||
select DMA_SHARED_BUFFER
|
||||
default n
|
||||
help
|
||||
Support for the VC shared memory on the Broadcom reference
|
||||
design. Uses the VCHIQ stack.
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
|
||||
obj-$(CONFIG_BCM_VC_SM) += vc_sm/
|
||||
|
||||
9
drivers/char/broadcom/vc_sm/Makefile
Normal file
9
drivers/char/broadcom/vc_sm/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
ccflags-$(CONFIG_BCM_VC_SM) += -Werror -Wall -Wstrict-prototypes -Wno-trigraphs -O2
|
||||
ccflags-$(CONFIG_BCM_VC_SM) += -I$(srctree)/"drivers/staging/vc04_services" -I$(srctree)/"drivers/staging/vc04_services/interface/vchi" -I$(srctree)/"drivers/staging/vc04_services/interface/vchiq_arm" -I$(srctree)/"fs"
|
||||
ccflags-$(CONFIG_BCM_VC_SM) += -DOS_ASSERT_FAILURE -D__STDC_VERSION=199901L -D__STDC_VERSION__=199901L -D__VCCOREVER__=0 -D__KERNEL__ -D__linux__
|
||||
|
||||
obj-$(CONFIG_BCM_VC_SM) := vc-sm.o
|
||||
|
||||
vc-sm-objs := \
|
||||
vmcs_sm.o \
|
||||
vc_vchi_sm.o
|
||||
237
drivers/char/broadcom/vc_sm/vc_sm_defs.h
Normal file
237
drivers/char/broadcom/vc_sm/vc_sm_defs.h
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
****************************************************************************
|
||||
* Copyright 2011 Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available at
|
||||
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* consent.
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __VC_SM_DEFS_H__INCLUDED__
|
||||
#define __VC_SM_DEFS_H__INCLUDED__
|
||||
|
||||
/* FourCC code used for VCHI connection */
|
||||
#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM")
|
||||
|
||||
/* Maximum message length */
|
||||
#define VC_SM_MAX_MSG_LEN (sizeof(union vc_sm_msg_union_t) + \
|
||||
sizeof(struct vc_sm_msg_hdr_t))
|
||||
#define VC_SM_MAX_RSP_LEN (sizeof(union vc_sm_msg_union_t))
|
||||
|
||||
/* Resource name maximum size */
|
||||
#define VC_SM_RESOURCE_NAME 32
|
||||
|
||||
enum vc_sm_msg_type {
|
||||
/* Message types supported for HOST->VC direction */
|
||||
|
||||
/* Allocate shared memory block */
|
||||
VC_SM_MSG_TYPE_ALLOC,
|
||||
/* Lock allocated shared memory block */
|
||||
VC_SM_MSG_TYPE_LOCK,
|
||||
/* Unlock allocated shared memory block */
|
||||
VC_SM_MSG_TYPE_UNLOCK,
|
||||
/* Unlock allocated shared memory block, do not answer command */
|
||||
VC_SM_MSG_TYPE_UNLOCK_NOANS,
|
||||
/* Free shared memory block */
|
||||
VC_SM_MSG_TYPE_FREE,
|
||||
/* Resize a shared memory block */
|
||||
VC_SM_MSG_TYPE_RESIZE,
|
||||
/* Walk the allocated shared memory block(s) */
|
||||
VC_SM_MSG_TYPE_WALK_ALLOC,
|
||||
|
||||
/* A previously applied action will need to be reverted */
|
||||
VC_SM_MSG_TYPE_ACTION_CLEAN,
|
||||
|
||||
/*
|
||||
* Import a physical address and wrap into a MEM_HANDLE_T.
|
||||
* Release with VC_SM_MSG_TYPE_FREE.
|
||||
*/
|
||||
VC_SM_MSG_TYPE_IMPORT,
|
||||
|
||||
/* Message types supported for VC->HOST direction */
|
||||
|
||||
/*
|
||||
* VC has finished with an imported memory allocation.
|
||||
* Release any Linux reference counts on the underlying block.
|
||||
*/
|
||||
VC_SM_MSG_TYPE_RELEASED,
|
||||
|
||||
VC_SM_MSG_TYPE_MAX
|
||||
};
|
||||
|
||||
/* Type of memory to be allocated */
|
||||
enum vc_sm_alloc_type_t {
|
||||
VC_SM_ALLOC_CACHED,
|
||||
VC_SM_ALLOC_NON_CACHED,
|
||||
};
|
||||
|
||||
/* Message header for all messages in HOST->VC direction */
|
||||
struct vc_sm_msg_hdr_t {
|
||||
int32_t type;
|
||||
uint32_t trans_id;
|
||||
uint8_t body[0];
|
||||
|
||||
};
|
||||
|
||||
/* Request to allocate memory (HOST->VC) */
|
||||
struct vc_sm_alloc_t {
|
||||
/* type of memory to allocate */
|
||||
enum vc_sm_alloc_type_t type;
|
||||
/* byte amount of data to allocate per unit */
|
||||
uint32_t base_unit;
|
||||
/* number of unit to allocate */
|
||||
uint32_t num_unit;
|
||||
/* alignement to be applied on allocation */
|
||||
uint32_t alignement;
|
||||
/* identity of who allocated this block */
|
||||
uint32_t allocator;
|
||||
/* resource name (for easier tracking on vc side) */
|
||||
char name[VC_SM_RESOURCE_NAME];
|
||||
|
||||
};
|
||||
|
||||
/* Result of a requested memory allocation (VC->HOST) */
|
||||
struct vc_sm_alloc_result_t {
|
||||
/* Transaction identifier */
|
||||
uint32_t trans_id;
|
||||
|
||||
/* Resource handle */
|
||||
uint32_t res_handle;
|
||||
/* Pointer to resource buffer */
|
||||
uint32_t res_mem;
|
||||
/* Resource base size (bytes) */
|
||||
uint32_t res_base_size;
|
||||
/* Resource number */
|
||||
uint32_t res_num;
|
||||
|
||||
};
|
||||
|
||||
/* Request to free a previously allocated memory (HOST->VC) */
|
||||
struct vc_sm_free_t {
|
||||
/* Resource handle (returned from alloc) */
|
||||
uint32_t res_handle;
|
||||
/* Resource buffer (returned from alloc) */
|
||||
uint32_t res_mem;
|
||||
|
||||
};
|
||||
|
||||
/* Request to lock a previously allocated memory (HOST->VC) */
|
||||
struct vc_sm_lock_unlock_t {
|
||||
/* Resource handle (returned from alloc) */
|
||||
uint32_t res_handle;
|
||||
/* Resource buffer (returned from alloc) */
|
||||
uint32_t res_mem;
|
||||
|
||||
};
|
||||
|
||||
/* Request to resize a previously allocated memory (HOST->VC) */
|
||||
struct vc_sm_resize_t {
|
||||
/* Resource handle (returned from alloc) */
|
||||
uint32_t res_handle;
|
||||
/* Resource buffer (returned from alloc) */
|
||||
uint32_t res_mem;
|
||||
/* Resource *new* size requested (bytes) */
|
||||
uint32_t res_new_size;
|
||||
|
||||
};
|
||||
|
||||
/* Result of a requested memory lock (VC->HOST) */
|
||||
struct vc_sm_lock_result_t {
|
||||
/* Transaction identifier */
|
||||
uint32_t trans_id;
|
||||
|
||||
/* Resource handle */
|
||||
uint32_t res_handle;
|
||||
/* Pointer to resource buffer */
|
||||
uint32_t res_mem;
|
||||
/*
|
||||
* Pointer to former resource buffer if the memory
|
||||
* was reallocated
|
||||
*/
|
||||
uint32_t res_old_mem;
|
||||
|
||||
};
|
||||
|
||||
/* Generic result for a request (VC->HOST) */
|
||||
struct vc_sm_result_t {
|
||||
/* Transaction identifier */
|
||||
uint32_t trans_id;
|
||||
|
||||
int32_t success;
|
||||
|
||||
};
|
||||
|
||||
/* Request to revert a previously applied action (HOST->VC) */
|
||||
struct vc_sm_action_clean_t {
|
||||
/* Action of interest */
|
||||
enum vc_sm_msg_type res_action;
|
||||
/* Transaction identifier for the action of interest */
|
||||
uint32_t action_trans_id;
|
||||
|
||||
};
|
||||
|
||||
/* Request to remove all data associated with a given allocator (HOST->VC) */
|
||||
struct vc_sm_free_all_t {
|
||||
/* Allocator identifier */
|
||||
uint32_t allocator;
|
||||
};
|
||||
|
||||
/* Request to import memory (HOST->VC) */
|
||||
struct vc_sm_import {
|
||||
/* type of memory to allocate */
|
||||
enum vc_sm_alloc_type_t type;
|
||||
/* pointer to the VC (ie physical) address of the allocated memory */
|
||||
uint32_t addr;
|
||||
/* size of buffer */
|
||||
uint32_t size;
|
||||
/* opaque handle returned in RELEASED messages */
|
||||
int32_t kernel_id;
|
||||
/* Allocator identifier */
|
||||
uint32_t allocator;
|
||||
/* resource name (for easier tracking on vc side) */
|
||||
char name[VC_SM_RESOURCE_NAME];
|
||||
};
|
||||
|
||||
/* Result of a requested memory import (VC->HOST) */
|
||||
struct vc_sm_import_result {
|
||||
/* Transaction identifier */
|
||||
uint32_t trans_id;
|
||||
|
||||
/* Resource handle */
|
||||
uint32_t res_handle;
|
||||
};
|
||||
|
||||
/* Notification that VC has finished with an allocation (VC->HOST) */
|
||||
struct vc_sm_released {
|
||||
/* pointer to the VC (ie physical) address of the allocated memory */
|
||||
uint32_t addr;
|
||||
/* size of buffer */
|
||||
uint32_t size;
|
||||
/* opaque handle returned in RELEASED messages */
|
||||
int32_t kernel_id;
|
||||
};
|
||||
|
||||
/* Union of ALL messages */
|
||||
union vc_sm_msg_union_t {
|
||||
struct vc_sm_alloc_t alloc;
|
||||
struct vc_sm_alloc_result_t alloc_result;
|
||||
struct vc_sm_free_t free;
|
||||
struct vc_sm_lock_unlock_t lock_unlock;
|
||||
struct vc_sm_action_clean_t action_clean;
|
||||
struct vc_sm_resize_t resize;
|
||||
struct vc_sm_lock_result_t lock_result;
|
||||
struct vc_sm_result_t result;
|
||||
struct vc_sm_free_all_t free_all;
|
||||
struct vc_sm_import import;
|
||||
struct vc_sm_import_result import_result;
|
||||
struct vc_sm_released released;
|
||||
};
|
||||
|
||||
#endif /* __VC_SM_DEFS_H__INCLUDED__ */
|
||||
53
drivers/char/broadcom/vc_sm/vc_sm_knl.h
Normal file
53
drivers/char/broadcom/vc_sm/vc_sm_knl.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
****************************************************************************
|
||||
* Copyright 2011 Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available at
|
||||
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* consent.
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __VC_SM_KNL_H__INCLUDED__
|
||||
#define __VC_SM_KNL_H__INCLUDED__
|
||||
|
||||
#if !defined(__KERNEL__)
|
||||
#error "This interface is for kernel use only..."
|
||||
#endif
|
||||
|
||||
/* Type of memory to be locked (ie mapped) */
|
||||
enum vc_sm_lock_cache_mode {
|
||||
VC_SM_LOCK_CACHED,
|
||||
VC_SM_LOCK_NON_CACHED,
|
||||
};
|
||||
|
||||
/* Allocate a shared memory handle and block. */
|
||||
int vc_sm_alloc(struct vc_sm_alloc_t *alloc, int *handle);
|
||||
|
||||
/* Free a previously allocated shared memory handle and block. */
|
||||
int vc_sm_free(int handle);
|
||||
|
||||
/* Lock a memory handle for use by kernel. */
|
||||
int vc_sm_lock(int handle, enum vc_sm_lock_cache_mode mode,
|
||||
unsigned long *data);
|
||||
|
||||
/* Unlock a memory handle in use by kernel. */
|
||||
int vc_sm_unlock(int handle, int flush, int no_vc_unlock);
|
||||
|
||||
/* Get an internal resource handle mapped from the external one. */
|
||||
int vc_sm_int_handle(int handle);
|
||||
|
||||
/* Map a shared memory region for use by kernel. */
|
||||
int vc_sm_map(int handle, unsigned int sm_addr,
|
||||
enum vc_sm_lock_cache_mode mode, unsigned long *data);
|
||||
|
||||
/* Import a block of memory into the GPU space. */
|
||||
int vc_sm_import_dmabuf(struct dma_buf *dmabuf, int *handle);
|
||||
|
||||
#endif /* __VC_SM_KNL_H__INCLUDED__ */
|
||||
500
drivers/char/broadcom/vc_sm/vc_vchi_sm.c
Normal file
500
drivers/char/broadcom/vc_sm/vc_vchi_sm.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/*
|
||||
****************************************************************************
|
||||
* Copyright 2011-2012 Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available at
|
||||
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* consent.
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/* ---- Include Files ----------------------------------------------------- */
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include "vc_vchi_sm.h"
|
||||
|
||||
#define VC_SM_VER 1
|
||||
#define VC_SM_MIN_VER 0
|
||||
|
||||
/* ---- Private Constants and Types -------------------------------------- */
|
||||
|
||||
/* Command blocks come from a pool */
|
||||
#define SM_MAX_NUM_CMD_RSP_BLKS 32
|
||||
|
||||
struct sm_cmd_rsp_blk {
|
||||
struct list_head head; /* To create lists */
|
||||
struct semaphore sema; /* To be signaled when the response is there */
|
||||
|
||||
uint16_t id;
|
||||
uint16_t length;
|
||||
|
||||
uint8_t msg[VC_SM_MAX_MSG_LEN];
|
||||
|
||||
uint32_t wait:1;
|
||||
uint32_t sent:1;
|
||||
uint32_t alloc:1;
|
||||
|
||||
};
|
||||
|
||||
struct sm_instance {
|
||||
uint32_t num_connections;
|
||||
struct vchi_service_handle * vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
|
||||
struct task_struct *io_thread;
|
||||
struct semaphore io_sema;
|
||||
|
||||
uint32_t trans_id;
|
||||
|
||||
struct mutex lock;
|
||||
struct list_head cmd_list;
|
||||
struct list_head rsp_list;
|
||||
struct list_head dead_list;
|
||||
|
||||
struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS];
|
||||
struct list_head free_list;
|
||||
struct mutex free_lock;
|
||||
struct semaphore free_sema;
|
||||
|
||||
};
|
||||
|
||||
/* ---- Private Variables ------------------------------------------------ */
|
||||
|
||||
/* ---- Private Function Prototypes -------------------------------------- */
|
||||
|
||||
/* ---- Private Functions ------------------------------------------------ */
|
||||
static int
|
||||
bcm2835_vchi_msg_queue(struct vchi_service_handle * handle,
|
||||
void *data,
|
||||
unsigned int size)
|
||||
{
|
||||
return vchi_queue_kernel_message(handle,
|
||||
data,
|
||||
size);
|
||||
}
|
||||
|
||||
static struct
|
||||
sm_cmd_rsp_blk *vc_vchi_cmd_create(struct sm_instance *instance,
|
||||
enum vc_sm_msg_type id, void *msg,
|
||||
uint32_t size, int wait)
|
||||
{
|
||||
struct sm_cmd_rsp_blk *blk;
|
||||
struct vc_sm_msg_hdr_t *hdr;
|
||||
|
||||
if (down_interruptible(&instance->free_sema)) {
|
||||
blk = kmalloc(sizeof(*blk), GFP_KERNEL);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
|
||||
blk->alloc = 1;
|
||||
sema_init(&blk->sema, 0);
|
||||
} else {
|
||||
mutex_lock(&instance->free_lock);
|
||||
blk =
|
||||
list_first_entry(&instance->free_list,
|
||||
struct sm_cmd_rsp_blk, head);
|
||||
list_del(&blk->head);
|
||||
mutex_unlock(&instance->free_lock);
|
||||
}
|
||||
|
||||
blk->sent = 0;
|
||||
blk->wait = wait;
|
||||
blk->length = sizeof(*hdr) + size;
|
||||
|
||||
hdr = (struct vc_sm_msg_hdr_t *) blk->msg;
|
||||
hdr->type = id;
|
||||
mutex_lock(&instance->lock);
|
||||
hdr->trans_id = blk->id = ++instance->trans_id;
|
||||
mutex_unlock(&instance->lock);
|
||||
|
||||
if (size)
|
||||
memcpy(hdr->body, msg, size);
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
static void
|
||||
vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk)
|
||||
{
|
||||
if (blk->alloc) {
|
||||
kfree(blk);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&instance->free_lock);
|
||||
list_add(&blk->head, &instance->free_list);
|
||||
mutex_unlock(&instance->free_lock);
|
||||
up(&instance->free_sema);
|
||||
}
|
||||
|
||||
static int vc_vchi_sm_videocore_io(void *arg)
|
||||
{
|
||||
struct sm_instance *instance = arg;
|
||||
struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp;
|
||||
struct vc_sm_result_t *reply;
|
||||
uint32_t reply_len;
|
||||
int32_t status;
|
||||
int svc_use = 1;
|
||||
|
||||
while (1) {
|
||||
if (svc_use)
|
||||
vchi_service_release(instance->vchi_handle[0]);
|
||||
svc_use = 0;
|
||||
if (!down_interruptible(&instance->io_sema)) {
|
||||
vchi_service_use(instance->vchi_handle[0]);
|
||||
svc_use = 1;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Get new command and move it to response list
|
||||
*/
|
||||
mutex_lock(&instance->lock);
|
||||
if (list_empty(&instance->cmd_list)) {
|
||||
/* no more commands to process */
|
||||
mutex_unlock(&instance->lock);
|
||||
break;
|
||||
}
|
||||
cmd =
|
||||
list_first_entry(&instance->cmd_list,
|
||||
struct sm_cmd_rsp_blk,
|
||||
head);
|
||||
list_move(&cmd->head, &instance->rsp_list);
|
||||
cmd->sent = 1;
|
||||
mutex_unlock(&instance->lock);
|
||||
|
||||
/* Send the command */
|
||||
status = bcm2835_vchi_msg_queue(
|
||||
instance->vchi_handle[0],
|
||||
cmd->msg, cmd->length);
|
||||
if (status) {
|
||||
pr_err("%s: failed to queue message (%d)",
|
||||
__func__, status);
|
||||
}
|
||||
|
||||
/* If no reply is needed then we're done */
|
||||
if (!cmd->wait) {
|
||||
mutex_lock(&instance->lock);
|
||||
list_del(&cmd->head);
|
||||
mutex_unlock(&instance->lock);
|
||||
vc_vchi_cmd_delete(instance, cmd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
up(&cmd->sema);
|
||||
continue;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
while (!vchi_msg_peek
|
||||
(instance->vchi_handle[0], (void **)&reply,
|
||||
&reply_len, VCHI_FLAGS_NONE)) {
|
||||
mutex_lock(&instance->lock);
|
||||
list_for_each_entry(cmd, &instance->rsp_list,
|
||||
head) {
|
||||
if (cmd->id == reply->trans_id)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&instance->lock);
|
||||
|
||||
if (&cmd->head == &instance->rsp_list) {
|
||||
pr_debug("%s: received response %u, throw away...",
|
||||
__func__, reply->trans_id);
|
||||
} else if (reply_len > sizeof(cmd->msg)) {
|
||||
pr_err("%s: reply too big (%u) %u, throw away...",
|
||||
__func__, reply_len,
|
||||
reply->trans_id);
|
||||
} else {
|
||||
memcpy(cmd->msg, reply, reply_len);
|
||||
up(&cmd->sema);
|
||||
}
|
||||
|
||||
vchi_msg_remove(instance->vchi_handle[0]);
|
||||
}
|
||||
|
||||
/* Go through the dead list and free them */
|
||||
mutex_lock(&instance->lock);
|
||||
list_for_each_entry_safe(cmd, cmd_tmp,
|
||||
&instance->dead_list, head) {
|
||||
list_del(&cmd->head);
|
||||
vc_vchi_cmd_delete(instance, cmd);
|
||||
}
|
||||
mutex_unlock(&instance->lock);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vc_sm_vchi_callback(void *param,
|
||||
const enum vchi_callback_reason reason,
|
||||
void *msg_handle)
|
||||
{
|
||||
struct sm_instance *instance = param;
|
||||
|
||||
(void)msg_handle;
|
||||
|
||||
switch (reason) {
|
||||
case VCHI_CALLBACK_MSG_AVAILABLE:
|
||||
up(&instance->io_sema);
|
||||
break;
|
||||
|
||||
case VCHI_CALLBACK_SERVICE_CLOSED:
|
||||
pr_info("%s: service CLOSED!!", __func__);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct sm_instance *vc_vchi_sm_init(struct vchi_instance_handle * vchi_instance)
|
||||
{
|
||||
uint32_t i;
|
||||
struct sm_instance *instance;
|
||||
int status;
|
||||
int num_connections = 1;
|
||||
|
||||
pr_debug("%s: start", __func__);
|
||||
|
||||
/* Allocate memory for this instance */
|
||||
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
|
||||
|
||||
/* Misc initialisations */
|
||||
mutex_init(&instance->lock);
|
||||
sema_init(&instance->io_sema, 0);
|
||||
INIT_LIST_HEAD(&instance->cmd_list);
|
||||
INIT_LIST_HEAD(&instance->rsp_list);
|
||||
INIT_LIST_HEAD(&instance->dead_list);
|
||||
INIT_LIST_HEAD(&instance->free_list);
|
||||
sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS);
|
||||
mutex_init(&instance->free_lock);
|
||||
for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) {
|
||||
sema_init(&instance->free_blk[i].sema, 0);
|
||||
list_add(&instance->free_blk[i].head, &instance->free_list);
|
||||
}
|
||||
|
||||
/* Open the VCHI service connections */
|
||||
instance->num_connections = num_connections;
|
||||
for (i = 0; i < num_connections; i++) {
|
||||
struct service_creation params = {
|
||||
.version = VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER),
|
||||
.service_id = VC_SM_SERVER_NAME,
|
||||
.callback = vc_sm_vchi_callback,
|
||||
.callback_param = instance,
|
||||
};
|
||||
|
||||
status = vchi_service_open(vchi_instance,
|
||||
¶ms, &instance->vchi_handle[i]);
|
||||
if (status) {
|
||||
pr_err("%s: failed to open VCHI service (%d)",
|
||||
__func__, status);
|
||||
|
||||
goto err_close_services;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the thread which takes care of all io to/from videoocore. */
|
||||
instance->io_thread = kthread_create(&vc_vchi_sm_videocore_io,
|
||||
(void *)instance, "SMIO");
|
||||
if (instance->io_thread == NULL) {
|
||||
pr_err("%s: failed to create SMIO thread", __func__);
|
||||
|
||||
goto err_close_services;
|
||||
}
|
||||
set_user_nice(instance->io_thread, -10);
|
||||
wake_up_process(instance->io_thread);
|
||||
|
||||
pr_debug("%s: success - instance 0x%x", __func__,
|
||||
(unsigned int)instance);
|
||||
return instance;
|
||||
|
||||
err_close_services:
|
||||
for (i = 0; i < instance->num_connections; i++) {
|
||||
if (instance->vchi_handle[i] != NULL)
|
||||
vchi_service_close(instance->vchi_handle[i]);
|
||||
}
|
||||
kfree(instance);
|
||||
pr_debug("%s: FAILED", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vc_vchi_sm_stop(struct sm_instance **handle)
|
||||
{
|
||||
struct sm_instance *instance;
|
||||
uint32_t i;
|
||||
|
||||
if (handle == NULL) {
|
||||
pr_err("%s: invalid pointer to handle %p", __func__, handle);
|
||||
goto lock;
|
||||
}
|
||||
|
||||
if (*handle == NULL) {
|
||||
pr_err("%s: invalid handle %p", __func__, *handle);
|
||||
goto lock;
|
||||
}
|
||||
|
||||
instance = *handle;
|
||||
|
||||
/* Close all VCHI service connections */
|
||||
for (i = 0; i < instance->num_connections; i++) {
|
||||
vchi_service_use(instance->vchi_handle[i]);
|
||||
|
||||
vchi_service_close(instance->vchi_handle[i]);
|
||||
}
|
||||
|
||||
kfree(instance);
|
||||
|
||||
*handle = NULL;
|
||||
return 0;
|
||||
|
||||
lock:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vc_vchi_sm_send_msg(struct sm_instance *handle,
|
||||
enum vc_sm_msg_type msg_id,
|
||||
void *msg, uint32_t msg_size,
|
||||
void *result, uint32_t result_size,
|
||||
uint32_t *cur_trans_id, uint8_t wait_reply)
|
||||
{
|
||||
int status = 0;
|
||||
struct sm_instance *instance = handle;
|
||||
struct sm_cmd_rsp_blk *cmd_blk;
|
||||
|
||||
if (handle == NULL) {
|
||||
pr_err("%s: invalid handle", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (msg == NULL) {
|
||||
pr_err("%s: invalid msg pointer", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_blk =
|
||||
vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply);
|
||||
if (cmd_blk == NULL) {
|
||||
pr_err("[%s]: failed to allocate global tracking resource",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cur_trans_id != NULL)
|
||||
*cur_trans_id = cmd_blk->id;
|
||||
|
||||
mutex_lock(&instance->lock);
|
||||
list_add_tail(&cmd_blk->head, &instance->cmd_list);
|
||||
mutex_unlock(&instance->lock);
|
||||
up(&instance->io_sema);
|
||||
|
||||
if (!wait_reply)
|
||||
/* We're done */
|
||||
return 0;
|
||||
|
||||
/* Wait for the response */
|
||||
if (down_interruptible(&cmd_blk->sema)) {
|
||||
mutex_lock(&instance->lock);
|
||||
if (!cmd_blk->sent) {
|
||||
list_del(&cmd_blk->head);
|
||||
mutex_unlock(&instance->lock);
|
||||
vc_vchi_cmd_delete(instance, cmd_blk);
|
||||
return -ENXIO;
|
||||
}
|
||||
mutex_unlock(&instance->lock);
|
||||
|
||||
mutex_lock(&instance->lock);
|
||||
list_move(&cmd_blk->head, &instance->dead_list);
|
||||
mutex_unlock(&instance->lock);
|
||||
up(&instance->io_sema);
|
||||
return -EINTR; /* We're done */
|
||||
}
|
||||
|
||||
if (result && result_size) {
|
||||
memcpy(result, cmd_blk->msg, result_size);
|
||||
} else {
|
||||
struct vc_sm_result_t *res =
|
||||
(struct vc_sm_result_t *) cmd_blk->msg;
|
||||
status = (res->success == 0) ? 0 : -ENXIO;
|
||||
}
|
||||
|
||||
mutex_lock(&instance->lock);
|
||||
list_del(&cmd_blk->head);
|
||||
mutex_unlock(&instance->lock);
|
||||
vc_vchi_cmd_delete(instance, cmd_blk);
|
||||
return status;
|
||||
}
|
||||
|
||||
int vc_vchi_sm_alloc(struct sm_instance *handle, struct vc_sm_alloc_t *msg,
|
||||
struct vc_sm_alloc_result_t *result,
|
||||
uint32_t *cur_trans_id)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_ALLOC,
|
||||
msg, sizeof(*msg), result, sizeof(*result),
|
||||
cur_trans_id, 1);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_free(struct sm_instance *handle,
|
||||
struct vc_sm_free_t *msg, uint32_t *cur_trans_id)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_FREE,
|
||||
msg, sizeof(*msg), 0, 0, cur_trans_id, 0);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_lock(struct sm_instance *handle,
|
||||
struct vc_sm_lock_unlock_t *msg,
|
||||
struct vc_sm_lock_result_t *result,
|
||||
uint32_t *cur_trans_id)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_LOCK,
|
||||
msg, sizeof(*msg), result, sizeof(*result),
|
||||
cur_trans_id, 1);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_unlock(struct sm_instance *handle,
|
||||
struct vc_sm_lock_unlock_t *msg,
|
||||
uint32_t *cur_trans_id, uint8_t wait_reply)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, wait_reply ?
|
||||
VC_SM_MSG_TYPE_UNLOCK :
|
||||
VC_SM_MSG_TYPE_UNLOCK_NOANS, msg,
|
||||
sizeof(*msg), 0, 0, cur_trans_id,
|
||||
wait_reply);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_resize(struct sm_instance *handle, struct vc_sm_resize_t *msg,
|
||||
uint32_t *cur_trans_id)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_RESIZE,
|
||||
msg, sizeof(*msg), 0, 0, cur_trans_id, 1);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_walk_alloc(struct sm_instance *handle)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_WALK_ALLOC,
|
||||
0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_clean_up(struct sm_instance *handle,
|
||||
struct vc_sm_action_clean_t *msg)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_ACTION_CLEAN,
|
||||
msg, sizeof(*msg), 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int vc_vchi_sm_import(struct sm_instance *handle, struct vc_sm_import *msg,
|
||||
struct vc_sm_import_result *result,
|
||||
uint32_t *cur_trans_id)
|
||||
{
|
||||
return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_IMPORT,
|
||||
msg, sizeof(*msg), result, sizeof(*result),
|
||||
cur_trans_id, 1);
|
||||
}
|
||||
100
drivers/char/broadcom/vc_sm/vc_vchi_sm.h
Normal file
100
drivers/char/broadcom/vc_sm/vc_vchi_sm.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
****************************************************************************
|
||||
* Copyright 2011 Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available at
|
||||
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* consent.
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __VC_VCHI_SM_H__INCLUDED__
|
||||
#define __VC_VCHI_SM_H__INCLUDED__
|
||||
|
||||
#include "interface/vchi/vchi.h"
|
||||
|
||||
#include "vc_sm_defs.h"
|
||||
|
||||
/*
|
||||
* Forward declare.
|
||||
*/
|
||||
struct sm_instance;
|
||||
|
||||
/*
|
||||
* Initialize the shared memory service, opens up vchi connection to talk to it.
|
||||
*/
|
||||
struct sm_instance *vc_vchi_sm_init(struct vchi_instance_handle * vchi_instance);
|
||||
|
||||
/*
|
||||
* Terminates the shared memory service.
|
||||
*/
|
||||
int vc_vchi_sm_stop(struct sm_instance **handle);
|
||||
|
||||
/*
|
||||
* Ask the shared memory service to allocate some memory on videocre and
|
||||
* return the result of this allocation (which upon success will be a pointer
|
||||
* to some memory in videocore space).
|
||||
*/
|
||||
int vc_vchi_sm_alloc(struct sm_instance *handle, struct vc_sm_alloc_t *alloc,
|
||||
struct vc_sm_alloc_result_t *alloc_result,
|
||||
uint32_t *trans_id);
|
||||
|
||||
/*
|
||||
* Ask the shared memory service to free up some memory that was previously
|
||||
* allocated by the vc_vchi_sm_alloc function call.
|
||||
*/
|
||||
int vc_vchi_sm_free(struct sm_instance *handle,
|
||||
struct vc_sm_free_t *free, uint32_t *trans_id);
|
||||
|
||||
/*
|
||||
* Ask the shared memory service to lock up some memory that was previously
|
||||
* allocated by the vc_vchi_sm_alloc function call.
|
||||
*/
|
||||
int vc_vchi_sm_lock(struct sm_instance *handle,
|
||||
struct vc_sm_lock_unlock_t *lock_unlock,
|
||||
struct vc_sm_lock_result_t *lock_result,
|
||||
uint32_t *trans_id);
|
||||
|
||||
/*
|
||||
* Ask the shared memory service to unlock some memory that was previously
|
||||
* allocated by the vc_vchi_sm_alloc function call.
|
||||
*/
|
||||
int vc_vchi_sm_unlock(struct sm_instance *handle,
|
||||
struct vc_sm_lock_unlock_t *lock_unlock,
|
||||
uint32_t *trans_id, uint8_t wait_reply);
|
||||
|
||||
/*
|
||||
* Ask the shared memory service to resize some memory that was previously
|
||||
* allocated by the vc_vchi_sm_alloc function call.
|
||||
*/
|
||||
int vc_vchi_sm_resize(struct sm_instance *handle,
|
||||
struct vc_sm_resize_t *resize, uint32_t *trans_id);
|
||||
|
||||
/*
|
||||
* Walk the allocated resources on the videocore side, the allocation will
|
||||
* show up in the log. This is purely for debug/information and takes no
|
||||
* specific actions.
|
||||
*/
|
||||
int vc_vchi_sm_walk_alloc(struct sm_instance *handle);
|
||||
|
||||
/*
|
||||
* Clean up following a previously interrupted action which left the system
|
||||
* in a bad state of some sort.
|
||||
*/
|
||||
int vc_vchi_sm_clean_up(struct sm_instance *handle,
|
||||
struct vc_sm_action_clean_t *action_clean);
|
||||
|
||||
/*
|
||||
* Import a contiguous block of memory and wrap it in a GPU MEM_HANDLE_T.
|
||||
*/
|
||||
int vc_vchi_sm_import(struct sm_instance *handle, struct vc_sm_import *msg,
|
||||
struct vc_sm_import_result *result,
|
||||
uint32_t *cur_trans_id);
|
||||
|
||||
#endif /* __VC_VCHI_SM_H__INCLUDED__ */
|
||||
3526
drivers/char/broadcom/vc_sm/vmcs_sm.c
Normal file
3526
drivers/char/broadcom/vc_sm/vmcs_sm.c
Normal file
File diff suppressed because it is too large
Load Diff
294
include/linux/broadcom/vmcs_sm_ioctl.h
Normal file
294
include/linux/broadcom/vmcs_sm_ioctl.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/*****************************************************************************
|
||||
* Copyright 2011 Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Unless you and Broadcom execute a separate written software license
|
||||
* agreement governing use of this software, this software is licensed to you
|
||||
* under the terms of the GNU General Public License version 2, available at
|
||||
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
|
||||
*
|
||||
* Notwithstanding the above, under no circumstances may you combine this
|
||||
* software in any way with any other Broadcom software provided under a
|
||||
* license other than the GPL, without Broadcom's express prior written
|
||||
* consent.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#if !defined(__VMCS_SM_IOCTL_H__INCLUDED__)
|
||||
#define __VMCS_SM_IOCTL_H__INCLUDED__
|
||||
|
||||
/* ---- Include Files ---------------------------------------------------- */
|
||||
|
||||
#if defined(__KERNEL__)
|
||||
#include <linux/types.h> /* Needed for standard types */
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* ---- Constants and Types ---------------------------------------------- */
|
||||
|
||||
#define VMCS_SM_RESOURCE_NAME 32
|
||||
#define VMCS_SM_RESOURCE_NAME_DEFAULT "sm-host-resource"
|
||||
|
||||
/* Type define used to create unique IOCTL number */
|
||||
#define VMCS_SM_MAGIC_TYPE 'I'
|
||||
|
||||
/* IOCTL commands */
|
||||
enum vmcs_sm_cmd_e {
|
||||
VMCS_SM_CMD_ALLOC = 0x5A, /* Start at 0x5A arbitrarily */
|
||||
VMCS_SM_CMD_ALLOC_SHARE,
|
||||
VMCS_SM_CMD_LOCK,
|
||||
VMCS_SM_CMD_LOCK_CACHE,
|
||||
VMCS_SM_CMD_UNLOCK,
|
||||
VMCS_SM_CMD_RESIZE,
|
||||
VMCS_SM_CMD_UNMAP,
|
||||
VMCS_SM_CMD_FREE,
|
||||
VMCS_SM_CMD_FLUSH,
|
||||
VMCS_SM_CMD_INVALID,
|
||||
|
||||
VMCS_SM_CMD_SIZE_USR_HANDLE,
|
||||
VMCS_SM_CMD_CHK_USR_HANDLE,
|
||||
|
||||
VMCS_SM_CMD_MAPPED_USR_HANDLE,
|
||||
VMCS_SM_CMD_MAPPED_USR_ADDRESS,
|
||||
VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR,
|
||||
VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL,
|
||||
VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL,
|
||||
|
||||
VMCS_SM_CMD_VC_WALK_ALLOC,
|
||||
VMCS_SM_CMD_HOST_WALK_MAP,
|
||||
VMCS_SM_CMD_HOST_WALK_PID_ALLOC,
|
||||
VMCS_SM_CMD_HOST_WALK_PID_MAP,
|
||||
|
||||
VMCS_SM_CMD_CLEAN_INVALID,
|
||||
VMCS_SM_CMD_CLEAN_INVALID2,
|
||||
|
||||
VMCS_SM_CMD_IMPORT_DMABUF,
|
||||
|
||||
VMCS_SM_CMD_LAST /* Do not delete */
|
||||
};
|
||||
|
||||
/* Cache type supported, conveniently matches the user space definition in
|
||||
** user-vcsm.h.
|
||||
*/
|
||||
enum vmcs_sm_cache_e {
|
||||
VMCS_SM_CACHE_NONE,
|
||||
VMCS_SM_CACHE_HOST,
|
||||
VMCS_SM_CACHE_VC,
|
||||
VMCS_SM_CACHE_BOTH,
|
||||
};
|
||||
|
||||
/* Cache functions */
|
||||
#define VCSM_CACHE_OP_INV 0x01
|
||||
#define VCSM_CACHE_OP_CLEAN 0x02
|
||||
#define VCSM_CACHE_OP_FLUSH 0x03
|
||||
|
||||
/* IOCTL Data structures */
|
||||
struct vmcs_sm_ioctl_alloc {
|
||||
/* user -> kernel */
|
||||
unsigned int size;
|
||||
unsigned int num;
|
||||
enum vmcs_sm_cache_e cached;
|
||||
char name[VMCS_SM_RESOURCE_NAME];
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int handle;
|
||||
/* unsigned int base_addr; */
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_alloc_share {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_free {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
/* unsigned int base_addr; */
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_lock_unlock {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int addr;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_lock_cache {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
enum vmcs_sm_cache_e cached;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_resize {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
unsigned int new_size;
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int old_size;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_map {
|
||||
/* user -> kernel */
|
||||
/* and kernel -> user */
|
||||
unsigned int pid;
|
||||
unsigned int handle;
|
||||
unsigned int addr;
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_walk {
|
||||
/* user -> kernel */
|
||||
unsigned int pid;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_chk {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int addr;
|
||||
unsigned int size;
|
||||
enum vmcs_sm_cache_e cache;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_size {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_cache {
|
||||
/* user -> kernel */
|
||||
unsigned int handle;
|
||||
unsigned int addr;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Cache functions to be set to struct vmcs_sm_ioctl_clean_invalid cmd and
|
||||
* vmcs_sm_ioctl_clean_invalid2 invalidate_mode.
|
||||
*/
|
||||
#define VCSM_CACHE_OP_NOP 0x00
|
||||
#define VCSM_CACHE_OP_INV 0x01
|
||||
#define VCSM_CACHE_OP_CLEAN 0x02
|
||||
#define VCSM_CACHE_OP_FLUSH 0x03
|
||||
|
||||
struct vmcs_sm_ioctl_clean_invalid {
|
||||
/* user -> kernel */
|
||||
struct {
|
||||
unsigned int cmd;
|
||||
unsigned int handle;
|
||||
unsigned int addr;
|
||||
unsigned int size;
|
||||
} s[8];
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_clean_invalid2 {
|
||||
uint8_t op_count;
|
||||
uint8_t zero[3];
|
||||
struct vmcs_sm_ioctl_clean_invalid_block {
|
||||
uint16_t invalidate_mode;
|
||||
uint16_t block_count;
|
||||
void * start_address;
|
||||
uint32_t block_size;
|
||||
uint32_t inter_block_stride;
|
||||
} s[0];
|
||||
};
|
||||
|
||||
struct vmcs_sm_ioctl_import_dmabuf {
|
||||
/* user -> kernel */
|
||||
int dmabuf_fd;
|
||||
enum vmcs_sm_cache_e cached;
|
||||
char name[VMCS_SM_RESOURCE_NAME];
|
||||
|
||||
/* kernel -> user */
|
||||
unsigned int handle;
|
||||
};
|
||||
|
||||
/* IOCTL numbers */
|
||||
#define VMCS_SM_IOCTL_MEM_ALLOC\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\
|
||||
struct vmcs_sm_ioctl_alloc)
|
||||
#define VMCS_SM_IOCTL_MEM_ALLOC_SHARE\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC_SHARE,\
|
||||
struct vmcs_sm_ioctl_alloc_share)
|
||||
#define VMCS_SM_IOCTL_MEM_LOCK\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_LOCK,\
|
||||
struct vmcs_sm_ioctl_lock_unlock)
|
||||
#define VMCS_SM_IOCTL_MEM_LOCK_CACHE\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_LOCK_CACHE,\
|
||||
struct vmcs_sm_ioctl_lock_cache)
|
||||
#define VMCS_SM_IOCTL_MEM_UNLOCK\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_UNLOCK,\
|
||||
struct vmcs_sm_ioctl_lock_unlock)
|
||||
#define VMCS_SM_IOCTL_MEM_RESIZE\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_RESIZE,\
|
||||
struct vmcs_sm_ioctl_resize)
|
||||
#define VMCS_SM_IOCTL_MEM_FREE\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_FREE,\
|
||||
struct vmcs_sm_ioctl_free)
|
||||
#define VMCS_SM_IOCTL_MEM_FLUSH\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_FLUSH,\
|
||||
struct vmcs_sm_ioctl_cache)
|
||||
#define VMCS_SM_IOCTL_MEM_INVALID\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\
|
||||
struct vmcs_sm_ioctl_cache)
|
||||
#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\
|
||||
struct vmcs_sm_ioctl_clean_invalid)
|
||||
#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID2\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID2,\
|
||||
struct vmcs_sm_ioctl_clean_invalid2)
|
||||
|
||||
#define VMCS_SM_IOCTL_SIZE_USR_HDL\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\
|
||||
struct vmcs_sm_ioctl_size)
|
||||
#define VMCS_SM_IOCTL_CHK_USR_HDL\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CHK_USR_HANDLE,\
|
||||
struct vmcs_sm_ioctl_chk)
|
||||
|
||||
#define VMCS_SM_IOCTL_MAP_USR_HDL\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_USR_HANDLE,\
|
||||
struct vmcs_sm_ioctl_map)
|
||||
#define VMCS_SM_IOCTL_MAP_USR_ADDRESS\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_USR_ADDRESS,\
|
||||
struct vmcs_sm_ioctl_map)
|
||||
#define VMCS_SM_IOCTL_MAP_VC_HDL_FR_ADDR\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR,\
|
||||
struct vmcs_sm_ioctl_map)
|
||||
#define VMCS_SM_IOCTL_MAP_VC_HDL_FR_HDL\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL,\
|
||||
struct vmcs_sm_ioctl_map)
|
||||
#define VMCS_SM_IOCTL_MAP_VC_ADDR_FR_HDL\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL,\
|
||||
struct vmcs_sm_ioctl_map)
|
||||
|
||||
#define VMCS_SM_IOCTL_VC_WALK_ALLOC\
|
||||
_IO(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_VC_WALK_ALLOC)
|
||||
#define VMCS_SM_IOCTL_HOST_WALK_MAP\
|
||||
_IO(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_MAP)
|
||||
#define VMCS_SM_IOCTL_HOST_WALK_PID_ALLOC\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_PID_ALLOC,\
|
||||
struct vmcs_sm_ioctl_walk)
|
||||
#define VMCS_SM_IOCTL_HOST_WALK_PID_MAP\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_PID_MAP,\
|
||||
struct vmcs_sm_ioctl_walk)
|
||||
|
||||
#define VMCS_SM_IOCTL_MEM_IMPORT_DMABUF\
|
||||
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_IMPORT_DMABUF,\
|
||||
struct vmcs_sm_ioctl_import_dmabuf)
|
||||
|
||||
/* ---- Variable Externs ------------------------------------------------- */
|
||||
|
||||
/* ---- Function Prototypes ---------------------------------------------- */
|
||||
|
||||
#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */
|
||||
Reference in New Issue
Block a user