-
Notifications
You must be signed in to change notification settings - Fork 116
[Deepin-Kernel-SIG] [linux 6.6.y] [deepin] LoongArch: legacyboot: BPI: workaround old firmware with ISA #1631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: linux-6.6.y
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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); | ||||||||||||||||||||||||||
| 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)); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| pgprot_device(PAGE_KERNEL)); | |
| pgprot_device(PAGE_KERNEL)); | |
| if (ret) { | |
| logic_pio_unregister_range(range); | |
| kfree(range); | |
| } |
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
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().
| fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC); | |
| fwnode = acpi_alloc_fwnode_static(); |
Copilot
AI
Apr 16, 2026
There was a problem hiding this comment.
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.
| 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); |
There was a problem hiding this comment.
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.