mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
base: add irq_type session argument
By adding the `irq_type` argument, one can explicitly specify whether to use LEGACY, MSI or MSI-X interrupts. We formerly used the `device_phys_config` to implicitly select MSI, however, with the addition of IOMMU support to the platform driver there is at least one instance where we need an MSI for a non-PCI device. Yet, by adding another session argument to the Irq session, we exceed the character limit for session args. Since not all arguments are relevant for LEGACY interrupts resp. MSI, we can split the Irq_connection constructor to handle the two cases separately and omit unneeded arguments. genodelabs/genode#5002
This commit is contained in:
parent
a80464299a
commit
eefaa07024
@ -16,6 +16,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <irq_root.h>
|
||||
#include <irq_args.h>
|
||||
#include <util.h>
|
||||
|
||||
/* L4/Fiasco includes */
|
||||
@ -125,7 +126,9 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
_irq_alloc(irq_alloc),
|
||||
_irq_object(_irq_number)
|
||||
{
|
||||
long msi = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
Irq_args irq_args(args);
|
||||
bool msi { irq_args.type() != Irq_session::TYPE_LEGACY };
|
||||
|
||||
if (msi)
|
||||
throw Service_denied();
|
||||
|
||||
|
@ -193,7 +193,8 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
_irq_number((unsigned)Arg_string::find_arg(args, "irq_number").long_value(-1)),
|
||||
_irq_alloc(irq_alloc), _irq_object()
|
||||
{
|
||||
long const msi = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
Irq_args const irq_args(args);
|
||||
bool msi { irq_args.type() != TYPE_LEGACY };
|
||||
|
||||
if (msi) {
|
||||
if (msi_alloc().get(_irq_number, 1)) {
|
||||
@ -208,8 +209,6 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
}
|
||||
}
|
||||
|
||||
Irq_args const irq_args(args);
|
||||
|
||||
if (_irq_object.associate(_irq_number, msi, irq_args.trigger(),
|
||||
irq_args.polarity()))
|
||||
return;
|
||||
|
@ -69,10 +69,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
_irq_number((unsigned)Platform::irq(_irq_args.irq_number())),
|
||||
_irq_alloc(irq_alloc), _kobj(), _is_msi(false), _address(0), _value(0)
|
||||
{
|
||||
long const mmconf =
|
||||
Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
|
||||
if (mmconf) {
|
||||
if (_irq_args.type() != Irq_session::TYPE_LEGACY) {
|
||||
_is_msi = Platform::alloc_msi_vector(_address, _value);
|
||||
if (!_is_msi)
|
||||
throw Service_denied();
|
||||
|
@ -115,7 +115,7 @@ void Irq_object::sigh(Signal_context_capability cap)
|
||||
|
||||
/* associate GSI or MSI to device belonging to device_phys */
|
||||
bool ok = false;
|
||||
if (_device_phys)
|
||||
if (_device_phys || (_msi_addr && _msi_data))
|
||||
ok = associate_msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
|
||||
else
|
||||
ok = associate_gsi(irq_sel(), cap, _gsi_flags);
|
||||
@ -173,10 +173,10 @@ void Irq_object::start(unsigned irq, addr_t const device_phys, Irq_args const &i
|
||||
|
||||
/* associate GSI or MSI to device belonging to device_phys */
|
||||
bool ok = false;
|
||||
if (device_phys)
|
||||
ok = associate_msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
|
||||
else
|
||||
if (irq_args.type() == Irq_session::TYPE_LEGACY)
|
||||
ok = associate_gsi(irq_sel(), _sigh_cap, _gsi_flags);
|
||||
else
|
||||
ok = associate_msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
|
||||
|
||||
if (!ok)
|
||||
throw Service_denied();
|
||||
@ -217,8 +217,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
Irq_args const irq_args(args);
|
||||
|
||||
long irq_number = irq_args.irq_number();
|
||||
long device_phys = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
if (device_phys) {
|
||||
if (irq_args.type() != Irq_session::TYPE_LEGACY) {
|
||||
|
||||
if ((unsigned long)irq_number >= kernel_hip().sel_gsi)
|
||||
throw Service_denied();
|
||||
@ -236,6 +235,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
|
||||
_irq_number = (unsigned)irq_number;
|
||||
|
||||
long device_phys = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
_irq_object.start(_irq_number, device_phys, irq_args);
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <irq_root.h>
|
||||
#include <irq_args.h>
|
||||
#include <irq_session_component.h>
|
||||
|
||||
/* base-internal includes */
|
||||
@ -133,7 +134,8 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
_irq_alloc(irq_alloc),
|
||||
_irq_object(_irq_number)
|
||||
{
|
||||
long msi = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
Irq_args irq_args(args);
|
||||
bool msi { irq_args.type() != Irq_session::TYPE_LEGACY };
|
||||
if (msi)
|
||||
throw Service_denied();
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <irq_root.h>
|
||||
#include <irq_args.h>
|
||||
#include <util.h>
|
||||
|
||||
using namespace Core;
|
||||
@ -126,7 +127,8 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
_irq_alloc(irq_alloc),
|
||||
_irq_object(_irq_number)
|
||||
{
|
||||
long msi = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
Irq_args irq_args(args);
|
||||
bool msi { irq_args.type() != Irq_session::TYPE_LEGACY };
|
||||
if (msi)
|
||||
throw Service_denied();
|
||||
|
||||
|
@ -103,7 +103,8 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
_irq_alloc(irq_alloc),
|
||||
_irq_object(_irq_number)
|
||||
{
|
||||
long msi = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
Irq_args const irq_args(args);
|
||||
bool msi { irq_args.type() != Irq_session::TYPE_LEGACY };
|
||||
if (msi)
|
||||
throw Service_denied();
|
||||
|
||||
@ -113,8 +114,6 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
}
|
||||
|
||||
|
||||
Irq_args const irq_args(args);
|
||||
|
||||
if (!_irq_object.associate(irq_args.trigger(), irq_args.polarity())) {
|
||||
error("could not associate with IRQ ", irq_args.irq_number());
|
||||
throw Service_denied();
|
||||
|
@ -32,14 +32,32 @@ struct Genode::Irq_connection : Connection<Irq_session>, Irq_session_client
|
||||
Irq_connection(Env &env,
|
||||
Label const &label,
|
||||
Trigger trigger = Irq_session::TRIGGER_UNCHANGED,
|
||||
Polarity polarity = Irq_session::POLARITY_UNCHANGED,
|
||||
addr_t device_config_phys = 0)
|
||||
Polarity polarity = Irq_session::POLARITY_UNCHANGED)
|
||||
:
|
||||
Connection<Irq_session>(env, label, Ram_quota { RAM_QUOTA },
|
||||
Args("irq_number=", label, ", "
|
||||
"irq_trigger=", unsigned(trigger), ", "
|
||||
"irq_polarity=", unsigned(polarity), ", "
|
||||
"device_config_phys=", Hex(device_config_phys))),
|
||||
"irq_type=", unsigned(TYPE_LEGACY))),
|
||||
Irq_session_client(cap())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param label (virtual) interrupt number
|
||||
* \param device_config_phys config-space physical address
|
||||
* \param type interrupt type (e.g., msi/msi-x)
|
||||
*/
|
||||
Irq_connection(Env &env,
|
||||
Label const &label,
|
||||
addr_t device_config_phys,
|
||||
Type type = Irq_session::TYPE_MSI)
|
||||
:
|
||||
Connection<Irq_session>(env, label, Ram_quota { RAM_QUOTA },
|
||||
Args("irq_number=", label, ", "
|
||||
"device_config_phys=", Hex(device_config_phys), ", "
|
||||
"irq_type=", unsigned(type))),
|
||||
Irq_session_client(cap())
|
||||
{ }
|
||||
};
|
||||
|
@ -48,6 +48,11 @@ struct Genode::Irq_session : Session
|
||||
*/
|
||||
enum Polarity { POLARITY_UNCHANGED = 0, POLARITY_HIGH, POLARITY_LOW };
|
||||
|
||||
/**
|
||||
* Interrupt type
|
||||
*/
|
||||
enum Type { TYPE_LEGACY = 0, TYPE_MSI, TYPE_MSIX };
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
|
@ -29,6 +29,7 @@ class Core::Irq_args
|
||||
|
||||
Irq_session::Trigger _irq_trigger { Irq_session::TRIGGER_UNCHANGED };
|
||||
Irq_session::Polarity _irq_polarity { Irq_session::POLARITY_UNCHANGED };
|
||||
Irq_session::Type _irq_type { Irq_session::TYPE_LEGACY };
|
||||
|
||||
long const _irq_number;
|
||||
|
||||
@ -38,8 +39,9 @@ class Core::Irq_args
|
||||
:
|
||||
_irq_number(Arg_string::find_arg(args, "irq_number").long_value(-1))
|
||||
{
|
||||
long irq_trg = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
|
||||
long irq_pol = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
|
||||
long irq_trg = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
|
||||
long irq_pol = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
|
||||
long irq_type = Arg_string::find_arg(args, "irq_type").long_value(-1);
|
||||
|
||||
switch (irq_trg) {
|
||||
case -1:
|
||||
@ -74,11 +76,29 @@ class Core::Irq_args
|
||||
_irq_number);
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
switch (irq_type) {
|
||||
case -1:
|
||||
case Irq_session::TYPE_LEGACY:
|
||||
_irq_type = Irq_session::TYPE_LEGACY;
|
||||
break;
|
||||
case Irq_session::TYPE_MSI:
|
||||
_irq_type = Irq_session::TYPE_MSI;
|
||||
break;
|
||||
case Irq_session::TYPE_MSIX:
|
||||
_irq_type = Irq_session::TYPE_MSIX;
|
||||
break;
|
||||
default:
|
||||
error("invalid type ", irq_type, " specified for IRQ ",
|
||||
_irq_number);
|
||||
throw Service_denied();
|
||||
}
|
||||
}
|
||||
|
||||
long irq_number() const { return _irq_number; }
|
||||
Irq_session::Trigger trigger() const { return _irq_trigger; }
|
||||
Irq_session::Polarity polarity() const { return _irq_polarity; }
|
||||
Irq_session::Type type() const { return _irq_type; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_ARGS_H_ */
|
||||
|
@ -207,7 +207,8 @@ void Driver::Device::update(Allocator &alloc, Xml_node const &node)
|
||||
irq.mode = (mode == "edge") ? Irq_session::TRIGGER_EDGE
|
||||
: Irq_session::TRIGGER_LEVEL;
|
||||
if (type.valid())
|
||||
irq.type = (type == "msi-x") ? Irq::MSIX : Irq::MSI;
|
||||
irq.type = (type == "msi-x") ? Irq_session::TYPE_MSIX
|
||||
: Irq_session::TYPE_MSI;
|
||||
|
||||
return irq;
|
||||
},
|
||||
@ -463,7 +464,7 @@ void Driver::Device_model::update(Xml_node const & node)
|
||||
for_each([&] (Device const & device) {
|
||||
device._irq_list.for_each([&] (Device::Irq const & irq) {
|
||||
|
||||
if (irq.type != Device::Irq::LEGACY)
|
||||
if (irq.type != Irq_session::TYPE_LEGACY)
|
||||
return;
|
||||
|
||||
if (detected_irqs.get(irq.number, 1)) {
|
||||
@ -480,7 +481,7 @@ void Driver::Device_model::update(Xml_node const & node)
|
||||
for_each([&] (Device & device) {
|
||||
device._irq_list.for_each([&] (Device::Irq & irq) {
|
||||
|
||||
if (irq.type != Device::Irq::LEGACY)
|
||||
if (irq.type != Irq_session::TYPE_LEGACY)
|
||||
return;
|
||||
|
||||
if (shared_irqs.get(irq.number, 1))
|
||||
|
@ -97,10 +97,8 @@ class Driver::Device : private List_model<Device>::Element
|
||||
|
||||
struct Irq : List_model<Irq>::Element
|
||||
{
|
||||
enum Type { LEGACY, MSI, MSIX };
|
||||
|
||||
unsigned number;
|
||||
Type type { LEGACY };
|
||||
Irq_session::Type type { Irq_session::TYPE_LEGACY };
|
||||
Irq_session::Polarity polarity { Irq_session::POLARITY_UNCHANGED };
|
||||
Irq_session::Trigger mode { Irq_session::TRIGGER_UNCHANGED };
|
||||
bool shared { false };
|
||||
|
@ -104,15 +104,17 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx)
|
||||
|
||||
if (!irq.shared && !irq.irq.constructed()) {
|
||||
addr_t pci_cfg_addr = 0;
|
||||
if (irq.type != Device::Irq::LEGACY) {
|
||||
if (irq.type != Irq_session::TYPE_LEGACY) {
|
||||
if (_pci_config.constructed()) pci_cfg_addr = _pci_config->addr;
|
||||
else
|
||||
error("MSI(-x) detected for device without pci-config!");
|
||||
}
|
||||
irq.irq.construct(_env, irq.number, irq.mode, irq.polarity,
|
||||
pci_cfg_addr);
|
||||
|
||||
irq.irq.construct(_env, irq.number, pci_cfg_addr, irq.type);
|
||||
} else
|
||||
irq.irq.construct(_env, irq.number, irq.mode, irq.polarity);
|
||||
|
||||
Irq_session::Info info = irq.irq->info();
|
||||
if (info.type == Irq_session::Info::MSI)
|
||||
if (pci_cfg_addr && info.type == Irq_session::Info::MSI)
|
||||
pci_msi_enable(_env, *this, pci_cfg_addr, info, irq.type);
|
||||
}
|
||||
|
||||
@ -179,7 +181,7 @@ Device_component::Device_component(Registry<Device_component> & registry,
|
||||
try {
|
||||
device.for_each_irq([&] (unsigned idx,
|
||||
unsigned nr,
|
||||
Device::Irq::Type type,
|
||||
Irq_session::Type type,
|
||||
Irq_session::Polarity polarity,
|
||||
Irq_session::Trigger mode,
|
||||
bool shared)
|
||||
|
@ -40,7 +40,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned number;
|
||||
Device::Irq::Type type;
|
||||
Irq_session::Type type;
|
||||
Irq_session::Polarity polarity;
|
||||
Irq_session::Trigger mode;
|
||||
bool shared;
|
||||
@ -50,7 +50,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
|
||||
Irq(Registry<Irq> & registry,
|
||||
unsigned idx,
|
||||
unsigned number,
|
||||
Device::Irq::Type type,
|
||||
Irq_session::Type type,
|
||||
Irq_session::Polarity polarity,
|
||||
Irq_session::Trigger mode,
|
||||
bool shared)
|
||||
|
@ -193,13 +193,13 @@ void Driver::pci_msi_enable(Env & env,
|
||||
Device_component & dc,
|
||||
addr_t cfg_space,
|
||||
Irq_session::Info const info,
|
||||
Device::Irq::Type type)
|
||||
Irq_session::Type type)
|
||||
{
|
||||
Attached_io_mem_dataspace io_mem { env, cfg_space, 0x1000 };
|
||||
Config config { (addr_t)io_mem.local_addr<void>() };
|
||||
config.scan();
|
||||
|
||||
if (type == Device::Irq::Type::MSIX && config.msi_x_cap.constructed()) {
|
||||
if (type == Irq_session::TYPE_MSIX && config.msi_x_cap.constructed()) {
|
||||
try {
|
||||
/* find the MSI-x table from the device's memory bars */
|
||||
Platform::Device_interface::Range range;
|
||||
@ -231,7 +231,7 @@ void Driver::pci_msi_enable(Env & env,
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == Device::Irq::Type::MSI && config.msi_cap.constructed()) {
|
||||
if (type == Irq_session::TYPE_MSI && config.msi_cap.constructed()) {
|
||||
config.msi_cap->enable(info.address, (uint16_t)info.value);
|
||||
return;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace Driver {
|
||||
void pci_apply_quirks(Genode::Env & env, Device const & dev);
|
||||
void pci_msi_enable(Genode::Env & env, Device_component & dc,
|
||||
addr_t cfg_space, Genode::Irq_session::Info const info,
|
||||
Device::Irq::Type type);
|
||||
Irq_session::Type type);
|
||||
bool pci_device_matches(Genode::Session_policy const & policy,
|
||||
Device const & dev);
|
||||
void pci_device_specific_info(Device const & dev,
|
||||
|
Loading…
Reference in New Issue
Block a user