Path: blob/21.2-virgl/src/freedreno/drm/freedreno_pipe.c
4564 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 "freedreno_drmif.h"27#include "freedreno_priv.h"2829/**30* priority of zero is highest priority, and higher numeric values are31* lower priorities32*/33struct fd_pipe *34fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio)35{36struct fd_pipe *pipe;37uint64_t val;3839if (id > FD_PIPE_MAX) {40ERROR_MSG("invalid pipe id: %d", id);41return NULL;42}4344if ((prio != 1) && (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES)) {45ERROR_MSG("invalid priority!");46return NULL;47}4849pipe = dev->funcs->pipe_new(dev, id, prio);50if (!pipe) {51ERROR_MSG("allocation failed");52return NULL;53}5455pipe->dev = fd_device_ref(dev);56pipe->id = id;57p_atomic_set(&pipe->refcnt, 1);5859fd_pipe_get_param(pipe, FD_GPU_ID, &val);60pipe->gpu_id = val;6162pipe->control_mem = fd_bo_new(dev, sizeof(*pipe->control),630, "pipe-control");64pipe->control = fd_bo_map(pipe->control_mem);6566/* We could be getting a bo from the bo-cache, make sure the fence value67* is not garbage:68*/69pipe->control->fence = 0;7071/* We don't want the control_mem bo to hold a reference to the ourself,72* so disable userspace fencing. This also means that we won't be able73* to determine if the buffer is idle which is needed by bo-cache. But74* pipe creation/destroy is not a high frequency event so just disable75* the bo-cache as well:76*/77pipe->control_mem->nosync = true;78pipe->control_mem->bo_reuse = NO_CACHE;7980return pipe;81}8283struct fd_pipe *84fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)85{86return fd_pipe_new2(dev, id, 1);87}8889struct fd_pipe *90fd_pipe_ref(struct fd_pipe *pipe)91{92simple_mtx_lock(&table_lock);93fd_pipe_ref_locked(pipe);94simple_mtx_unlock(&table_lock);95return pipe;96}9798struct fd_pipe *99fd_pipe_ref_locked(struct fd_pipe *pipe)100{101simple_mtx_assert_locked(&table_lock);102pipe->refcnt++;103return pipe;104}105106void107fd_pipe_del(struct fd_pipe *pipe)108{109simple_mtx_lock(&table_lock);110fd_pipe_del_locked(pipe);111simple_mtx_unlock(&table_lock);112}113114void115fd_pipe_del_locked(struct fd_pipe *pipe)116{117simple_mtx_assert_locked(&table_lock);118if (!p_atomic_dec_zero(&pipe->refcnt))119return;120fd_bo_del_locked(pipe->control_mem);121fd_device_del_locked(pipe->dev);122pipe->funcs->destroy(pipe);123}124125/**126* Discard any unflushed deferred submits. This is called at context-127* destroy to make sure we don't leak unflushed submits.128*/129void130fd_pipe_purge(struct fd_pipe *pipe)131{132struct fd_device *dev = pipe->dev;133struct list_head deferred_submits;134135list_inithead(&deferred_submits);136137simple_mtx_lock(&dev->submit_lock);138139foreach_submit_safe (deferred_submit, &dev->deferred_submits) {140if (deferred_submit->pipe != pipe)141continue;142143list_del(&deferred_submit->node);144list_addtail(&deferred_submit->node, &deferred_submits);145dev->deferred_cmds -= fd_ringbuffer_cmd_count(deferred_submit->primary);146}147148simple_mtx_unlock(&dev->submit_lock);149150foreach_submit_safe (deferred_submit, &deferred_submits) {151list_del(&deferred_submit->node);152fd_submit_del(deferred_submit);153}154}155156int157fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value)158{159return pipe->funcs->get_param(pipe, param, value);160}161162int163fd_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence)164{165return fd_pipe_wait_timeout(pipe, fence, ~0);166}167168int169fd_pipe_wait_timeout(struct fd_pipe *pipe, const struct fd_fence *fence,170uint64_t timeout)171{172if (!fd_fence_after(fence->ufence, pipe->control->fence))173return 0;174175fd_pipe_flush(pipe, fence->ufence);176177return pipe->funcs->wait(pipe, fence, timeout);178}179180uint32_t181fd_pipe_emit_fence(struct fd_pipe *pipe, struct fd_ringbuffer *ring)182{183uint32_t fence = ++pipe->last_fence;184185if (pipe->gpu_id >= 500) {186OUT_PKT7(ring, CP_EVENT_WRITE, 4);187OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_TS));188OUT_RELOC(ring, control_ptr(pipe, fence)); /* ADDR_LO/HI */189OUT_RING(ring, fence);190} else {191OUT_PKT3(ring, CP_EVENT_WRITE, 3);192OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_TS));193OUT_RELOC(ring, control_ptr(pipe, fence)); /* ADDR */194OUT_RING(ring, fence);195}196197return fence;198}199200201