From fa124dd3405767a8c56f49664b26c1a8240d6804 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Fri, 30 Sep 2022 17:15:32 +0200 Subject: [PATCH] lx_kit: do not close/re-open IRQ session Instead of dynamically close/open IRQ session whenever an IRQ gots masked/unmasked, track the state internally and resp. deliver an interrupt delayed. --- repos/dde_linux/src/include/lx_kit/device.h | 3 ++ .../src/lib/lx_emul/spec/x86/irqchip.c | 1 + repos/dde_linux/src/lib/lx_kit/device.cc | 35 ++++++++++++------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/repos/dde_linux/src/include/lx_kit/device.h b/repos/dde_linux/src/include/lx_kit/device.h index aa6f1fa713..593b7b25be 100644 --- a/repos/dde_linux/src/include/lx_kit/device.h +++ b/repos/dde_linux/src/include/lx_kit/device.h @@ -65,11 +65,14 @@ class Lx_kit::Device : List::Element Index idx; unsigned number; Io_signal_handler handler; + bool masked { true }; + bool occured { false }; Constructible session {}; Irq(Entrypoint & ep, unsigned idx, unsigned number); + void _handle(); void handle(); }; diff --git a/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c b/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c index 707317e849..06916672a7 100644 --- a/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c +++ b/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c @@ -60,6 +60,7 @@ int lx_emul_irq_task_function(void * data) lx_emul_irq_last()); } else { generic_handle_irq(irq); + lx_emul_irq_eoi(irq); } irq_exit(); diff --git a/repos/dde_linux/src/lib/lx_kit/device.cc b/repos/dde_linux/src/lib/lx_kit/device.cc index de52007ed2..e3b2928ac8 100644 --- a/repos/dde_linux/src/lib/lx_kit/device.cc +++ b/repos/dde_linux/src/lib/lx_kit/device.cc @@ -42,11 +42,22 @@ bool Device::Io_port::match(uint16_t addr) ** Device::Irq** ****************/ +void Device::Irq::_handle() +{ + handle(); + env().scheduler.schedule(); +} + + void Device::Irq::handle() { + occured = true; + + if (masked) + return; + env().last_irq = number; env().scheduler.unblock_irq_handler(); - env().scheduler.schedule(); } @@ -54,7 +65,7 @@ Device::Irq::Irq(Entrypoint & ep, unsigned idx, unsigned number) : idx{idx}, number(number), - handler(ep, *this, &Irq::handle) { } + handler(ep, *this, &Irq::_handle) { } /************ @@ -139,12 +150,14 @@ bool Device::irq_unmask(unsigned number) ret = true; enable(); - if (irq.session.constructed()) - return; + if (!irq.session.constructed()) { + irq.session.construct(*_pdev, irq.idx); + irq.session->sigh_omit_initial_signal(irq.handler); + irq.session->ack(); + } - irq.session.construct(*_pdev, irq.idx); - irq.session->sigh_omit_initial_signal(irq.handler); - irq.session->ack(); + irq.masked = false; + if (irq.occured) irq.handle(); }); return ret; @@ -157,10 +170,7 @@ void Device::irq_mask(unsigned number) return; for_each_irq([&] (Irq & irq) { - if (irq.number != number) - return; - irq.session.destruct(); - }); + if (irq.number == number) irq.masked = true; }); } @@ -171,8 +181,9 @@ void Device::irq_ack(unsigned number) return; for_each_irq([&] (Irq & irq) { - if (irq.number != number || !irq.session.constructed()) + if (irq.number != number || !irq.occured || !irq.session.constructed()) return; + irq.occured = false; irq.session->ack(); }); }