From 90e151e2c40ab4397da72447769cef63c291ec36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 24 Sep 2021 17:22:58 +0200 Subject: [PATCH] gpu: add 'complete' RPC call This call allows for checking if the given execution buffer has been completed and complements the completion signal. Initially the GPU multiplexer always sent such a signal when the currently scheduled execution buffer has been completed. During enablement of the 'iris' driver it became necessary to properly check of sequence number. In case of the Intel GPU multiplexer the sequence numbers are continous, which prompted the greater-than-or-equal check in the DRM back end. By hidding this implementation detail behind the interface, GPU drivers are free to deal with sequence numbers any way they like and allows for polling in the client, where the completion signal is now more of a progress signal. Issue #4265. --- repos/libports/src/lib/libdrm/ioctl_iris.cc | 21 ++++++++++----------- repos/os/include/gpu_session/client.h | 3 +++ repos/os/include/gpu_session/gpu_session.h | 14 +++++++++++++- repos/os/src/drivers/gpu/intel/main.cc | 5 +++++ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/repos/libports/src/lib/libdrm/ioctl_iris.cc b/repos/libports/src/lib/libdrm/ioctl_iris.cc index d2a2c9763f..3f5641e9f6 100644 --- a/repos/libports/src/lib/libdrm/ioctl_iris.cc +++ b/repos/libports/src/lib/libdrm/ioctl_iris.cc @@ -227,7 +227,6 @@ class Drm_call Gpu::Info_intel const &_gpu_info { *_gpu_session.attached_info() }; size_t _available_gtt_size { _gpu_info.aperture_size }; - bool _complete { false }; using Buffer = Gpu::Buffer; @@ -376,11 +375,7 @@ class Drm_call ** execbuffer completion ** ***************************/ - void _handle_completion() - { - /* wake up possible waiters */ - _complete = true; - } + void _handle_completion() { } Genode::Io_signal_handler _completion_sigh { _env.ep(), *this, &Drm_call::_handle_completion }; @@ -811,9 +806,11 @@ class Drm_call while (busy) { + Gpu::Sequence_number seqno { }; try { _buffer_space.apply(id, [&](Buffer &b) { busy = b.busy; + seqno = b.seqno; }); } catch (Genode::Id_space::Unknown_id) { Genode::error(__func__, ": handle ", p->bo_handle, " invalid"); @@ -830,7 +827,7 @@ class Drm_call return -1; } - wait_for_completion(); + wait_for_completion(seqno); } return 0; @@ -1139,12 +1136,14 @@ class Drm_call : _generic_ioctl(command_number(request), arg); } - void wait_for_completion() + void wait_for_completion(Gpu::Sequence_number seqno) { - _complete = false; - - while (_complete == false) + while (true) { + if (_gpu_session.complete(seqno)) { + break; + } _env.ep().wait_and_dispatch_one_io_signal(); + } /* mark done buffer objects */ diff --git a/repos/os/include/gpu_session/client.h b/repos/os/include/gpu_session/client.h index b136bc5ab3..83f7f277ad 100644 --- a/repos/os/include/gpu_session/client.h +++ b/repos/os/include/gpu_session/client.h @@ -44,6 +44,9 @@ class Gpu::Session_client : public Genode::Rpc_client Genode::size_t size) override { return call(id, size); } + bool complete(Sequence_number seqno) override { + return call(seqno); } + void completion_sigh(Genode::Signal_context_capability sigh) override { call(sigh); } diff --git a/repos/os/include/gpu_session/gpu_session.h b/repos/os/include/gpu_session/gpu_session.h index fe8f1b6f47..4753cab096 100644 --- a/repos/os/include/gpu_session/gpu_session.h +++ b/repos/os/include/gpu_session/gpu_session.h @@ -75,6 +75,16 @@ struct Gpu::Session : public Genode::Session */ virtual Gpu::Sequence_number exec_buffer(Buffer_id id, Genode::size_t size) = 0; + /** + * Check if execution buffer has been completed + * + * \param seqno sequence number of the execution buffer + * + * \return true if execution buffer has been finished, otherwise + * false is returned + */ + virtual bool complete(Sequence_number seqno) = 0; + /** * Register completion signal handler * @@ -155,6 +165,8 @@ struct Gpu::Session : public Genode::Session GENODE_RPC_THROW(Rpc_exec_buffer, Gpu::Sequence_number, exec_buffer, GENODE_TYPE_LIST(Invalid_state), Gpu::Buffer_id, Genode::size_t); + GENODE_RPC(Rpc_complete, bool, complete, + Gpu::Sequence_number); GENODE_RPC(Rpc_completion_sigh, void, completion_sigh, Genode::Signal_context_capability); GENODE_RPC_THROW(Rpc_alloc_buffer, Genode::Dataspace_capability, alloc_buffer, @@ -175,7 +187,7 @@ struct Gpu::Session : public Genode::Session Gpu::Buffer_id, unsigned); GENODE_RPC_INTERFACE(Rpc_info_dataspace, Rpc_exec_buffer, - Rpc_completion_sigh, Rpc_alloc_buffer, + Rpc_complete, Rpc_completion_sigh, Rpc_alloc_buffer, Rpc_free_buffer, Rpc_map_buffer, Rpc_unmap_buffer, Rpc_map_buffer_ppgtt, Rpc_unmap_buffer_ppgtt, Rpc_set_tiling); diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index 940ef00403..1af43359b3 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -1612,6 +1612,11 @@ class Gpu::Session_component : public Genode::Session_object return { .value = _vgpu.current_seqno() }; } + bool complete(Gpu::Sequence_number seqno) override + { + return _vgpu.completed_seqno() >= seqno.value; + } + void completion_sigh(Genode::Signal_context_capability sigh) override { _vgpu.completion_sigh(sigh);