dde_linux: decouple Lx_kit::Irq and Platform::Device

The Lx_kit::Irq abstraction of DDE Linux was always using the very first
interrupt of a Platform::Device stored in it. Instead of handing over the
platform device it is much more flexible and sane to hand over the actual
interrupt capability.

Ref #3865
This commit is contained in:
Stefan Kalkowski 2020-08-21 13:57:30 +02:00 committed by Norman Feske
parent 73d3698e2f
commit e223be32ce
14 changed files with 59 additions and 379 deletions

View File

@ -1,81 +0,0 @@
/*
* \brief Platform_device implementation for ARM
* \author Sebastian Sumpf
* \date 2016-04-25
*
* Note: Throw away when there exists a plaform device implementation for ARM
* in generic code
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#include <lx_emul/extern_c_begin.h>
#include <lx_emul/printf.h>
#include <lx_emul/extern_c_end.h>
#include <lx_kit/malloc.h>
#include <platform_device/device.h>
#include <irq_session/connection.h>
#include <util/list.h>
#include <util/reconstructible.h>
namespace Platform { struct Device; }
struct Platform::Device : Platform::Abstract_device, Genode::List<Device>::Element
{
Genode::Env &env;
unsigned irq_num;
Genode::Constructible<Genode::Irq_connection> irq_connection;
Device(Genode::Env &env, unsigned irq) : env(env), irq_num(irq) { }
unsigned vendor_id() { return ~0U; }
unsigned device_id() { return ~0U; }
Genode::Irq_session_capability irq(Genode::uint8_t) override
{
irq_connection.construct(env, irq_num);
return irq_connection->cap();
}
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t, Genode::size_t) override
{
lx_printf("%s: not implemented\n", __PRETTY_FUNCTION__);
return Genode::Io_mem_session_capability();
}
static Genode::List<Device> &list()
{
static Genode::List<Device> l;
return l;
}
static Device &create(Genode::Env &env, unsigned irq_num)
{
Device *d;
for (d = list().first(); d; d = d->next())
if (d->irq_num == irq_num)
return *d;
d = new (Lx::Malloc::mem()) Device(env, irq_num);
list().insert(d);
return *d;
}
};
#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */

View File

@ -15,6 +15,7 @@
/* Genode includes */ /* Genode includes */
#include <base/attached_io_mem_dataspace.h> #include <base/attached_io_mem_dataspace.h>
#include <irq_session/connection.h>
/* local includes */ /* local includes */
#include <driver.h> #include <driver.h>
@ -564,8 +565,10 @@ void irq_set_chained_handler_and_data(unsigned int irq,
irqsteer_irq_desc.irq_data.chip = irqsteer_chip; irqsteer_irq_desc.irq_data.chip = irqsteer_chip;
irqsteer_irq_desc.handle_irq = handle; irqsteer_irq_desc.handle_irq = handle;
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
irq, irqsteer_irq_handler, nullptr, nullptr); Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq,
irqsteer_irq_handler, nullptr, nullptr);
} }
@ -583,8 +586,9 @@ int devm_request_threaded_irq(struct device *dev, unsigned int irq,
return -1; return -1;
} }
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
irq, handler, dev_id, thread_fn); Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id, thread_fn);
return 0; return 0;
} }
@ -885,9 +889,11 @@ int devm_request_irq(struct device *dev, unsigned int irq,
irqsteer_handler[irq] = handler; irqsteer_handler[irq] = handler;
irqsteer_dev_id[irq] = dev_id; irqsteer_dev_id[irq] = dev_id;
enable_irq(irq); enable_irq(irq);
} else } else {
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
irq, handler, dev_id); Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id);
}
return 0; return 0;
} }

View File

@ -166,7 +166,7 @@ void Framebuffer::Driver::finish_initialization()
void Framebuffer::Driver::_poll() void Framebuffer::Driver::_poll()
{ {
Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) lx_drm_device->pdev->bus; Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) lx_drm_device->pdev->bus;
Lx::Irq::irq().inject_irq(pci_dev->client()); Lx::Irq::irq().inject_irq(pci_dev->irq);
} }
@ -1095,7 +1095,7 @@ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
{ {
struct drm_device * drm_dev = (struct drm_device*) dev; struct drm_device * drm_dev = (struct drm_device*) dev;
Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) drm_dev->pdev->bus; Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) drm_dev->pdev->bus;
Lx::Irq::irq().request_irq(pci_dev->client(), irq, handler, dev); Lx::Irq::irq().request_irq(pci_dev->client().irq(0), irq, handler, dev);
return 0; return 0;
} }

View File

@ -20,7 +20,7 @@
#include <base/env.h> #include <base/env.h>
#include <base/snprintf.h> #include <base/snprintf.h>
#include <gpio_session/connection.h> #include <gpio_session/connection.h>
#include <irq_session/client.h> #include <irq_session/connection.h>
#include <component.h> #include <component.h>
#include <lx_emul.h> #include <lx_emul.h>
@ -586,7 +586,9 @@ int platform_get_irq(struct platform_device * d, unsigned int i)
int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
{ {
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), irq, handler, dev_id); Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id);
return 0; return 0;
} }

View File

@ -1,81 +0,0 @@
/*
* \brief Platform_device implementation for ARM
* \author Sebastian Sumpf
* \date 2016-04-25
*
* Note: Throw away when there exists a plaform device implementation for ARM
* in generic code
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#include <lx_emul/extern_c_begin.h>
#include <lx_emul/printf.h>
#include <lx_emul/extern_c_end.h>
#include <lx_kit/malloc.h>
#include <platform_device/device.h>
#include <irq_session/connection.h>
#include <util/list.h>
#include <util/reconstructible.h>
namespace Platform { struct Device; }
struct Platform::Device : Platform::Abstract_device, Genode::List<Device>::Element
{
Genode::Env &env;
unsigned irq_num;
Genode::Constructible<Genode::Irq_connection> irq_connection;
Device(Genode::Env &env, unsigned irq) : env(env), irq_num(irq) { }
unsigned vendor_id() { return ~0U; }
unsigned device_id() { return ~0U; }
Genode::Irq_session_capability irq(Genode::uint8_t) override
{
irq_connection.construct(env, irq_num);
return irq_connection->cap();
}
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t, Genode::size_t) override
{
lx_printf("%s: not implemented\n", __PRETTY_FUNCTION__);
return Genode::Io_mem_session_capability();
}
static Genode::List<Device> &list()
{
static Genode::List<Device> l;
return l;
}
static Device &create(Genode::Env &env, unsigned irq_num)
{
Device *d;
for (d = list().first(); d; d = d->next())
if (d->irq_num == irq_num)
return *d;
d = new (Lx::Malloc::mem()) Device(env, irq_num);
list().insert(d);
return *d;
}
};
#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */

View File

@ -1,81 +0,0 @@
/*
* \brief Platform_device implementation for ARM
* \author Sebastian Sumpf
* \date 2016-04-25
*
* Note: Throw away when there exists a plaform device implementation for ARM
* in generic code
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#include <lx_emul/extern_c_begin.h>
#include <lx_emul/printf.h>
#include <lx_emul/extern_c_end.h>
#include <lx_kit/malloc.h>
#include <platform_device/device.h>
#include <irq_session/connection.h>
#include <util/list.h>
#include <util/reconstructible.h>
namespace Platform { struct Device; }
struct Platform::Device : Platform::Abstract_device, Genode::List<Device>::Element
{
Genode::Env &env;
unsigned irq_num;
Genode::Constructible<Genode::Irq_connection> irq_connection;
Device(Genode::Env &env, unsigned irq) : env(env), irq_num(irq) { }
unsigned vendor_id() { return ~0U; }
unsigned device_id() { return ~0U; }
Genode::Irq_session_capability irq(Genode::uint8_t) override
{
irq_connection.construct(env, irq_num);
return irq_connection->cap();
}
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t, Genode::size_t) override
{
lx_printf("%s: not implemented\n", __PRETTY_FUNCTION__);
return Genode::Io_mem_session_capability();
}
static Genode::List<Device> &list()
{
static Genode::List<Device> l;
return l;
}
static Device &create(Genode::Env &env, unsigned irq_num)
{
Device *d;
for (d = list().first(); d; d = d->next())
if (d->irq_num == irq_num)
return *d;
d = new (Lx::Malloc::mem()) Device(env, irq_num);
list().insert(d);
return *d;
}
};
#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */

View File

@ -11,8 +11,10 @@
* version 2. * version 2.
*/ */
#include <lx_emul/irq.h>
#include <base/env.h> #include <base/env.h>
#include <irq_session/connection.h>
#include <lx_emul/irq.h>
#include <lx_kit/backend_alloc.h> #include <lx_kit/backend_alloc.h>
#include <lx_kit/env.h> #include <lx_kit/env.h>
#include <lx_kit/irq.h> #include <lx_kit/irq.h>
@ -45,7 +47,9 @@ void Lx::backend_free(Genode::Ram_dataspace_capability cap) {
extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev) const char *name, void *dev)
{ {
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), irq, handler, dev); Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev);
return 0; return 0;
} }

View File

@ -186,7 +186,7 @@ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
{ {
for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next()) for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next())
if (pci_dev->irq == irq) { if (pci_dev->irq == irq) {
Lx::Irq::irq().request_irq(pci_dev->client(), irq, handler, dev); Lx::Irq::irq().request_irq(pci_dev->client().irq(0), irq, handler, dev);
return 0; return 0;
} }

View File

@ -12,6 +12,7 @@
*/ */
#include <base/attached_io_mem_dataspace.h> #include <base/attached_io_mem_dataspace.h>
#include <irq_session/connection.h>
#include <base/env.h> #include <base/env.h>
#include <lx_emul.h> #include <lx_emul.h>
@ -19,6 +20,7 @@
#include <lx_kit/backend_alloc.h> #include <lx_kit/backend_alloc.h>
#include <lx_kit/env.h> #include <lx_kit/env.h>
#include <lx_kit/irq.h> #include <lx_kit/irq.h>
#include <lx_kit/malloc.h>
/**************************** /****************************
@ -48,7 +50,10 @@ void Lx::backend_free(Genode::Ram_dataspace_capability cap) {
extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev) const char *name, void *dev)
{ {
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), irq, handler, dev); Genode::Irq_connection * irq_con =
new(Lx::Malloc::mem())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev);
return 0; return 0;
} }
@ -56,7 +61,10 @@ extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned lon
int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
{ {
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), irq, handler, dev_id); Genode::Irq_connection * irq_con =
new(Lx::Malloc::mem())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id);
return 0; return 0;
} }

View File

@ -1,81 +0,0 @@
/*
* \brief Platform_device implementation for ARM
* \author Sebastian Sumpf
* \date 2016-04-25
*
* Note: Throw away when there exists a plaform device implementation for ARM
* in generic code
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#include <lx_emul/extern_c_begin.h>
#include <lx_emul/printf.h>
#include <lx_emul/extern_c_end.h>
#include <lx_kit/malloc.h>
#include <platform_device/device.h>
#include <irq_session/connection.h>
#include <util/list.h>
#include <util/reconstructible.h>
namespace Platform { struct Device; }
struct Platform::Device : Platform::Abstract_device, Genode::List<Device>::Element
{
Genode::Env &env;
unsigned irq_num;
Genode::Constructible<Genode::Irq_connection> irq_connection;
Device(Genode::Env &env, unsigned irq) : env(env), irq_num(irq) { }
unsigned vendor_id() { return ~0U; }
unsigned device_id() { return ~0U; }
Genode::Irq_session_capability irq(Genode::uint8_t) override
{
irq_connection.construct(env, irq_num);
return irq_connection->cap();
}
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t, Genode::size_t) override
{
lx_printf("%s: not implemented\n", __PRETTY_FUNCTION__);
return Genode::Io_mem_session_capability();
}
static Genode::List<Device> &list()
{
static Genode::List<Device> l;
return l;
}
static Device &create(Genode::Env &env, unsigned irq_num)
{
Device *d;
for (d = list().first(); d; d = d->next())
if (d->irq_num == irq_num)
return *d;
d = new (Lx::Malloc::mem()) Device(env, irq_num);
list().insert(d);
return *d;
}
};
#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */

View File

@ -188,12 +188,10 @@ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
{ {
for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next()) for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next())
if (pci_dev->irq == irq) { if (pci_dev->irq == irq) {
{
Genode::Irq_session_client is(pci_dev->client().irq(0)); Genode::Irq_session_client is(pci_dev->client().irq(0));
if ((is.info().type != Genode::Irq_session::Info::MSI) if ((is.info().type != Genode::Irq_session::Info::MSI)
&& !flags) return 1; && !flags) return 1;
} Lx::Irq::irq().request_irq(is.rpc_cap(), irq, handler, dev);
Lx::Irq::irq().request_irq(pci_dev->client(), irq, handler, dev);
return 0; return 0;
} }

View File

@ -32,11 +32,12 @@ class Lx::Irq
/** /**
* Request an IRQ * Request an IRQ
*/ */
virtual void request_irq(Platform::Device &dev, unsigned int irq, virtual void request_irq(Genode::Irq_session_capability cap,
unsigned int irq,
irq_handler_t handler, void *dev_id, irq_handler_t handler, void *dev_id,
irq_handler_t thread_fn = 0) = 0; irq_handler_t thread_fn = 0) = 0;
virtual void inject_irq(Platform::Device &dev) = 0; virtual void inject_irq(unsigned int irq) = 0;
/** /**
* Disable an IRQ * Disable an IRQ

View File

@ -1333,7 +1333,7 @@ int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name, void *dev) unsigned long flags, const char *name, void *dev)
{ {
Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first();
Lx::Irq::irq().request_irq(pci_dev->client(), irq, handler, dev); Lx::Irq::irq().request_irq(pci_dev->client().irq(0), irq, handler, dev);
return 0; return 0;
} }
@ -1344,7 +1344,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
void *dev) void *dev)
{ {
Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first();
Lx::Irq::irq().request_irq(pci_dev->client(), irq, handler, dev, thread_fn); Lx::Irq::irq().request_irq(pci_dev->client().irq(0), irq, handler, dev, thread_fn);
return 0; return 0;
} }

View File

@ -41,12 +41,10 @@ class Lx_kit::Irq : public Lx::Irq
{ {
char name[16]; char name[16];
Name_composer(Platform::Device &device) Name_composer(unsigned number)
{ {
Genode::snprintf(name, sizeof(name), Genode::snprintf(name, sizeof(name),
"irq_%02x:%02x", "irq_%02x", number);
device.vendor_id(),
device.device_id());
} }
}; };
@ -99,7 +97,6 @@ class Lx_kit::Irq : public Lx::Irq
private: private:
Name_composer _name; Name_composer _name;
Platform::Device &_dev;
unsigned int _irq; unsigned int _irq;
Genode::Irq_session_client _irq_sess; Genode::Irq_session_client _irq_sess;
Lx_kit::List<Handler> _handler; Lx_kit::List<Handler> _handler;
@ -125,13 +122,12 @@ class Lx_kit::Irq : public Lx::Irq
* Constructor * Constructor
*/ */
Context(Genode::Entrypoint &ep, Context(Genode::Entrypoint &ep,
Platform::Device &dev, Genode::Irq_session_capability cap,
unsigned int irq) unsigned int irq)
: :
_name(dev), _name(irq),
_dev(dev),
_irq(irq), _irq(irq),
_irq_sess(dev.irq(0)), _irq_sess(cap),
_task(_run_irq, this, _name.name, Lx::Task::PRIORITY_3, Lx::scheduler()), _task(_run_irq, this, _name.name, Lx::Task::PRIORITY_3, Lx::scheduler()),
_irq_enabled(true), _irq_enabled(true),
_irq_ack_pending(false), _irq_ack_pending(false),
@ -184,9 +180,6 @@ class Lx_kit::Irq : public Lx::Irq
*/ */
void add_handler(Handler *h) { _handler.append(h); } void add_handler(Handler *h) { _handler.append(h); }
bool device(Platform::Device &dev) {
return (&dev == &_dev); }
bool irq(unsigned int irq) { bool irq(unsigned int irq) {
return (irq == _irq); } return (irq == _irq); }
@ -219,16 +212,6 @@ class Lx_kit::Irq : public Lx::Irq
Context_slab _context_alloc; Context_slab _context_alloc;
Handler_slab _handler_alloc; Handler_slab _handler_alloc;
/**
* Find context for given device
*/
Context *_find_context(Platform::Device &dev)
{
for (Context *i = _list.first(); i; i = i->next())
if (i->device(dev)) return i;
return nullptr;
}
/** /**
* Find context for given IRQ number * Find context for given IRQ number
*/ */
@ -256,15 +239,17 @@ class Lx_kit::Irq : public Lx::Irq
** Lx::Irq interface ** ** Lx::Irq interface **
***********************/ ***********************/
void request_irq(Platform::Device &dev, unsigned int irq, void request_irq(Genode::Irq_session_capability cap,
irq_handler_t handler, void *dev_id, unsigned int irq,
irq_handler_t handler,
void * dev_id,
irq_handler_t thread_fn = 0) override irq_handler_t thread_fn = 0) override
{ {
Context *ctx = _find_context(dev); Context *ctx = _find_context(irq);
/* if this IRQ is not registered */ /* if this IRQ is not registered */
if (!ctx) { if (!ctx) {
ctx = new (&_context_alloc) Context(_ep, dev, irq); ctx = new (&_context_alloc) Context(_ep, cap, irq);
_list.insert(ctx); _list.insert(ctx);
} }
@ -274,9 +259,9 @@ class Lx_kit::Irq : public Lx::Irq
ctx->add_handler(h); ctx->add_handler(h);
} }
void inject_irq(Platform::Device &dev) void inject_irq(unsigned int irq)
{ {
Context *ctx = _find_context(dev); Context *ctx = _find_context(irq);
if (ctx) ctx->unblock(); if (ctx) ctx->unblock();
} }