Path: blob/21.2-virgl/src/freedreno/drm/msm_pipe.c
4565 views
/*1* Copyright (C) 2012-2018 Rob Clark <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors:23* Rob Clark <[email protected]>24*/2526#include "util/slab.h"2728#include "msm_priv.h"2930static int31query_param(struct fd_pipe *pipe, uint32_t param, uint64_t *value)32{33struct msm_pipe *msm_pipe = to_msm_pipe(pipe);34struct drm_msm_param req = {35.pipe = msm_pipe->pipe,36.param = param,37};38int ret;3940ret =41drmCommandWriteRead(pipe->dev->fd, DRM_MSM_GET_PARAM, &req, sizeof(req));42if (ret)43return ret;4445*value = req.value;4647return 0;48}4950static int51query_queue_param(struct fd_pipe *pipe, uint32_t param, uint64_t *value)52{53struct msm_pipe *msm_pipe = to_msm_pipe(pipe);54struct drm_msm_submitqueue_query req = {55.data = VOID2U64(value),56.id = msm_pipe->queue_id,57.param = param,58.len = sizeof(*value),59};60int ret;6162ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_QUERY, &req,63sizeof(req));64if (ret)65return ret;6667return 0;68}6970static int71msm_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,72uint64_t *value)73{74struct msm_pipe *msm_pipe = to_msm_pipe(pipe);75switch (param) {76case FD_DEVICE_ID: // XXX probably get rid of this..77case FD_GPU_ID:78*value = msm_pipe->gpu_id;79return 0;80case FD_GMEM_SIZE:81*value = msm_pipe->gmem;82return 0;83case FD_GMEM_BASE:84*value = msm_pipe->gmem_base;85return 0;86case FD_CHIP_ID:87*value = msm_pipe->chip_id;88return 0;89case FD_MAX_FREQ:90return query_param(pipe, MSM_PARAM_MAX_FREQ, value);91case FD_TIMESTAMP:92return query_param(pipe, MSM_PARAM_TIMESTAMP, value);93case FD_NR_RINGS:94return query_param(pipe, MSM_PARAM_NR_RINGS, value);95case FD_PP_PGTABLE:96return query_param(pipe, MSM_PARAM_PP_PGTABLE, value);97case FD_CTX_FAULTS:98return query_queue_param(pipe, MSM_SUBMITQUEUE_PARAM_FAULTS, value);99case FD_GLOBAL_FAULTS:100return query_param(pipe, MSM_PARAM_FAULTS, value);101case FD_SUSPEND_COUNT:102return query_param(pipe, MSM_PARAM_SUSPENDS, value);103default:104ERROR_MSG("invalid param id: %d", param);105return -1;106}107}108109static int110msm_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence, uint64_t timeout)111{112struct fd_device *dev = pipe->dev;113struct drm_msm_wait_fence req = {114.fence = fence->kfence,115.queueid = to_msm_pipe(pipe)->queue_id,116};117int ret;118119get_abs_timeout(&req.timeout, timeout);120121ret = drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &req, sizeof(req));122if (ret && (ret != -ETIMEDOUT)) {123ERROR_MSG("wait-fence failed! %d (%s)", ret, strerror(errno));124}125126return ret;127}128129static int130open_submitqueue(struct fd_pipe *pipe, uint32_t prio)131{132struct drm_msm_submitqueue req = {133.flags = 0,134.prio = prio,135};136uint64_t nr_rings = 1;137int ret;138139if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) {140to_msm_pipe(pipe)->queue_id = 0;141return 0;142}143144msm_pipe_get_param(pipe, FD_NR_RINGS, &nr_rings);145146req.prio = MIN2(req.prio, MAX2(nr_rings, 1) - 1);147148ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_NEW, &req,149sizeof(req));150if (ret) {151ERROR_MSG("could not create submitqueue! %d (%s)", ret, strerror(errno));152return ret;153}154155to_msm_pipe(pipe)->queue_id = req.id;156return 0;157}158159static void160close_submitqueue(struct fd_pipe *pipe, uint32_t queue_id)161{162if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES)163return;164165drmCommandWrite(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_CLOSE, &queue_id,166sizeof(queue_id));167}168169static void170msm_pipe_destroy(struct fd_pipe *pipe)171{172struct msm_pipe *msm_pipe = to_msm_pipe(pipe);173174if (msm_pipe->suballoc_bo)175fd_bo_del_locked(msm_pipe->suballoc_bo);176177close_submitqueue(pipe, msm_pipe->queue_id);178msm_pipe_sp_ringpool_init(msm_pipe);179free(msm_pipe);180}181182static const struct fd_pipe_funcs sp_funcs = {183.ringbuffer_new_object = msm_ringbuffer_sp_new_object,184.submit_new = msm_submit_sp_new,185.flush = msm_pipe_sp_flush,186.get_param = msm_pipe_get_param,187.wait = msm_pipe_wait,188.destroy = msm_pipe_destroy,189};190191static const struct fd_pipe_funcs legacy_funcs = {192.ringbuffer_new_object = msm_ringbuffer_new_object,193.submit_new = msm_submit_new,194.get_param = msm_pipe_get_param,195.wait = msm_pipe_wait,196.destroy = msm_pipe_destroy,197};198199static uint64_t200get_param(struct fd_pipe *pipe, uint32_t param)201{202uint64_t value;203int ret = query_param(pipe, param, &value);204if (ret) {205ERROR_MSG("get-param failed! %d (%s)", ret, strerror(errno));206return 0;207}208return value;209}210211struct fd_pipe *212msm_pipe_new(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio)213{214static const uint32_t pipe_id[] = {215[FD_PIPE_3D] = MSM_PIPE_3D0,216[FD_PIPE_2D] = MSM_PIPE_2D0,217};218struct msm_pipe *msm_pipe = NULL;219struct fd_pipe *pipe = NULL;220221msm_pipe = calloc(1, sizeof(*msm_pipe));222if (!msm_pipe) {223ERROR_MSG("allocation failed");224goto fail;225}226227pipe = &msm_pipe->base;228229if (fd_device_version(dev) >= FD_VERSION_SOFTPIN) {230pipe->funcs = &sp_funcs;231} else {232pipe->funcs = &legacy_funcs;233}234235/* initialize before get_param(): */236pipe->dev = dev;237msm_pipe->pipe = pipe_id[id];238239/* these params should be supported since the first version of drm/msm: */240msm_pipe->gpu_id = get_param(pipe, MSM_PARAM_GPU_ID);241msm_pipe->gmem = get_param(pipe, MSM_PARAM_GMEM_SIZE);242msm_pipe->chip_id = get_param(pipe, MSM_PARAM_CHIP_ID);243244if (fd_device_version(pipe->dev) >= FD_VERSION_GMEM_BASE)245msm_pipe->gmem_base = get_param(pipe, MSM_PARAM_GMEM_BASE);246247if (!msm_pipe->gpu_id)248goto fail;249250INFO_MSG("Pipe Info:");251INFO_MSG(" GPU-id: %d", msm_pipe->gpu_id);252INFO_MSG(" Chip-id: 0x%08x", msm_pipe->chip_id);253INFO_MSG(" GMEM size: 0x%08x", msm_pipe->gmem);254255if (open_submitqueue(pipe, prio))256goto fail;257258msm_pipe_sp_ringpool_init(msm_pipe);259260return pipe;261fail:262if (pipe)263fd_pipe_del(pipe);264return NULL;265}266267268