• Maciej W. Rozycki's avatar
    RISC-V: PCI: Avoid handing out address 0 to devices · bb356ddb
    Maciej W. Rozycki authored
    For RISC-V platforms we permit assigning addresses from 0 to PCI devices,
    both in the memory and the I/O bus space, and we happily do so if there
    is no conflict, e.g.:
    
    pci 0000:07:00.0: BAR 0: assigned [io  0x0000-0x0007]
    pci 0000:07:00.1: BAR 0: assigned [io  0x0008-0x000f]
    pci 0000:06:01.0: PCI bridge to [bus 07]
    pci 0000:06:01.0:   bridge window [io  0x0000-0x0fff]
    
    (with the SiFive HiFive Unmatched RISC-V board and a dual serial port
    option card based on the OxSemi OXPCIe952 device wired for the legacy
    UART mode).
    
    Address 0 is treated specially however in many places, for example in
    `pci_iomap_range' and `pci_iomap_wc_range' we require that the start
    address is non-zero, and even if we let such an address through, then
    individual device drivers could reject a request to handle a device at
    such an address, such as in `uart_configure_port'.  Consequently given
    devices configured as shown above only one is actually usable:
    
    Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
    serial 0000:07:00.0: enabling device (0000 -> 0001)
    serial: probe of 0000:07:00.0 failed with error -12
    serial 0000:07:00.1: enabling device (0000 -> 0001)
    serial 0000:07:00.1: detected caps 00000700 should be 00000500
    0000:07:00.1: ttyS0 at I/O 0x8 (irq = 39, base_baud = 15625000) is a 16C950/954
    
    Therefore avoid handing out address 0, by bumping the lowest address
    available to PCI via PCIBIOS_MIN_IO and PCIBIOS_MIN_MEM up by 4 and 16
    respectively, which is the minimum allocation size for I/O and memory
    BARs.
    
    With this in place the system in question we have:
    
    pci 0000:07:00.0: BAR 0: assigned [io  0x1000-0x1007]
    pci 0000:07:00.1: BAR 0: assigned [io  0x1008-0x100f]
    pci 0000:06:01.0: PCI bridge to [bus 07]
    pci 0000:06:01.0:   bridge window [io  0x1000-0x1fff]
    
    and then devices work correctly:
    
    Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
    serial 0000:07:00.0: enabling device (0000 -> 0001)
    serial 0000:07:00.0: detected caps 00000700 should be 00000500
    0000:07:00.0: ttyS0 at I/O 0x1000 (irq = 38, base_baud = 15625000) is a 16C950/954
    serial 0000:07:00.1: enabling device (0000 -> 0001)
    serial 0000:07:00.1: detected caps 00000700 should be 00000500
    0000:07:00.1: ttyS1 at I/O 0x1008 (irq = 39, base_baud = 15625000) is a 16C950/954
    
    Especially I/O space ranges are particularly valuable, because bridges
    only decode bits from 12 up and consequently where 16-bit addressing is
    in effect, as few as 16 separate ranges can be assigned to individual
    buses only, however a generic change to avoid handing out address 0 only
    has turned out controversial as per the discussion referred via the link
    below.
    
    Conversely sorting this out in platform code has been standard practice
    since forever to avoid a clash with legacy devices subtractively decoded
    by the southbridge where present.  This can be revised should a generic
    solution be adopted sometime.
    Signed-off-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
    Link: https://lore.kernel.org/r/alpine.DEB.2.21.2202260044180.25061@angie.orcam.me.ukSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
    bb356ddb
pci.h 1.04 KB