+config ACPI_GTDT
+ bool "ACPI GTDT Support"
+ depends on ARM64
+ help
+ GTDT (Generic Timer Description Table) provides
information
+ for per-processor timers and Platform (memory-mapped)
timers
+ for ARM platforms. Select this option to provide
information
+ needed for the timers init.
Why not ARM64's Kconfig select ACPI_GTDT ?
This config option assumes an user will manually select this option
which I believe it makes sense to have always on when ARM64=y. So
why not create a silent option and select it directly from the ARM64
platform Kconfig ?
I use "depends on ARM64" here, because GTDT is only for ARM, and only
ARM64 support ACPI. GTDT is meaningless for other architecture. This
"depends on" just makes sure only ARM64 can select it.
But user don't need to manually select this option. Once ARM64=y and
ACPI=y, this will be automatically selected, because we have this in
[PATCH v5 5/6]:
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 47352d2..5a5baa1 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -8,6 +8,7 @@ config CLKSRC_OF
config CLKSRC_ACPI
bool
select CLKSRC_PROBE
+select ACPI_GTDT
config CLKSRC_PROBE
bool
And CLKSRC_ACPI will be selected by below in Kconfig of
clocksource(mainline kernel):
config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF
select CLKSRC_ACPI if ACPI
And ARM_ARCH_TIMER will be selected by ARM64 in
arch/arm64/Kconfig(mainline kernel).
So ARM64=y --> ARM_ARCH_TIMER=y (if ACPI=y) --> CLKSRC_ACPI=y -->
ACPI_GTDT=y
I think that is the right solution. Do I miss something?
+static int __init for_platform_timer(enum acpi_gtdt_type type,
+ platform_timer_handler
handler, void *data)
For the clarity of the code, I suggest to use a macro with a name
similar to what we find in the kernel:
#define gtdt_for_each(type, ...) ...
#define gtdt_for_each_timer gtdt_for_each(ACPI_GTDT_TYPE_TIMER_BLOCK)
#define gtdt_for_each_wd gtdt_for_each(ACPI_GTDT_TYPE_WATCHDOG)
... and rework this function to clarify its purpose.
yes, that is a very good idea, thanks, will do.
What is for ? Count the number of 'type' which succeed to call the
handler ?
because we need a index of watchdog timer for importing it into the
resource of platform_device,
but I think I can ues a static variable to solve this problem? Any thought?
+{
+ struct acpi_gtdt_header *header;
+ int i, index, ret;
+ void *platform_timer = platform_timer_struct;
+
+ for (i = 0, index = 0; i < platform_timer_count; i++) {
+ if (platform_timer > gtdt_end) {
+ pr_err(FW_BUG "subtable pointer
overflows.\n");
+ platform_timer_count = i;
Fix firmware bug in the kernel ? No. Up to the firmware to fix it,
"no handy, no candy".
So you are suggesting that if we find this firmware bug, just return
error instead of using the info in a problematic table, right?
+ break;
+ }
+ header = (struct acpi_gtdt_header *)platform_timer;
+ if (header->type == type) {
+ ret = handler(platform_timer, index, data);
+ if (ret)
+ pr_err("failed to handler
subtable %d.\n", i);
+ else
+ index++;
+ }
+ platform_timer += header->length;
That is not correct. This function is setting the platform_timer
pointer to the end. Even if that works, it violates the
encapsulation paradigm. Regarding how are used those global
variables, please kill them and use proper parameter and structure
encapsulation.
So let me explain this a little:
"void *platform_timer = platform_timer_struct;" is getting the pointer
of first Platform Timer Structure, platform_timer_struct in this
patchset is a global variable, but platform_timer is a local variable in
the for_platform_timer function.
Platform Timer Structure Field is a array of Platform Timer Type structures.
And the length of each structure maybe different, so I think
"platform_timer += header->length" is a right approach to move on to
next Platform Timer structures
Do I misunderstand your comment? or maybe I miss something?
+/*
+ * Get some basic info from GTDT table, and init the global
variables above
+ * for all timers initialization of Generic Timer.
+ * This function does some validation on GTDT table, and will
be run only once.
+ */
+static void __init platform_timer_init(struct acpi_table_header
*table,
+ struct acpi_table_gtdt *gtdt)
+{
+ gtdt_end = (void *)table + table->length;
+
+ if (table->revision < 2) {
+ pr_info("Revision:%d doesn't support Platform
Timers.\n",
+ table->revision);
+ return;
+ }
This check should be called much sooner, before entering the gtdt
subsystems. It is too late here.
the reason I check table revision here is that:
the difference between revision 1 and 2 is revision-2 adds Platform
Timer Structure support.
and this init function is just for getting some basic Platform Timer
info in "main" table.
So at the beginning of this function I check the revision.
But it also makes sense to move this out to gtdt_arch_timer_init like this:
if (table->revision < 2)
return 0;
else
platform_timer_init(table, gtdt);
Any suggestion??