kgsl_ioctl_gpu_command
Posted bubbleben
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kgsl_ioctl_gpu_command相关的知识,希望对你有一定的参考价值。
// ioctl命令:IOCTL_KGSL_GPU_COMMAND
// ioctl参数:kgsl_gpu_command
// ioctl函数:kgsl_ioctl_gpu_command
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_COMMAND, kgsl_ioctl_gpu_command),
1. kgsl_ioctl_gpu_command
long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
// IOCTL_KGSL_GPU_COMMAND命令参数[见1.1节]
struct kgsl_gpu_command *param = data;
struct kgsl_device *device = dev_priv->device;
struct kgsl_context *context;
// kgsl_drawobj[见第1.2节]数组:用于存放kgsl_drawobj_sync和kgsl_drawobj_cmd中的kgsl_drawobj
struct kgsl_drawobj *drawobj[2];
unsigned int type;
long result;
unsigned int i = 0;
// 根据参数计算对象类型[见第2节]
type = _process_command_input(device, param->flags, param->numcmds,
param->numobjs, param->numsyncs);
if (!type)
return -EINVAL;
// 根据context id查找对应的kgsl_context
context = kgsl_context_get_owner(dev_priv, param->context_id);
if (context == NULL)
return -EINVAL;
// 1.如果指定KGSL_DRAWOBJ_SYNC标志位, 则命令类型为SYNCOBJ_TYPE
// 2.如果传入的kgsl_gpu_command的numsyncs大于0, 则命令类型包含SYNCOBJ_TYPE
if (type & SYNCOBJ_TYPE)
struct kgsl_drawobj_sync *syncobj =
kgsl_drawobj_sync_create(device, context);
if (IS_ERR(syncobj))
result = PTR_ERR(syncobj);
goto done;
drawobj[i++] = DRAWOBJ(syncobj);
result = kgsl_drawobj_sync_add_synclist(device, syncobj,
u64_to_user_ptr(param->synclist),
param->syncsize, param->numsyncs);
if (result)
goto done;
// 1.如果指定KGSL_DRAWOBJ_MARKER标志位, 则命令类型为MARKEROBJ_TYPE
// 2.如果传入的kgsl_gpu_command的numcmds大于0, 则命令类型包含CMDOBJ_TYPE
// 3.如果传入的kgsl_gpu_command的numcmds等于0, 则命令类型为MARKEROBJ_TYPE
if (type & (CMDOBJ_TYPE | MARKEROBJ_TYPE))
// 调用kgsl_drawobj_cmd_create[见第3节]创建kgsl_drawobj_cmd
struct kgsl_drawobj_cmd *cmdobj =
kgsl_drawobj_cmd_create(device,
context, param->flags, type);
if (IS_ERR(cmdobj))
result = PTR_ERR(cmdobj);
goto done;
// drawobj数组元素加1
drawobj[i++] = DRAWOBJ(cmdobj);
// 将cmdlist插入kgsl_drawobj_cmd的cmdlist链表[第4节]
result = kgsl_drawobj_cmd_add_cmdlist(device, cmdobj,
u64_to_user_ptr(param->cmdlist),
param->cmdsize, param->numcmds);
if (result)
goto done;
// 将objlist插入kgsl_drawobj_cmd的memlist链表[第5节]
result = kgsl_drawobj_cmd_add_memlist(device, cmdobj,
u64_to_user_ptr(param->objlist),
param->objsize, param->numobjs);
if (result)
goto done;
/* If no profiling buffer was specified, clear the flag */
if (cmdobj->profiling_buf_entry == NULL)
DRAWOBJ(cmdobj)->flags &=
~(unsigned long)KGSL_DRAWOBJ_PROFILING;
// 调用adreno_functable中定义的adreno_queue_cmds[第6节]将kgsl_drawobj提交给ringbuffer
result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
i, ¶m->timestamp);
done:
/*
* -EPROTO is a "success" error - it just tells the user that the
* context had previously faulted
*/
if (result && result != -EPROTO)
while (i--)
kgsl_drawobj_destroy(drawobj[i]);
kgsl_context_put(context);
return result;
1.1 kgsl_gpu_command
/**
* struct kgsl_command_object - Argument for IOCTL_KGSL_GPU_COMMAND
*/
struct kgsl_gpu_command
// 标志位
__u64 flags;
// 指向kgsl_command_object链表的指针(for submission)
__u64 __user cmdlist;
// kgsl_command_object的大小
unsigned int cmdsize;
// cmdlist中kgsl_command_object的数量
unsigned int numcmds;
// 指向kgsl_command_object链表的指针(for tracking)
__u64 __user objlist;
// kgsl_command_object的大小
unsigned int objsize;
// objlist中kgsl_command_object的数量
unsigned int numobjs;
// 指向kgsl_command_syncpoint链表的指针
__u64 __user synclist;
// kgsl_command_syncpoint的大小
unsigned int syncsize;
// synclist中kgsl_command_syncpoint的数量
unsigned int numsyncs;
// kgsl_context的id
unsigned int context_id;
// Timestamp for the submitted commands
unsigned int timestamp;
;
1.2 kgsl_drawobj
/**
* struct kgsl_drawobj - KGSL drawobj descriptor
*/
// kgsl_drawobj的容器为kgsl_drawobj_cmd[见1.3节]
struct kgsl_drawobj
// KGSL GPU device that the command was created for
struct kgsl_device *device;
// KGSL context that created the command
struct kgsl_context *context;
// Object type
uint32_t type;
// Timestamp assigned to the command
uint32_t timestamp;
// 标志位
unsigned long flags;
// 引用计数
struct kref refcount;
/** @destroy: Callbak function to take down the object */
void (*destroy)(struct kgsl_drawobj *drawobj);
/** @destroy_object: Callback function to free the object memory */
void (*destroy_object)(struct kgsl_drawobj *drawobj);
;
1.3 kgsl_drawobj_cmd
/**
* struct kgsl_drawobj_cmd - KGSL command obj, This covers marker
* cmds also since markers are special form of cmds that do not
* need their cmds to be executed.
*/
struct kgsl_drawobj_cmd
// 第一个成员
struct kgsl_drawobj base;
// Internal flags
unsigned long priv;
// The ringbuffer timestamp corresponding to this command obj
unsigned int global_ts;
unsigned long fault_policy;
unsigned long fault_recovery;
// List of IBs to issue
struct list_head cmdlist;
// List of all memory used in this command batch
struct list_head memlist;
// For markers, the timestamp of the last "real" command that was queued
unsigned int marker_timestamp;
// profiling
struct kgsl_mem_entry *profiling_buf_entry;
uint64_t profiling_buffer_gpuaddr;
unsigned int profile_index;
// Variable to hold ticks at the time of command obj submit
uint64_t submit_ticks;
;
2. _process_command_input
// kgsl_command_object最多100000个
#define KGSL_MAX_NUMIBS 100000
// kgsl_command_syncpoint最多32个
#define KGSL_MAX_SYNCPOINTS 32
#define CMDOBJ_TYPE BIT(0)
#define MARKEROBJ_TYPE BIT(1)
#define SYNCOBJ_TYPE BIT(2)
#define TIMELINEOBJ_TYPE BIT(4)
/* Returns 0 on failure. Returns command type(s) on success */
static unsigned int _process_command_input(struct kgsl_device *device,
unsigned int flags, unsigned int numcmds,
unsigned int numobjs, unsigned int numsyncs)
// kgsl_gpu_command的成员numcmds, numobjs和numsyncs不能超过最大限制
if (numcmds > KGSL_MAX_NUMIBS ||
numobjs > KGSL_MAX_NUMIBS ||
numsyncs > KGSL_MAX_SYNCPOINTS)
return 0;
/*
* The SYNC bit is supposed to identify a dummy sync object
* so warn the user if they specified any IBs with it.
* A MARKER command can either have IBs or not but if the
* command has 0 IBs it is automatically assumed to be a marker.
*/
/* If they specify the flag, go with what they say */
// 首先根据标志位判断对象类型
if (flags & KGSL_DRAWOBJ_MARKER)
return MARKEROBJ_TYPE;
else if (flags & KGSL_DRAWOBJ_SYNC)
return SYNCOBJ_TYPE;
/* If not, deduce what they meant */
// 然后根据numsyncs和numcmds确定对象类型
if (numsyncs && numcmds)
return SYNCOBJ_TYPE | CMDOBJ_TYPE;
else if (numsyncs)
return SYNCOBJ_TYPE;
else if (numcmds)
return CMDOBJ_TYPE;
else if (numcmds == 0)
return MARKEROBJ_TYPE;
return 0;
3. kgsl_drawobj_cmd_create
/**
* kgsl_drawobj_cmd_create() - Create a new command obj structure
* Allocate a new kgsl_drawobj_cmd structure
*/
struct kgsl_drawobj_cmd *kgsl_drawobj_cmd_create(struct kgsl_device *device,
struct kgsl_context *context, unsigned int flags,
unsigned int type)
// 分配kgsl_drawobj_cmd
struct kgsl_drawobj_cmd *cmdobj = kzalloc(sizeof(*cmdobj), GFP_KERNEL);
int ret;
if (!cmdobj)
return ERR_PTR(-ENOMEM);
// 初始化kgsl_drawobj[见3.1节]
ret = drawobj_init(device, context, &cmdobj->base,
(type & (CMDOBJ_TYPE | MARKEROBJ_TYPE)));
if (ret)
kfree(cmdobj);
return ERR_PTR(ret);
// 设置kgsl_drawobj的destroy回调
cmdobj->base.destroy = cmdobj_destroy;
// 设置kgsl_drawobj的destroy_object回调
cmdobj->base.destroy_object = cmdobj_destroy_object;
/* sanitize our flags for drawobjs */
// 设置kgsl_drawobj的标志位
cmdobj->base.flags = flags & (KGSL_DRAWOBJ_CTX_SWITCH
| KGSL_DRAWOBJ_MARKER
| KGSL_DRAWOBJ_END_OF_FRAME
| KGSL_DRAWOBJ_PWR_CONSTRAINT
| KGSL_DRAWOBJ_MEMLIST
| KGSL_DRAWOBJ_PROFILING
| KGSL_DRAWOBJ_PROFILING_KTIME);
// 初始化kgsl_drawobj_cmd的cmdlist
INIT_LIST_HEAD(&cmdobj->cmdlist);
// 初始化kgsl_drawobj_cmd的memlist
INIT_LIST_HEAD(&cmdobj->memlist);
return cmdobj;
3.1 drawobj_init
static int drawobj_init(struct kgsl_device *device,
struct kgsl_context *context, struct kgsl_drawobj *drawobj,
int type)
/*
* Increase the reference count on the context so it doesn't disappear
* during the lifetime of this object
*/
// 增加kgsl_context引用计数
if (!_kgsl_context_get(context))
return -ENOENT;
// 初始化kgsl_drawobj的引用计数
kref_init(&drawobj->refcount);
drawobj->device = device;
// 设置kgsl_drawobj所属的kgsl_context
drawobj->context = context;
// 设置kgsl_drawobj类型
drawobj->type = type;
return 0;
4. kgsl_drawobj_cmd_add_cmdlist
/* This can only accept MARKEROBJ_TYPE and CMDOBJ_TYPE */
// ptr:kgsl_gpu_command的cmdlist
// size:kgsl_gpu_command的cmdsize
// count:kgsl_gpu_command的numcmds
int kgsl_drawobj_cmd_add_cmdlist(struct kgsl_device *device,
struct kgsl_drawobj_cmd *cmdobj, void __user *ptr,
unsigned int size, unsigned int count)
// kgsl_command_object[见4.1节]
struct kgsl_command_object obj;
struct kgsl_drawobj *baseobj = DRAWOBJ(cmdobj);
int i, ret;
/* Ignore everything if this is a MARKER */
if (baseobj->type & MARKEROBJ_TYPE)
return 0;
// 参数校验
ret = _verify_input_list(count, ptr, size);
if (ret <= 0)
return ret;
// 遍历每一个cmd
for (i = 0; i < count; i++)
memset(&obj, 0, sizeof(obj));
// 将用户空间传入的ptr指向的大小为size的对象拷贝到kgsl_command_object
ret = kgsl_copy_from_user(&obj, ptr, sizeof(obj), size);
if (ret)
return ret;
/* Sanity check the flags */
if (!(obj.flags & CMDLIST_FLAGS))
dev_err(device->dev,
"invalid cmdobj ctxt %d flags %d id %d offset %llu addr %llx size %llu\\n",
baseobj->context->id, obj.flags, obj.id,
obj.offset, obj.gpuaddr, obj.size);
return -EINVAL;
// 将kgsl_command_object添加到kgsl_drawobj_cmd的链表cmdlist[见4.2节]
ret = kgsl_drawobj_add_memobject(&cmdobj->cmdlist, &obj);
if (ret)
return ret;
// ptr指针向后移动以遍历下一个cmd
ptr += sizeof(obj);
return 0;
4.1 kgsl_command_object
/**
* struct kgsl_command_object - GPU command object
*/
struct kgsl_command_object
// GPU address offset of the object
__u64 offset;
// GPU address of the object
__u64 gpuaddr;
// Size of the object
__u64 size;
// Current flags for the object
unsigned int flags;
// GPU command object ID
unsigned int id;
;
4.2 kgsl_drawobj_add_memobject
static int kgsl_drawobj_add_memobject(struct list_head *head,
struct kgsl_command_object *obj)
struct kgsl_memobj_node *mem;
// 创建kgsl_memobj_node[见4.2.1节]
mem = kmem_cache_alloc(memobjs_cache, GFP_KERNEL);
if (mem == NULL)
return -ENOMEM;
// 将kgsl_command_object的成员赋值给kgsl_memobj_node
mem->gpuaddr = obj->gpuaddr;
mem->size = obj->size;
mem->id = obj->id;
mem->offset = obj->offset;
mem->flags = obj->flags;
// 初始化priv成员
mem->priv = 0;
// 将kgsl_memobj_node插入到kgsl_drawobj_cmd链表cmdlist的表尾
list_add_tail(&mem->node, head);
return 0;
4.2.1 kgsl_memobj_node
/**
* struct kgsl_memobj_node - Memory object descriptor
* @node: Local list node for the object
* @id: GPU memory ID for the object
* offset: Offset within the object
* @gpuaddr: GPU address for the object
* @flags: External flags passed by the user
* @priv: Internal flags set by the driver
*/
struct kgsl_memobj_node
struct list_head node;
unsigned int id;
uint64_t offset;
uint64_t gpuaddr;
uint64_t size;
unsigned long flags;
unsigned long priv;
;
5. kgsl_drawobj_cmd_add_memlist
// ptr:kgsl_gpu_command的objlist
// size:kgsl_gpu_command的objsize
// count:kgsl_gpu_command的numobjs
int kgsl_drawobj_cmd_add_memlist(struct kgsl_device *device,
struct kgsl_drawobj_cmd *cmdobj, void __user *ptr,
unsigned int size, unsigned int count)
struct kgsl_command_object obj;
struct kgsl_drawobj *baseobj = DRAWOBJ(cmdobj);
int i, ret;
/* Ignore everything if this is a MARKER */
if (baseobj->type & MARKEROBJ_TYPE)
return 0;
ret = _verify_input_list(count, ptr, size);
if (ret <= 0)
return ret;
// 遍历每一个cmd
for (i = 0; i < count; i++)
memset(&obj, 0, sizeof(obj));
// 将用户空间传入的ptr指向的大小为size的对象拷贝到kgsl_command_object
ret = kgsl_copy_from_user(&obj, ptr, sizeof(obj), size);
if (ret)
return ret;
if (!(obj.flags & KGSL_OBJLIST_MEMOBJ))
dev_err(device->dev,
"invalid memobj ctxt %d flags %d id %d offset %lld addr %lld size %lld\\n",
DRAWOBJ(cmdobj)->context->id, obj.flags,
obj.id, obj.offset, obj.gpuaddr,
obj.size);
return -EINVAL;
if (obj.flags & KGSL_OBJLIST_PROFILE)
add_profiling_buffer(device, cmdobj, obj.gpuaddr,
obj.size, obj.id, obj.offset);
else
// 将kgsl_command_object添加到kgsl_drawobj_cmd的链表memlist
ret = kgsl_drawobj_add_memobject(&cmdobj->memlist,
&obj);
if (ret)
return ret;
// ptr指针向后移动以遍历下一个cmd
ptr += sizeof(obj);
return 0;
6. adreno_queue_cmds
static int adreno_queue_cmds(struct kgsl_device_private *dev_priv,
struct kgsl_context *context, struct kgsl_drawobj *drawobj[],
u32 count, u32 *timestamp)
struct kgsl_device *device = dev_priv->device;
if (test_bit(GMU_DISPATCH, &device->gmu_core.flags))
return adreno_hwsched_queue_cmds(dev_priv, context, drawobj,
count, timestamp);
// Queue a new draw object in the context[见第7节]
return adreno_dispatcher_queue_cmds(dev_priv, context, drawobj, count,
timestamp);
7. adreno_dispatcher_queue_cmds
/* Number of commands that can be queued in a context before it sleeps */
static unsigned int _context_drawqueue_size = 50;
/**
* adreno_dispactcher_queue_cmds() - Queue a new draw object in the context
* @dev_priv: Pointer to the device private struct
* @context: Pointer to the kgsl draw context
* @drawobj: Pointer to the array of drawobj's being submitted
* @count: Number of drawobj's being submitted
* @timestamp: Pointer to the requested timestamp
*
* Queue a command in the context - if there isn't any room in the queue, then
* block until there is
*/
int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
struct kgsl_con以上是关于kgsl_ioctl_gpu_command的主要内容,如果未能解决你的问题,请参考以下文章
Linux Shell中编写判断IP地址有效性脚本碰到了问题