Question about a quirky (DesignWare) PCIe RC in Allwinner H6

Bjorn Helgaas helgaas at kernel.org
Tue Mar 6 15:38:32 PST 2018


[+cc Marc]

On Tue, Mar 06, 2018 at 11:57:03AM +0800, Icenowy Zheng wrote:
> 在 2018-03-05一的 15:47 -0600,Bjorn Helgaas写道:
> > On Mon, Mar 05, 2018 at 10:50:58PM +0800, Icenowy Zheng wrote:
> > > Hi everyone,
> > > 
> > > I'm trying to implement a driver for the quirky (DW) PCIe RC in the
> > > Allwinner H6 SoC.
> > > 
> > > The quirk is that only the "dbi" space is always mapped, but at the
> > > same time only 64KiB of other spaces (config, downstream IO and
> > > non-
> > > prefetchable memory) are accessible. To access a certain address
> > > the
> > > high 16-bit of the address (all bus addresses in H6 SoC are 32-bit
> > > despite the CPU is 64-bit) needs to be written into the
> > > PCIE_ADDR_PAGE_CFG register (a vendor-defined register in DBI
> > > space).
> > > So the access to these spaces cannot be processed correctly with
> > > just
> > > readl/writel, as the existing code does.
> > > 
> > > Is it possible to workaround this in the PCI subsystem of Linux?
> > > 
> > > (I have thought a workaround that only maps the current accessible
> > > 64KiB with the MMU, and when accessing the non-accessible part,
> > > catch
> > > the page fault and re-setup the map to the new 64KiB page. But
> > > surely
> > > it will kill the performance.)
> > 
> > If you only need to write to PCIE_ADDR_PAGE_CFG for *config*
> > accesses,
> > this should be easy.  All config accesses go through wrappers
> > (pci_read_config_word(), etc) and several host bridge drivers have to
> > update a register with parts of the config address, e.g.,
> > advk_pcie_rd_conf(), mvebu_pcie_hw_rd_conf().
> > 
> > It sounds like you also need to update PCIE_ADDR_PAGE_CFG for I/O
> > port
> > accesses.  I/O port accesses do go through a wrapper (inb(), etc), so
> > it might be possible in principle to intercept these, although much
> > more difficult than config accesses, because the config accesses are
> > already set up with per-host bridge hooks, while the I/O port
> > accessors are mostly per-arch.
> > 
> > But if you have to update PCIE_ADDR_PAGE_CFG for memory accesses,
> > that's really a problem because drivers are allowed to essentially
> > read a memory BAR, convert that bus address to a CPU physical memory
> > address, ioremap() it, then directly access the PCIe memory with
> > loads
> > and stores.
> 
> Unfortunately this is the case. All above (config, IO, memory) needs
> PCIE_ADDR_PAGE_CFG update.

tango_pcie_probe() has a similar issue.  We don't have a good solution
there, so we just live with the fact that the platform will be
unreliable.

Bjorn



More information about the linux-arm-kernel mailing list