From 7c133add52c641fad641564b2fae9afaea1cf64e Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Tue, 28 Apr 2015 12:56:59 +0200 Subject: [PATCH] hw: acknowledge IRQs via Kernel::ack_irq In the past, when the user blocked for an IRQ signal, the last signal was acknowledged automatically thereby unmasking the IRQ. Now, the signal session got a dedicated RPC for acknowledging IRQs and the HW back-end of that RPC acknowledged the IRQ signal too. This led to the situation that IRQs were unmasked twice. However, drivers expect an interrupt to be unmasked only on the Irq_session::ack_irq and thus IRQ unmasking was moved from Kernel::ack_signal to a dedicated kernel call. Fixes #1493 --- .../src/core/include/kernel/core_interface.h | 11 +++++ repos/base-hw/src/core/include/kernel/irq.h | 41 +++++-------------- .../base-hw/src/core/include/kernel/thread.h | 1 + .../base-hw/src/core/irq_session_component.cc | 5 ++- repos/base-hw/src/core/kernel/thread.cc | 5 +++ 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/repos/base-hw/src/core/include/kernel/core_interface.h b/repos/base-hw/src/core/include/kernel/core_interface.h index 4f49cea583..09b1a19c44 100644 --- a/repos/base-hw/src/core/include/kernel/core_interface.h +++ b/repos/base-hw/src/core/include/kernel/core_interface.h @@ -58,6 +58,7 @@ namespace Kernel constexpr Call_arg call_id_new_irq() { return 32; } constexpr Call_arg call_id_delete_irq() { return 33; } constexpr Call_arg call_id_thread_quota() { return 34; } + constexpr Call_arg call_id_ack_irq() { return 35; } /** * Create a domain @@ -376,6 +377,16 @@ namespace Kernel return call(call_id_new_irq(), (Call_arg) p, irq_nr, signal_context_id); } + /** + * Acknowledge interrupt + * + * \param irq pointer to interrupt kernel object + */ + inline void ack_irq(User_irq * const irq) + { + call(call_id_ack_irq(), (Call_arg) irq); + } + /** * Destruct an interrupt object * diff --git a/repos/base-hw/src/core/include/kernel/irq.h b/repos/base-hw/src/core/include/kernel/irq.h index 83ec010da8..1d753d23b7 100644 --- a/repos/base-hw/src/core/include/kernel/irq.h +++ b/repos/base-hw/src/core/include/kernel/irq.h @@ -90,10 +90,7 @@ class Kernel::Irq : public Object_pool::Item }; -class Kernel::User_irq -: - public Kernel::Irq, - public Signal_ack_handler +class Kernel::User_irq : public Kernel::Irq { private: @@ -104,32 +101,18 @@ class Kernel::User_irq */ static Irq::Pool * _pool(); - - /************************ - ** Signal_ack_handler ** - ************************/ - - void _signal_acknowledged() { enable(); } - public: /** - * Constructor - * - * \param irq_id kernel name of the interrupt + * Construct object that signals interrupt 'irq' via signal 'context' */ - User_irq(unsigned const irq_id, Signal_context &context) - : Irq(irq_id, *_pool()), _context(context) - { - disable(); - _context.ack_handler(this); - } + User_irq(unsigned const irq, Signal_context &context) + : Irq(irq, *_pool()), _context(context) { disable(); } - ~User_irq() - { - _context.ack_handler(nullptr); - disable(); - } + /** + * Destructor + */ + ~User_irq() { disable(); } /** * Handle occurence of the interrupt @@ -141,12 +124,10 @@ class Kernel::User_irq } /** - * Handle occurence of an interrupt - * - * \param irq_id kernel name of targeted interrupt + * Handle occurence of interrupt 'irq' */ - static User_irq * object(unsigned const irq_id) { - return dynamic_cast(_pool()->object(irq_id)); } + static User_irq * object(unsigned const irq) { + return dynamic_cast(_pool()->object(irq)); } }; #endif /* _KERNEL__IRQ_H_ */ diff --git a/repos/base-hw/src/core/include/kernel/thread.h b/repos/base-hw/src/core/include/kernel/thread.h index c802bf84f7..0a4cb75299 100644 --- a/repos/base-hw/src/core/include/kernel/thread.h +++ b/repos/base-hw/src/core/include/kernel/thread.h @@ -245,6 +245,7 @@ class Kernel::Thread void _call_route_thread_event(); void _call_new_irq(); void _call_delete_irq(); + void _call_ack_irq(); /*************************** diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc index 891e7bea53..f50105d438 100644 --- a/repos/base-hw/src/core/irq_session_component.cc +++ b/repos/base-hw/src/core/irq_session_component.cc @@ -31,7 +31,10 @@ unsigned Irq_session_component::_find_irq_number(const char * const args) void Irq_session_component::ack_irq() { - Kernel::ack_signal(_sig_cap.dst()); + using Kernel::User_irq; + if (!_sig_cap.valid()) { return; } + User_irq * const kirq = reinterpret_cast(&_kernel_object); + Kernel::ack_irq(kirq); } diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index 5ef9e6e968..69eb94399b 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -713,6 +713,10 @@ void Thread::_call_new_irq() } +void Thread::_call_ack_irq() { + reinterpret_cast(user_arg_1())->enable(); } + + void Thread::_call_delete_irq() { reinterpret_cast(user_arg_1())->~User_irq(); } @@ -794,6 +798,7 @@ void Thread::_call() case call_id_pause_thread(): _call_pause_thread(); return; case call_id_new_irq(): _call_new_irq(); return; case call_id_delete_irq(): _call_delete_irq(); return; + case call_id_ack_irq(): _call_ack_irq(); return; default: PWRN("%s -> %s: unknown kernel call", pd_label(), label()); _stop();