Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions arch/loongarch/kernel/legacy_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -718,3 +718,47 @@ void __init acpi_arch_init (void){
int loongarch_have_legacy_bpi (void){
return have_bpi;
}

static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, unsigned long isa_base)
{
int ret = 0;
unsigned long vaddr;
struct logic_pio_hwaddr *range;
range = kzalloc(sizeof(*range), GFP_ATOMIC);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Use GFP_KERNEL instead of GFP_ATOMIC in init context

This runs in init context, not atomic/IRQ, so GFP_ATOMIC is unnecessarily restrictive and increases the chance of allocation failure under memory pressure. Please use GFP_KERNEL here for a more appropriate and consistent init-time allocation.

Suggested change
range = kzalloc(sizeof(*range), GFP_ATOMIC);
range = kzalloc(sizeof(*range), GFP_KERNEL);

if (!range)
return -ENOMEM;
range->fwnode = fwnode;
range->size = ISA_IOSIZE;
range->hw_start = isa_base;
range->flags = LOGIC_PIO_CPU_MMIO;
ret = logic_pio_register_range(range);
if (ret) {
kfree(range);
return ret;
}
if (range->io_start != 0) {
logic_pio_unregister_range(range);
kfree(range);
return -EINVAL;
}
vaddr = (unsigned long)(PCI_IOBASE + range->io_start);
ret = ioremap_page_range(vaddr, vaddr + range->size, range->hw_start,
pgprot_device(PAGE_KERNEL));
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add_legacy_isa_io() returns the result of ioremap_page_range(), but on failure the newly-registered Logic PIO range is left registered (and the allocated range is leaked). Consider unregistering the range (and freeing the allocation) if ioremap_page_range() fails, to avoid a partially-initialized mapping remaining in the global io_range_list.

Suggested change
pgprot_device(PAGE_KERNEL));
pgprot_device(PAGE_KERNEL));
if (ret) {
logic_pio_unregister_range(range);
kfree(range);
}

Copilot uses AI. Check for mistakes.
return ret;
}

#define ISA_PHY_IOBASE LOONGSON_LIO_BASE
static int __init acpi_register_legacy_isa_io(void)
{
struct fwnode_handle *fwnode;
u64 cpu_addr;
if (!acpi_disabled) {
cpu_addr = ISA_PHY_IOBASE;
fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC);
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the ACPI-enabled path, allocating a raw struct fwnode_handle with kzalloc() leaves it uninitialized (no fwnode_ops), which can break helpers like is_acpi_device_node() if anything later inspects this handle. If you need a synthetic fwnode for a static mapping, use acpi_alloc_fwnode_static() (which calls fwnode_init() with acpi_static_fwnode_ops) rather than open-coding kzalloc().

Suggested change
fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC);
fwnode = acpi_alloc_fwnode_static();

Copilot uses AI. Check for mistakes.
}
Comment on lines +755 to +758
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

register_legacy_isa_io() runs unconditionally as an arch_initcall() and will also attempt DT-based registration when acpi_disabled is true. But LoongArch already registers ISA PIO ranges from DT in arch_reserve_pio_range() (arch/loongarch/kernel/setup.c:534-572). Depending on initcall ordering, this can lead to duplicate registrations (-EEXIST) and spurious warnings from the other path. Consider gating this initcall to the legacy-BPI/ACPI workaround case only (e.g., have_bpi && bpi_version == BPI_VERSION_V1 && !acpi_disabled), and rely on the existing DT path otherwise.

Suggested change
if (!acpi_disabled) {
cpu_addr = ISA_PHY_IOBASE;
fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC);
} else {
fwnode = parse_isa_base(&cpu_addr);
}
if (!have_bpi || bpi_version != BPI_VERSION_V1 || acpi_disabled)
return 0;
cpu_addr = ISA_PHY_IOBASE;
fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC);

Copilot uses AI. Check for mistakes.

if (fwnode)
add_legacy_isa_io(fwnode, cpu_addr);
return 0;
}
arch_initcall(acpi_register_legacy_isa_io);
Loading