Skip to content

Commit b0b3942

Browse files
chenhuacaigregkh
authored andcommitted
LoongArch: Add PIO for early access before ACPI PCI root register
commit 6061e65 upstream. For ACPI system we suppose the ISA/LPC PIO range is registered together with PCI root bridge. But the fact is there may be some early access to the ISA/LPC PIO range before ACPI PCI root register (most of them are due to abnormal BIOS). Unconditionally register the ISA/LPC PIO range usually causes ACPI PCI root register fail because of the address range confliction. So we add a pair of helpers: acpi_add_early_pio() to add PIO for early access, and acpi_remove_early_pio() to remove PIO before PCI root register. Since acpi_remove_early_pio() may be called multiple times, we add an acpi_pio flag to ensure PIO be removed only once. Cc: <stable@vger.kernel.org> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 865a048 commit b0b3942

4 files changed

Lines changed: 34 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
@@ -37,6 +37,8 @@ static inline bool acpi_has_cpu_in_madt(void)
3737
extern struct list_head acpi_wakeup_device_list;
3838
extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
3939

40+
extern void acpi_add_early_pio(void);
41+
extern void acpi_remove_early_pio(void);
4042
extern int __init parse_acpi_topology(void);
4143

4244
static inline u32 get_acpi_id_for_cpu(unsigned int cpu)

arch/loongarch/kernel/acpi.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/memblock.h>
1515
#include <linux/of_fdt.h>
1616
#include <linux/serial_core.h>
17+
#include <linux/vmalloc.h>
1718
#include <asm/io.h>
1819
#include <asm/numa.h>
1920
#include <asm/loongson.h>
@@ -57,6 +58,33 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
5758
return ioremap_cache(phys, size);
5859
}
5960

61+
#define PIO_BASE (unsigned long)PCI_IOBASE
62+
#define PIO_SIZE ALIGN(ISA_IOSIZE, PAGE_SIZE)
63+
64+
static bool acpi_pio;
65+
66+
/* Add PIO for early access */
67+
void acpi_add_early_pio(void)
68+
{
69+
if (!acpi_disabled) {
70+
acpi_pio = true;
71+
ioremap_page_range(PIO_BASE, PIO_BASE + PIO_SIZE,
72+
LOONGSON_LIO_BASE, pgprot_device(PAGE_KERNEL));
73+
}
74+
}
75+
76+
/* Remove PIO for PCI register */
77+
void acpi_remove_early_pio(void)
78+
{
79+
if (!acpi_pio)
80+
return;
81+
82+
if (!acpi_disabled) {
83+
acpi_pio = false;
84+
vunmap_range(PIO_BASE, PIO_BASE + PIO_SIZE);
85+
}
86+
}
87+
6088
#ifdef CONFIG_SMP
6189
static int set_processor_mask(u32 id, u32 flags)
6290
{

arch/loongarch/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ static __init int arch_reserve_pio_range(void)
530530
{
531531
struct device_node *np;
532532

533+
acpi_add_early_pio();
534+
533535
for_each_node_by_name(np, "isa") {
534536
struct of_range range;
535537
struct of_range_parser parser;

arch/loongarch/pci/acpi.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
6565
struct resource_entry *entry, *tmp;
6666
struct acpi_device *device = ci->bridge;
6767

68+
acpi_remove_early_pio();
69+
6870
status = acpi_pci_probe_root_resources(ci);
6971
if (status > 0) {
7072
acpi_evaluate_integer(device->handle, "PCIH", NULL, &pci_h);

0 commit comments

Comments
 (0)