Skip to content

Commit a103f46

Browse files
davejiangdjbw
authored andcommitted
acpi: Move common tables helper functions to common lib
Some of the routines in ACPI driver/acpi/tables.c can be shared with parsing CDAT. CDAT is a device-provided data structure that is formatted similar to a platform provided ACPI table. CDAT is used by CXL and can exist on platforms that do not use ACPI. Split out the common routine from ACPI to accommodate platforms that do not support ACPI and move that to /lib. The common routines can be built outside of ACPI if FIRMWARE_TABLES is selected. Link: https://lore.kernel.org/linux-cxl/CAJZ5v0jipbtTNnsA0-o5ozOk8ZgWnOg34m34a9pPenTyRLj=6A@mail.gmail.com/ Suggested-by: "Rafael J. Wysocki" <rafael@kernel.org> Reviewed-by: Hanjun Guo <guohanjun@huawei.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Acked-by: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> Link: https://lore.kernel.org/r/169713683430.2205276.17899451119920103445.stgit@djiang5-mobl3 Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 8358e8f commit a103f46

File tree

8 files changed

+251
-204
lines changed

8 files changed

+251
-204
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ F: drivers/pnp/pnpacpi/
294294
F: include/acpi/
295295
F: include/linux/acpi.h
296296
F: include/linux/fwnode.h
297+
F: include/linux/fw_table.h
298+
F: lib/fw_table.c
297299
F: tools/power/acpi/
298300

299301
ACPI APEI

drivers/acpi/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ menuconfig ACPI
1212
select PNP
1313
select NLS
1414
select CRC32
15+
select FIRMWARE_TABLE
1516
default y if X86
1617
help
1718
Advanced Configuration and Power Interface (ACPI) support for

drivers/acpi/tables.c

Lines changed: 0 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,6 @@ static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
3737

3838
static int acpi_apic_instance __initdata_or_acpilib;
3939

40-
enum acpi_subtable_type {
41-
ACPI_SUBTABLE_COMMON,
42-
ACPI_SUBTABLE_HMAT,
43-
ACPI_SUBTABLE_PRMT,
44-
ACPI_SUBTABLE_CEDT,
45-
};
46-
47-
struct acpi_subtable_entry {
48-
union acpi_subtable_headers *hdr;
49-
enum acpi_subtable_type type;
50-
};
51-
5240
/*
5341
* Disable table checksum verification for the early stage due to the size
5442
* limitation of the current x86 early mapping implementation.
@@ -237,167 +225,6 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
237225
}
238226
}
239227

240-
static unsigned long __init_or_acpilib
241-
acpi_get_entry_type(struct acpi_subtable_entry *entry)
242-
{
243-
switch (entry->type) {
244-
case ACPI_SUBTABLE_COMMON:
245-
return entry->hdr->common.type;
246-
case ACPI_SUBTABLE_HMAT:
247-
return entry->hdr->hmat.type;
248-
case ACPI_SUBTABLE_PRMT:
249-
return 0;
250-
case ACPI_SUBTABLE_CEDT:
251-
return entry->hdr->cedt.type;
252-
}
253-
return 0;
254-
}
255-
256-
static unsigned long __init_or_acpilib
257-
acpi_get_entry_length(struct acpi_subtable_entry *entry)
258-
{
259-
switch (entry->type) {
260-
case ACPI_SUBTABLE_COMMON:
261-
return entry->hdr->common.length;
262-
case ACPI_SUBTABLE_HMAT:
263-
return entry->hdr->hmat.length;
264-
case ACPI_SUBTABLE_PRMT:
265-
return entry->hdr->prmt.length;
266-
case ACPI_SUBTABLE_CEDT:
267-
return entry->hdr->cedt.length;
268-
}
269-
return 0;
270-
}
271-
272-
static unsigned long __init_or_acpilib
273-
acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)
274-
{
275-
switch (entry->type) {
276-
case ACPI_SUBTABLE_COMMON:
277-
return sizeof(entry->hdr->common);
278-
case ACPI_SUBTABLE_HMAT:
279-
return sizeof(entry->hdr->hmat);
280-
case ACPI_SUBTABLE_PRMT:
281-
return sizeof(entry->hdr->prmt);
282-
case ACPI_SUBTABLE_CEDT:
283-
return sizeof(entry->hdr->cedt);
284-
}
285-
return 0;
286-
}
287-
288-
static enum acpi_subtable_type __init_or_acpilib
289-
acpi_get_subtable_type(char *id)
290-
{
291-
if (strncmp(id, ACPI_SIG_HMAT, 4) == 0)
292-
return ACPI_SUBTABLE_HMAT;
293-
if (strncmp(id, ACPI_SIG_PRMT, 4) == 0)
294-
return ACPI_SUBTABLE_PRMT;
295-
if (strncmp(id, ACPI_SIG_CEDT, 4) == 0)
296-
return ACPI_SUBTABLE_CEDT;
297-
return ACPI_SUBTABLE_COMMON;
298-
}
299-
300-
static __init_or_acpilib bool has_handler(struct acpi_subtable_proc *proc)
301-
{
302-
return proc->handler || proc->handler_arg;
303-
}
304-
305-
static __init_or_acpilib int call_handler(struct acpi_subtable_proc *proc,
306-
union acpi_subtable_headers *hdr,
307-
unsigned long end)
308-
{
309-
if (proc->handler)
310-
return proc->handler(hdr, end);
311-
if (proc->handler_arg)
312-
return proc->handler_arg(hdr, proc->arg, end);
313-
return -EINVAL;
314-
}
315-
316-
/**
317-
* acpi_parse_entries_array - for each proc_num find a suitable subtable
318-
*
319-
* @id: table id (for debugging purposes)
320-
* @table_size: size of the root table
321-
* @table_header: where does the table start?
322-
* @proc: array of acpi_subtable_proc struct containing entry id
323-
* and associated handler with it
324-
* @proc_num: how big proc is?
325-
* @max_entries: how many entries can we process?
326-
*
327-
* For each proc_num find a subtable with proc->id and run proc->handler
328-
* on it. Assumption is that there's only single handler for particular
329-
* entry id.
330-
*
331-
* The table_size is not the size of the complete ACPI table (the length
332-
* field in the header struct), but only the size of the root table; i.e.,
333-
* the offset from the very first byte of the complete ACPI table, to the
334-
* first byte of the very first subtable.
335-
*
336-
* On success returns sum of all matching entries for all proc handlers.
337-
* Otherwise, -ENODEV or -EINVAL is returned.
338-
*/
339-
static int __init_or_acpilib acpi_parse_entries_array(
340-
char *id, unsigned long table_size,
341-
struct acpi_table_header *table_header, struct acpi_subtable_proc *proc,
342-
int proc_num, unsigned int max_entries)
343-
{
344-
struct acpi_subtable_entry entry;
345-
unsigned long table_end, subtable_len, entry_len;
346-
int count = 0;
347-
int errs = 0;
348-
int i;
349-
350-
table_end = (unsigned long)table_header + table_header->length;
351-
352-
/* Parse all entries looking for a match. */
353-
354-
entry.type = acpi_get_subtable_type(id);
355-
entry.hdr = (union acpi_subtable_headers *)
356-
((unsigned long)table_header + table_size);
357-
subtable_len = acpi_get_subtable_header_length(&entry);
358-
359-
while (((unsigned long)entry.hdr) + subtable_len < table_end) {
360-
if (max_entries && count >= max_entries)
361-
break;
362-
363-
for (i = 0; i < proc_num; i++) {
364-
if (acpi_get_entry_type(&entry) != proc[i].id)
365-
continue;
366-
if (!has_handler(&proc[i]) ||
367-
(!errs &&
368-
call_handler(&proc[i], entry.hdr, table_end))) {
369-
errs++;
370-
continue;
371-
}
372-
373-
proc[i].count++;
374-
break;
375-
}
376-
if (i != proc_num)
377-
count++;
378-
379-
/*
380-
* If entry->length is 0, break from this loop to avoid
381-
* infinite loop.
382-
*/
383-
entry_len = acpi_get_entry_length(&entry);
384-
if (entry_len == 0) {
385-
pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
386-
return -EINVAL;
387-
}
388-
389-
entry.hdr = (union acpi_subtable_headers *)
390-
((unsigned long)entry.hdr + entry_len);
391-
}
392-
393-
if (max_entries && count > max_entries) {
394-
pr_warn("[%4.4s:0x%02x] found the maximum %i entries\n",
395-
id, proc->id, count);
396-
}
397-
398-
return errs ? -EINVAL : count;
399-
}
400-
401228
int __init_or_acpilib acpi_table_parse_entries_array(
402229
char *id, unsigned long table_size, struct acpi_subtable_proc *proc,
403230
int proc_num, unsigned int max_entries)

include/linux/acpi.h

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/mod_devicetable.h>
1616
#include <linux/property.h>
1717
#include <linux/uuid.h>
18+
#include <linux/fw_table.h>
1819

1920
struct irq_domain;
2021
struct irq_domain_ops;
@@ -24,6 +25,16 @@ struct irq_domain_ops;
2425
#endif
2526
#include <acpi/acpi.h>
2627

28+
#ifdef CONFIG_ACPI_TABLE_LIB
29+
#define EXPORT_SYMBOL_ACPI_LIB(x) EXPORT_SYMBOL_NS_GPL(x, ACPI)
30+
#define __init_or_acpilib
31+
#define __initdata_or_acpilib
32+
#else
33+
#define EXPORT_SYMBOL_ACPI_LIB(x)
34+
#define __init_or_acpilib __init
35+
#define __initdata_or_acpilib __initdata
36+
#endif
37+
2738
#ifdef CONFIG_ACPI
2839

2940
#include <linux/list.h>
@@ -119,21 +130,8 @@ enum acpi_address_range_id {
119130

120131

121132
/* Table Handlers */
122-
union acpi_subtable_headers {
123-
struct acpi_subtable_header common;
124-
struct acpi_hmat_structure hmat;
125-
struct acpi_prmt_module_header prmt;
126-
struct acpi_cedt_header cedt;
127-
};
128-
129133
typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
130134

131-
typedef int (*acpi_tbl_entry_handler)(union acpi_subtable_headers *header,
132-
const unsigned long end);
133-
134-
typedef int (*acpi_tbl_entry_handler_arg)(union acpi_subtable_headers *header,
135-
void *arg, const unsigned long end);
136-
137135
/* Debugger support */
138136

139137
struct acpi_debugger_ops {
@@ -207,14 +205,6 @@ static inline int acpi_debugger_notify_command_complete(void)
207205
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
208206
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
209207

210-
struct acpi_subtable_proc {
211-
int id;
212-
acpi_tbl_entry_handler handler;
213-
acpi_tbl_entry_handler_arg handler_arg;
214-
void *arg;
215-
int count;
216-
};
217-
218208
void __iomem *__acpi_map_table(unsigned long phys, unsigned long size);
219209
void __acpi_unmap_table(void __iomem *map, unsigned long size);
220210
int early_acpi_boot_init(void);
@@ -229,16 +219,6 @@ void acpi_reserve_initial_tables (void);
229219
void acpi_table_init_complete (void);
230220
int acpi_table_init (void);
231221

232-
#ifdef CONFIG_ACPI_TABLE_LIB
233-
#define EXPORT_SYMBOL_ACPI_LIB(x) EXPORT_SYMBOL_NS_GPL(x, ACPI)
234-
#define __init_or_acpilib
235-
#define __initdata_or_acpilib
236-
#else
237-
#define EXPORT_SYMBOL_ACPI_LIB(x)
238-
#define __init_or_acpilib __init
239-
#define __initdata_or_acpilib __initdata
240-
#endif
241-
242222
int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
243223
int __init_or_acpilib acpi_table_parse_entries(char *id,
244224
unsigned long table_size, int entry_id,

include/linux/fw_table.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* fw_tables.h - Parsing support for ACPI and ACPI-like tables provided by
4+
* platform or device firmware
5+
*
6+
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7+
* Copyright (C) 2023 Intel Corp.
8+
*/
9+
#ifndef _FW_TABLE_H_
10+
#define _FW_TABLE_H_
11+
12+
union acpi_subtable_headers;
13+
14+
typedef int (*acpi_tbl_entry_handler)(union acpi_subtable_headers *header,
15+
const unsigned long end);
16+
17+
typedef int (*acpi_tbl_entry_handler_arg)(union acpi_subtable_headers *header,
18+
void *arg, const unsigned long end);
19+
20+
struct acpi_subtable_proc {
21+
int id;
22+
acpi_tbl_entry_handler handler;
23+
acpi_tbl_entry_handler_arg handler_arg;
24+
void *arg;
25+
int count;
26+
};
27+
28+
#include <linux/acpi.h>
29+
#include <acpi/acpi.h>
30+
31+
union acpi_subtable_headers {
32+
struct acpi_subtable_header common;
33+
struct acpi_hmat_structure hmat;
34+
struct acpi_prmt_module_header prmt;
35+
struct acpi_cedt_header cedt;
36+
};
37+
38+
int acpi_parse_entries_array(char *id, unsigned long table_size,
39+
struct acpi_table_header *table_header,
40+
struct acpi_subtable_proc *proc,
41+
int proc_num, unsigned int max_entries);
42+
43+
#endif

lib/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,3 +764,6 @@ config ASN1_ENCODER
764764

765765
config POLYNOMIAL
766766
tristate
767+
768+
config FIRMWARE_TABLE
769+
bool

lib/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
405405

406406
obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
407407

408+
obj-$(CONFIG_FIRMWARE_TABLE) += fw_table.o
409+
408410
# FORTIFY_SOURCE compile-time behavior tests
409411
TEST_FORTIFY_SRCS = $(wildcard $(srctree)/$(src)/test_fortify/*-*.c)
410412
TEST_FORTIFY_LOGS = $(patsubst $(srctree)/$(src)/%.c, %.log, $(TEST_FORTIFY_SRCS))

0 commit comments

Comments
 (0)