diff --git a/repos/dde_linux/src/lib/usb/arm/platform_arndale/platform.cc b/repos/dde_linux/src/lib/usb/arm/platform_arndale/platform.cc index 4a67a4764..c6296ce1c 100644 --- a/repos/dde_linux/src/lib/usb/arm/platform_arndale/platform.cc +++ b/repos/dde_linux/src/lib/usb/arm/platform_arndale/platform.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include /* Emulation */ @@ -363,3 +364,15 @@ void platform_hcd_init(Services *services) if (services->xhci) xhci_setup(services); } + + +Genode::Irq_session_capability platform_irq_activate(int irq) +{ + try { + Genode::Irq_connection conn(irq); + conn.on_destruction(Genode::Irq_connection::KEEP_OPEN); + return conn; + } catch (...) { } + + return Genode::Irq_session_capability(); +} diff --git a/repos/dde_linux/src/lib/usb/arm/platform_panda/platform.cc b/repos/dde_linux/src/lib/usb/arm/platform_panda/platform.cc index 890283b91..896c9294a 100644 --- a/repos/dde_linux/src/lib/usb/arm/platform_panda/platform.cc +++ b/repos/dde_linux/src/lib/usb/arm/platform_panda/platform.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -320,3 +321,14 @@ void platform_hcd_init(Services *services) platform_device_register(pdev); } + +Genode::Irq_session_capability platform_irq_activate(int irq) +{ + try { + Genode::Irq_connection conn(irq); + conn.on_destruction(Genode::Irq_connection::KEEP_OPEN); + return conn; + } catch (...) { } + + return Genode::Irq_session_capability(); +} diff --git a/repos/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc b/repos/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc index ae7654f00..6cacb6dcc 100644 --- a/repos/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc +++ b/repos/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc @@ -13,6 +13,7 @@ /* Genode includes */ #include +#include #include #include @@ -228,3 +229,15 @@ void platform_hcd_init(Services *services) platform_device_register(pdev); } + + +Genode::Irq_session_capability platform_irq_activate(int irq) +{ + try { + Genode::Irq_connection conn(irq); + conn.on_destruction(Genode::Irq_connection::KEEP_OPEN); + return conn; + } catch (...) { } + + return Genode::Irq_session_capability(); +} diff --git a/repos/dde_linux/src/lib/usb/include/platform.h b/repos/dde_linux/src/lib/usb/include/platform.h index ef82c1fce..a96a2e441 100644 --- a/repos/dde_linux/src/lib/usb/include/platform.h +++ b/repos/dde_linux/src/lib/usb/include/platform.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include struct Services { @@ -111,5 +113,6 @@ struct Services }; void platform_hcd_init(Services *services); +Genode::Irq_session_capability platform_irq_activate(int irq); #endif /* _PLATFORM_H_ */ diff --git a/repos/dde_linux/src/lib/usb/pci_driver.cc b/repos/dde_linux/src/lib/usb/pci_driver.cc index 09e0508a1..834a54ef7 100644 --- a/repos/dde_linux/src/lib/usb/pci_driver.cc +++ b/repos/dde_linux/src/lib/usb/pci_driver.cc @@ -11,9 +11,13 @@ * under the terms of the GNU General Public License version 2. */ -/* Genode inludes */ +/* Genode base includes */ #include #include +#include + +/* Genode os includes */ +#include #include #include @@ -29,7 +33,7 @@ struct bus_type pci_bus_type; /** * Scan PCI bus and probe for HCDs */ -class Pci_driver +class Pci_driver : public Genode::List::Element { private: @@ -53,9 +57,12 @@ class Pci_driver { using namespace Pci; - _dev = new (Genode::env()->heap()) pci_dev; Device_client client(_cap); + uint8_t bus, dev, func; + client.bus_address(&bus, &dev, &func); + _dev = new (Genode::env()->heap()) pci_dev; + _dev->devfn = ((uint16_t)bus << 8) | (0xff & PCI_DEVFN(dev, func)); _dev->vendor = client.vendor_id(); _dev->device = client.device_id(); _dev->class_ = client.class_code(); @@ -105,6 +112,8 @@ class Pci_driver /* enable bus master */ cmd |= 0x4; client.config_write(CMD, cmd, Device::ACCESS_16BIT); + + _drivers().insert(this); } /** @@ -135,6 +144,12 @@ class Pci_driver } } + static Genode::List & _drivers() + { + static Genode::List _list; + return _list; + } + public: Pci_driver(pci_driver *drv, Pci::Device_capability cap, @@ -157,6 +172,8 @@ class Pci_driver dde_kit_release_io(r->start, (r->end - r->start) + 1); } + _drivers().remove(this); + destroy(Genode::env()->heap(), _dev); } @@ -176,8 +193,20 @@ class Pci_driver Pci::Device_client client(_cap); client.config_write(devfn, val, _access_size(val)); } -}; + static Genode::Irq_session_capability irq_cap(unsigned irq) + { + for (Pci_driver *d = _drivers().first(); d; d = d->next()) { + if (d->_dev && d->_dev->irq != irq) + continue; + + Pci::Device_client client(d->_cap); + return client.irq(0); + } + + return Genode::Irq_session_capability(); + } +}; /******************************** ** Backend memory definitions ** @@ -401,3 +430,13 @@ void Backend_memory::free(Genode::Ram_dataspace_capability cap) memory_pool.remove_locked(o); destroy(env()->heap(), o); } + + +/***************************************** + ** Platform specific irq cap discovery ** + *****************************************/ + +Genode::Irq_session_capability platform_irq_activate(int irq) +{ + return Pci_driver::irq_cap(irq); +} diff --git a/repos/dde_linux/src/lib/usb/signal/irq.cc b/repos/dde_linux/src/lib/usb/signal/irq.cc index 18aebba4f..83211ef29 100644 --- a/repos/dde_linux/src/lib/usb/signal/irq.cc +++ b/repos/dde_linux/src/lib/usb/signal/irq.cc @@ -12,19 +12,17 @@ */ #include +#include #include #include #include -extern "C" { -#include -} +#include + -#include /* our local incarnation of sender and receiver */ static Signal_helper *_signal = 0; -static Genode::Lock _irq_sync(Genode::Lock::LOCKED); /** * This contains the Linux-driver handlers @@ -52,6 +50,8 @@ class Irq_context : public Genode::List::Element unsigned int _irq; /* IRQ number */ Genode::List _handler_list; /* List of registered handlers */ Genode::Signal_rpc_member _dispatcher; + Genode::Irq_session_capability _irq_cap; + Genode::Irq_session_client _irq_client; static Genode::List *_list() { @@ -72,26 +72,6 @@ class Irq_context : public Genode::List::Element return 0; } - /* called by the DDE kit upon IRQ */ - static void _dde_handler(void *irq) - { - /* - * Make sure there is only one interrupt handled at a time, since dde_kit - * will use one thread per IRQ - */ - static Genode::Lock handler_lock; - Genode::Lock::Guard guard(handler_lock); - - Irq_context *ctx = static_cast(irq); - - /* set context & submit signal */ - _signal->sender().context(ctx->_dispatcher); - _signal->sender().submit(); - - /* wait for interrupt to get acked at device side */ - _irq_sync.lock(); - } - /** * Call one IRQ handler */ @@ -129,8 +109,8 @@ class Irq_context : public Genode::List::Element break; } - /* interrupt should be acked at device now */ - _irq_sync.unlock(); + /* ack interrupt */ + _irq_client.ack_irq(); if (handled) Routine::schedule_all(); @@ -144,14 +124,18 @@ class Irq_context : public Genode::List::Element Irq_context(unsigned int irq) : _irq(irq), - _dispatcher(_signal->ep(), *this, &Irq_context::_handle) + _dispatcher(_signal->ep(), *this, &Irq_context::_handle), + _irq_cap(platform_irq_activate(_irq)), + _irq_client(_irq_cap) { - /* register at DDE (shared) */ - int ret = dde_kit_interrupt_attach(_irq, 0, 0, _dde_handler, this); - if (ret) - PERR("Interrupt attach return %d for IRQ %u", ret, irq); + if (!_irq_cap.valid()) { + PERR("Interrupt %d attach failed", irq); + return; + } + + _irq_client.sigh(_dispatcher); + _irq_client.ack_irq(); - dde_kit_interrupt_enable(_irq); _list()->insert(this); }