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.
This commit is contained in:
Josef Söntgen 2021-09-24 17:22:58 +02:00 committed by Norman Feske
parent e37792ce94
commit 90e151e2c4
4 changed files with 31 additions and 12 deletions

View File

@ -227,7 +227,6 @@ class Drm_call
Gpu::Info_intel const &_gpu_info {
*_gpu_session.attached_info<Gpu::Info_intel>() };
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<Drm_call> _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<Buffer>(id, [&](Buffer &b) {
busy = b.busy;
seqno = b.seqno;
});
} catch (Genode::Id_space<Buffer>::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 */

View File

@ -44,6 +44,9 @@ class Gpu::Session_client : public Genode::Rpc_client<Session>
Genode::size_t size) override {
return call<Rpc_exec_buffer>(id, size); }
bool complete(Sequence_number seqno) override {
return call<Rpc_complete>(seqno); }
void completion_sigh(Genode::Signal_context_capability sigh) override {
call<Rpc_completion_sigh>(sigh); }

View File

@ -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);

View File

@ -1612,6 +1612,11 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
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);