On 17/06/26 11:45PM, Junjie Cao wrote:
Hi Shrihari,
On Tue, 9 Jun 2026 16:28:34 +0530, Shrihari E S wrote:
if (flitmode) {
- pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
+ uint32_t pos = dev->exp.exp_cap;
+
+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
PCI_EXP_LNKSTA2_FLIT);
+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
+ PCI_EXP_FLAGS_FLIT);
Following up on Jonathan's observation here -- I'd also noticed a
bogus Interrupt Message Number on a plain flit-mode root port, so I
checked what the stray write actually does to the Flags register.
The impact is wider than just UIO:
The first set_mask writes PCI_EXP_LNKSTA2_FLIT (0x0400) into
PCI_EXP_FLAGS (cap offset 0x02) instead of PCI_EXP_LNKSTA2 (0x32).
0x0400 falls in the Interrupt Message Number field (bits 13:9) of the
Flags register, so a flit-mode port ends up reporting a nonzero
Interrupt Message Number (it reads back as 2).
pcie_cap_fill_lnk() runs for every flit-mode port, and x-256b-flit
defaults to on for pcie-root-port, so even a plain
"-device pcie-root-port" comes up with the corrupted field.
The second line (PCI_EXP_FLAGS_FLIT into Flags) looks correct and
should stay. The first one looks like a typo in the destination
register -- it was PCI_EXP_LNKSTA2 before this series (visible in the
hunk above), so I'd restore it there rather than drop it.
pcie_cap_flit_write_config() does maintain the LNKSTA2 flit bit, but
only on guest LNKCTL writes; it doesn't run at realize/reset, so
dropping the line would leave LNKSTA2 flit status reading 0 at reset
instead of its pre-series value.
Many thanks,
Junjie
Hi Junjie,
Yeah, it's a typo. The destination register should be "PCI_EXP_LNKSTA2".
Thank you for pointing this out. We will rectify it in the next version.
Thanks,