Skip to content

Commit 6f8bcae

Browse files
inochisaavpatel
authored andcommitted
lib: utils/irqchip: always parse msi information for each aplic device
OpenSBI only parses MSI information of the first next level subdomain for now, which makes the root domain misconfigured in some case: 1. the msi is not enabled on the first subdomain of the root domain, but other subdomains enable MSI. 2. the root domain is set as direct mode, but its subdomains enable MSI. So it is needed to parse all child of the root domain, Otherwise, the some non-root domains are broken. As the specification says, it is safe to parse the MSI information of all its subdomain and write the msiaddrcfg register of the non root domain as they are read only. Parse the aplic MSI information recursively for all aplic device. Reviewed-by: Anup Patel <[email protected]> Signed-off-by: Inochi Amaoto <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
1 parent 771c656 commit 6f8bcae

File tree

1 file changed

+71
-69
lines changed

1 file changed

+71
-69
lines changed

lib/utils/fdt/fdt_helper.c

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -607,13 +607,59 @@ int fdt_parse_xlnx_uartlite_node(const void *fdt, int nodeoffset,
607607
return fdt_parse_uart_node_common(fdt, nodeoffset, uart, 0, 0);
608608
}
609609

610+
static int fdt_aplic_find_imsic_node(const void *fdt, int nodeoff,
611+
struct imsic_data *imsic, bool mmode)
612+
{
613+
const fdt32_t *val;
614+
int i, len, noff, rc;
615+
616+
val = fdt_getprop(fdt, nodeoff, "msi-parent", &len);
617+
if (val && len >= sizeof(fdt32_t)) {
618+
noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
619+
if (noff < 0)
620+
return noff;
621+
622+
rc = fdt_parse_imsic_node(fdt, noff, imsic);
623+
if (rc)
624+
return rc;
625+
626+
rc = imsic_data_check(imsic);
627+
if (rc)
628+
return rc;
629+
630+
if (imsic->targets_mmode == mmode) {
631+
return 0;
632+
}
633+
} else {
634+
return SBI_ENODEV;
635+
}
636+
637+
val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
638+
if (!val || len < sizeof(fdt32_t))
639+
return SBI_ENODEV;
640+
641+
len /= sizeof(fdt32_t);
642+
643+
for (i = 0; i < len; i++) {
644+
noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(val[i]));
645+
if (noff < 0)
646+
return noff;
647+
648+
rc = fdt_aplic_find_imsic_node(fdt, noff, imsic, mmode);
649+
if (!rc)
650+
break;
651+
}
652+
653+
return rc;
654+
}
655+
610656
int fdt_parse_aplic_node(const void *fdt, int nodeoff, struct aplic_data *aplic)
611657
{
612658
bool child_found;
613659
const fdt32_t *val;
614660
const fdt32_t *del;
615661
struct imsic_data imsic = { 0 };
616-
int i, j, d, dcnt, len, noff, rc;
662+
int i, j, d, dcnt, len, rc;
617663
uint64_t reg_addr, reg_size;
618664
struct aplic_delegate_data *deleg;
619665

@@ -640,78 +686,34 @@ int fdt_parse_aplic_node(const void *fdt, int nodeoff, struct aplic_data *aplic)
640686
}
641687
}
642688
aplic->num_idc = len / 2;
643-
goto aplic_msi_parent_done;
644689
}
645690

646-
val = fdt_getprop(fdt, nodeoff, "msi-parent", &len);
647-
if (val && len >= sizeof(fdt32_t)) {
648-
noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
649-
if (noff < 0)
650-
return noff;
651-
652-
rc = fdt_parse_imsic_node(fdt, noff, &imsic);
653-
if (rc)
654-
return rc;
655-
656-
rc = imsic_data_check(&imsic);
657-
if (rc)
658-
return rc;
659-
660-
aplic->targets_mmode = imsic.targets_mmode;
661-
662-
if (imsic.targets_mmode) {
663-
aplic->has_msicfg_mmode = true;
664-
aplic->msicfg_mmode.lhxs = imsic.guest_index_bits;
665-
aplic->msicfg_mmode.lhxw = imsic.hart_index_bits;
666-
aplic->msicfg_mmode.hhxw = imsic.group_index_bits;
667-
aplic->msicfg_mmode.hhxs = imsic.group_index_shift;
668-
if (aplic->msicfg_mmode.hhxs <
669-
(2 * IMSIC_MMIO_PAGE_SHIFT))
670-
return SBI_EINVAL;
671-
aplic->msicfg_mmode.hhxs -= 24;
672-
aplic->msicfg_mmode.base_addr = imsic.regs[0].addr;
673-
} else {
674-
goto aplic_msi_parent_done;
675-
}
676-
677-
val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
678-
if (!val || len < sizeof(fdt32_t))
679-
goto aplic_msi_parent_done;
680-
681-
noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
682-
if (noff < 0)
683-
return noff;
684-
685-
val = fdt_getprop(fdt, noff, "msi-parent", &len);
686-
if (!val || len < sizeof(fdt32_t))
687-
goto aplic_msi_parent_done;
688-
689-
noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
690-
if (noff < 0)
691-
return noff;
692-
693-
rc = fdt_parse_imsic_node(fdt, noff, &imsic);
694-
if (rc)
695-
return rc;
696-
697-
rc = imsic_data_check(&imsic);
698-
if (rc)
699-
return rc;
691+
rc = fdt_aplic_find_imsic_node(fdt, nodeoff, &imsic, true);
692+
if (!rc) {
693+
aplic->targets_mmode = true;
694+
aplic->has_msicfg_mmode = true;
695+
aplic->msicfg_mmode.lhxs = imsic.guest_index_bits;
696+
aplic->msicfg_mmode.lhxw = imsic.hart_index_bits;
697+
aplic->msicfg_mmode.hhxw = imsic.group_index_bits;
698+
aplic->msicfg_mmode.hhxs = imsic.group_index_shift;
699+
if (aplic->msicfg_mmode.hhxs < (2 * IMSIC_MMIO_PAGE_SHIFT))
700+
return SBI_EINVAL;
701+
aplic->msicfg_mmode.hhxs -= 24;
702+
aplic->msicfg_mmode.base_addr = imsic.regs[0].addr;
703+
}
700704

701-
if (!imsic.targets_mmode) {
702-
aplic->has_msicfg_smode = true;
703-
aplic->msicfg_smode.lhxs = imsic.guest_index_bits;
704-
aplic->msicfg_smode.lhxw = imsic.hart_index_bits;
705-
aplic->msicfg_smode.hhxw = imsic.group_index_bits;
706-
aplic->msicfg_smode.hhxs = imsic.group_index_shift;
707-
if (aplic->msicfg_smode.hhxs <
708-
(2 * IMSIC_MMIO_PAGE_SHIFT))
709-
return SBI_EINVAL;
710-
aplic->msicfg_smode.hhxs -= 24;
711-
aplic->msicfg_smode.base_addr = imsic.regs[0].addr;
712-
}
705+
rc = fdt_aplic_find_imsic_node(fdt, nodeoff, &imsic, false);
706+
if (!rc) {
707+
aplic->has_msicfg_smode = true;
708+
aplic->msicfg_smode.lhxs = imsic.guest_index_bits;
709+
aplic->msicfg_smode.lhxw = imsic.hart_index_bits;
710+
aplic->msicfg_smode.hhxw = imsic.group_index_bits;
711+
aplic->msicfg_smode.hhxs = imsic.group_index_shift;
712+
if (aplic->msicfg_smode.hhxs < (2 * IMSIC_MMIO_PAGE_SHIFT))
713+
return SBI_EINVAL;
714+
aplic->msicfg_smode.hhxs -= 24;
715+
aplic->msicfg_smode.base_addr = imsic.regs[0].addr;
713716
}
714-
aplic_msi_parent_done:
715717

716718
for (d = 0; d < APLIC_MAX_DELEGATE; d++) {
717719
deleg = &aplic->delegate[d];

0 commit comments

Comments
 (0)