mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
platform_drv: consider IRQ type, mode, polarity
Parse the devices ROM for additional interrupt information, and pass them to the IRQ connection when needed. Fix genodelabs/genode#4497
This commit is contained in:
parent
de7fdd3e1a
commit
6b92006565
@ -75,7 +75,12 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
struct Irq : List_model<Irq>::Element
|
||||
{
|
||||
unsigned number;
|
||||
enum Type { LEGACY, MSI, MSIX };
|
||||
|
||||
unsigned number;
|
||||
Type type { LEGACY };
|
||||
Irq_session::Polarity polarity { Irq_session::POLARITY_UNCHANGED };
|
||||
Irq_session::Trigger mode { Irq_session::TRIGGER_UNCHANGED };
|
||||
|
||||
Irq(unsigned number) : number(number) {}
|
||||
};
|
||||
@ -150,7 +155,7 @@ class Driver::Device : private List_model<Device>::Element
|
||||
{
|
||||
unsigned idx = 0;
|
||||
_irq_list.for_each([&] (Irq const & irq) {
|
||||
fn(idx++, irq.number); });
|
||||
fn(idx++, irq.number, irq.type, irq.polarity, irq.mode, 0); });
|
||||
}
|
||||
|
||||
template <typename FN> void for_each_io_mem(FN const & fn)
|
||||
@ -258,8 +263,22 @@ struct Driver::Irq_update_policy : Genode::List_model<Device::Irq>::Update_polic
|
||||
|
||||
Element & create_element(Genode::Xml_node node)
|
||||
{
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
return *(new (alloc) Element(number));
|
||||
unsigned number = node.attribute_value<unsigned>("number", 0);
|
||||
Element & elem = *(new (alloc) Element(number));
|
||||
|
||||
String<16> polarity = node.attribute_value("polarity", String<16>());
|
||||
String<16> mode = node.attribute_value("mode", String<16>());
|
||||
String<16> type = node.attribute_value("type", String<16>());
|
||||
if (polarity.valid())
|
||||
elem.polarity = (polarity == "high") ? Irq_session::POLARITY_HIGH
|
||||
: Irq_session::POLARITY_LOW;
|
||||
if (mode.valid())
|
||||
elem.mode = (mode == "edge") ? Irq_session::TRIGGER_EDGE
|
||||
: Irq_session::TRIGGER_LEVEL;
|
||||
if (type.valid())
|
||||
elem.type = (type == "msi-x") ? Element::MSIX : Element::MSI;
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
void update_element(Element &, Genode::Xml_node) {}
|
||||
|
@ -71,8 +71,21 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx)
|
||||
if (irq.idx != idx)
|
||||
return;
|
||||
|
||||
if (!irq.irq.constructed())
|
||||
irq.irq.construct(_session.env(), irq.number);
|
||||
if (!irq.irq.constructed()) {
|
||||
|
||||
/*
|
||||
* Unfortunately, we have to deliver the PCI config space address
|
||||
* to the IRQ session for working MSI(-x) on NOVA. It is used
|
||||
* for IOMMU configuration as some kind of access control
|
||||
*
|
||||
* Once, the IOMMU support is solved kernel-independent, this
|
||||
* attribute has to be removed from the IRQs
|
||||
*/
|
||||
addr_t pci_cfg_addr = (irq.type != Device::Irq::LEGACY)
|
||||
? irq.pci_config_addr : 0;
|
||||
irq.irq.construct(_session.env(), irq.number, irq.mode, irq.polarity,
|
||||
pci_cfg_addr);
|
||||
}
|
||||
|
||||
cap = irq.irq->cap();
|
||||
});
|
||||
@ -120,13 +133,19 @@ Device_component::Device_component(Registry<Device_component> & registry,
|
||||
*/
|
||||
|
||||
try {
|
||||
device.for_each_irq([&] (unsigned idx, unsigned nr)
|
||||
device.for_each_irq([&] (unsigned idx,
|
||||
unsigned nr,
|
||||
Device::Irq::Type type,
|
||||
Irq_session::Polarity polarity,
|
||||
Irq_session::Trigger mode,
|
||||
addr_t pci_cfg_addr)
|
||||
{
|
||||
session.ram_quota_guard().withdraw(Ram_quota{Irq_session::RAM_QUOTA});
|
||||
_ram_quota += Irq_session::RAM_QUOTA;
|
||||
session.cap_quota_guard().withdraw(Cap_quota{Irq_session::CAP_QUOTA});
|
||||
_cap_quota += Irq_session::CAP_QUOTA;
|
||||
new (session.heap()) Irq(_irq_registry, idx, nr);
|
||||
new (session.heap()) Irq(_irq_registry, idx, nr, type,
|
||||
polarity, mode, pci_cfg_addr);
|
||||
});
|
||||
|
||||
device.for_each_io_mem([&] (unsigned idx, Range range)
|
||||
|
@ -40,14 +40,24 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned number;
|
||||
Device::Irq::Type type;
|
||||
Irq_session::Polarity polarity;
|
||||
Irq_session::Trigger mode;
|
||||
addr_t pci_config_addr;
|
||||
Constructible<Irq_connection> irq {};
|
||||
|
||||
Irq(Registry<Irq> & registry,
|
||||
unsigned idx,
|
||||
unsigned number)
|
||||
Irq(Registry<Irq> & registry,
|
||||
unsigned idx,
|
||||
unsigned number,
|
||||
Device::Irq::Type type,
|
||||
Irq_session::Polarity polarity,
|
||||
Irq_session::Trigger mode,
|
||||
addr_t pci_config_addr)
|
||||
:
|
||||
Registry<Irq>::Element(registry, *this),
|
||||
idx(idx), number(number) {}
|
||||
idx(idx), number(number), type(type),
|
||||
polarity(polarity), mode(mode),
|
||||
pci_config_addr(pci_config_addr) {}
|
||||
};
|
||||
|
||||
struct Io_mem : Registry<Io_mem>::Element
|
||||
|
Loading…
Reference in New Issue
Block a user