Skip to content

Commit 797c053

Browse files
shankerwangmiaoopsiff
authored andcommitted
loongarch: fix missing dependency info in DSDT
On machines with legacy firmware with BPI01000 version, the devices on the LIO bus lackes the dependency on the PCI root controller, causing the memory-mapped address of the legacy IO ports read before the setup of the mapping, resulting in kernel panic. Such DSDT can work on the legacy loongarch linux port because the leading 16K is unconditionally registered, before the enumeration of the devices in the DSDT table. This patch addes such dependency info, to order the initialization of the devices on the LIO bus after the initialization of the PCI root controller, fixing this problem. However, the addition should be done on each possible LIO device, and currently the patch only includes the legacy EC device on some laptops located at the path \_SB.PCI0.LPC.EC. Thus, this patch will be improved to include more devices. The above behavior is only enabled when BPI data and the BPI01000 version is detected.
1 parent e1b7484 commit 797c053

4 files changed

Lines changed: 54 additions & 0 deletions

File tree

arch/loongarch/include/asm/acpi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ extern void acpi_arch_os_table_override (struct acpi_table_header *existing_tabl
5050
extern void acpi_arch_table_init_complete(void);
5151
#define ACPI_HAVE_ARCH_PCI_ROOT_RES_FILTER
5252
extern void acpi_arch_pci_probe_root_dev_filter(struct resource_entry *entry);
53+
#define ACPI_HAVE_ARCH_INIT
54+
extern void acpi_arch_init(void);
5355

5456
#endif /* !CONFIG_ACPI */
5557

arch/loongarch/kernel/legacy_boot.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,53 @@ void acpi_arch_pci_probe_root_dev_filter(struct resource_entry *entry)
617617
}
618618
}
619619

620+
static __initconst const struct {
621+
struct acpi_table_header header;
622+
unsigned char code [];
623+
} __packed dsdt_add_aml_code = {
624+
.header = {
625+
.signature = ACPI_SIG_DSDT
626+
},
627+
.code = {
628+
0x14,0x21,0x5C,0x2F, /* 00000020 " .!\/" */
629+
0x05,0x5F,0x53,0x42,0x5F,0x50,0x43,0x49, /* 00000028 "._SB_PCI" */
630+
0x30,0x4C,0x50,0x43,0x5F,0x45,0x43,0x5F, /* 00000030 "0LPC_EC_" */
631+
0x5F,0x5F,0x44,0x45,0x50,0x08,0xA4,0x12, /* 00000038 "__DEP..." */
632+
0x06,0x01,0x50,0x43,0x49,0x30 /* 00000040 "..PCI0" */
633+
},
634+
};
635+
636+
void __init acpi_arch_init (){
637+
if (bpi_version == BPI_VERSION_NONE) {
638+
return;
639+
}
640+
if (bpi_version > BPI_VERSION_V1) {
641+
return;
642+
}
643+
pr_info("BPI: Trying to patch DSDT\n");
644+
645+
acpi_status status;
646+
acpi_handle handle;
647+
648+
status = acpi_get_handle(NULL, "\\_SB.PCI0.LPC.EC", &handle);
649+
if (ACPI_FAILURE(status)) {
650+
if (status != AE_NOT_FOUND) {
651+
pr_info("BPI: Unable to find EC device: %s\n", acpi_format_exception(status));
652+
}
653+
return;
654+
}
655+
if (acpi_has_method(handle, "_DEP")) {
656+
return;
657+
}
658+
659+
status = acpi_install_method((u8 *)&dsdt_add_aml_code);
660+
if (ACPI_FAILURE(status)) {
661+
pr_info("BPI: Unable to patch DSDT(0x%x)\n", status);
662+
return;
663+
}
664+
acpi_handle_info(handle, "BPI: Patched DSDT\n");
665+
}
666+
620667
int loongarch_have_legacy_bpi (void){
621668
return have_bpi;
622669
}

drivers/acpi/bus.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,7 @@ static int __init acpi_init(void)
14141414
acpi_hest_init();
14151415
acpi_ghes_init();
14161416
acpi_arm_init();
1417+
acpi_arch_init();
14171418
acpi_scan_init();
14181419
acpi_ec_init();
14191420
acpi_debugfs_init();

include/linux/acpi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,10 @@ void acpi_arm_init(void);
15341534
static inline void acpi_arm_init(void) { }
15351535
#endif
15361536

1537+
#ifndef ACPI_HAVE_ARCH_INIT
1538+
static inline void acpi_arch_init(void) {}
1539+
#endif
1540+
15371541
#ifdef CONFIG_ACPI_PCC
15381542
void acpi_init_pcc(void);
15391543
#else

0 commit comments

Comments
 (0)