From 5a48f8ab0f60e1d56c226794b87e662b78153d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 4 Feb 2022 15:48:18 +0100 Subject: [PATCH] lx_kit/lx_emul: support for executing PCI fixups Ref genodelabs/genode#4411 --- repos/dde_linux/src/include/lx_emul/init.h | 5 +++ repos/dde_linux/src/include/lx_kit/env.h | 1 + repos/dde_linux/src/include/lx_kit/init.h | 26 ++++++++++++ repos/dde_linux/src/lib/lx_emul/pci_init.cc | 46 +++++++++++++++++++++ repos/dde_linux/src/lib/lx_kit/init.cc | 17 +++++++- 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 repos/dde_linux/src/lib/lx_emul/pci_init.cc diff --git a/repos/dde_linux/src/include/lx_emul/init.h b/repos/dde_linux/src/include/lx_emul/init.h index 9dd2faaedd..64119964b7 100644 --- a/repos/dde_linux/src/include/lx_emul/init.h +++ b/repos/dde_linux/src/include/lx_emul/init.h @@ -34,6 +34,11 @@ void lx_emul_register_of_clk_initcall(char const *compat, void *fn); void lx_emul_register_of_irqchip_initcall(char const *compat, void *fn); +struct pci_dev; +void lx_emul_register_pci_fixup(void (*fn)(struct pci_dev*), char const *name); + +void lx_emul_execute_pci_fixup(struct pci_dev *pci_dev); + #ifdef __cplusplus } #endif diff --git a/repos/dde_linux/src/include/lx_kit/env.h b/repos/dde_linux/src/include/lx_kit/env.h index 643ec8fad5..65c6ff0dce 100644 --- a/repos/dde_linux/src/include/lx_kit/env.h +++ b/repos/dde_linux/src/include/lx_kit/env.h @@ -41,6 +41,7 @@ struct Lx_kit::Env Genode::Env & env; Genode::Heap heap { env.ram(), env.rm() }; Initcalls initcalls { heap }; + Pci_fixup_calls pci_fixup_calls { heap }; Console console { }; Platform::Connection platform { env }; Timer::Connection timer { env }; diff --git a/repos/dde_linux/src/include/lx_kit/init.h b/repos/dde_linux/src/include/lx_kit/init.h index 011d140f61..0eb31fbfd9 100644 --- a/repos/dde_linux/src/include/lx_kit/init.h +++ b/repos/dde_linux/src/include/lx_kit/init.h @@ -22,6 +22,8 @@ namespace Lx_kit { void initialize(Env & env); class Initcalls; + + class Pci_fixup_calls; } @@ -48,4 +50,28 @@ class Lx_kit::Initcalls Initcalls(Heap & heap) : _heap(heap) {} }; +struct pci_dev; + +class Lx_kit::Pci_fixup_calls +{ + private: + + struct E : List::Element + { + void (*call) (struct pci_dev *); + + E(void (*fn)(struct pci_dev *)) : call { fn } { } + }; + + Heap & _heap; + List _call_list {}; + + public: + + void add(void (*fn)(struct pci_dev*)); + void execute(struct pci_dev *); + + Pci_fixup_calls(Heap & heap) : _heap(heap) { } +}; + #endif /* _LX_KIT__INIT_H_ */ diff --git a/repos/dde_linux/src/lib/lx_emul/pci_init.cc b/repos/dde_linux/src/lib/lx_emul/pci_init.cc new file mode 100644 index 0000000000..b20b2b1e59 --- /dev/null +++ b/repos/dde_linux/src/lib/lx_emul/pci_init.cc @@ -0,0 +1,46 @@ +/* + * \brief Lx_emul backend for PCI fixup calls + * \author Josef Soentgen + * \date 2022-02-04 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include +#include + +#include + + +extern "C" __attribute__((weak)) int inhibit_pci_fixup(char const *) +{ + return 0; +} + + +extern "C" void lx_emul_register_pci_fixup(void (*fn)(struct pci_dev*), const char * name) +{ + if (inhibit_pci_fixup(name)) + return; + + for (unsigned i = 0; i < (sizeof(lx_emul_pci_final_fixups) / sizeof(char*)); + i++) { + if (Genode::strcmp(name, lx_emul_pci_final_fixups[i]) == 0) { + Lx_kit::env().pci_fixup_calls.add(fn); + return; + } + } + Genode::error(__func__, " ignore unkown PCI fixup '", name, "'"); +} + + +extern "C" void lx_emul_execute_pci_fixup(struct pci_dev *pci_dev) +{ + Lx_kit::env().pci_fixup_calls.execute(pci_dev); +} diff --git a/repos/dde_linux/src/lib/lx_kit/init.cc b/repos/dde_linux/src/lib/lx_kit/init.cc index c3e904bc0c..e711ed44a2 100644 --- a/repos/dde_linux/src/lib/lx_kit/init.cc +++ b/repos/dde_linux/src/lib/lx_kit/init.cc @@ -16,7 +16,11 @@ #include #include -namespace Lx_kit { class Initcalls; } +namespace Lx_kit { + + class Initcalls; + class Pci_fixup_calls; +} void Lx_kit::Initcalls::add(int (*initcall)(void), unsigned int prio) { @@ -40,6 +44,17 @@ void Lx_kit::Initcalls::execute_in_order() } +void Lx_kit::Pci_fixup_calls::add(void (*fn)(struct pci_dev*)) { + _call_list.insert(new (_heap) E(fn)); } + + +void Lx_kit::Pci_fixup_calls::execute(struct pci_dev *pci_dev) +{ + for (E * entry = _call_list.first(); entry; entry = entry->next()) + entry->call(pci_dev); +} + + void Lx_kit::initialize(Genode::Env & env) { Lx_kit::env(&env);