[+cc linux-pci] On Tue, Dec 18, 2018 at 12:17:43PM +0100, Koen Vandeputte wrote: > Originally, cns3xxx used it's own functions for mapping, reading and writing registers. > > Commit 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors") > removed the internal PCI config write function in favor of the generic one: > > cns3xxx_pci_write_config() --> pci_generic_config_write() > > cns3xxx_pci_write_config() expected aligned addresses, being produced by cns3xxx_pci_map_bus() > while the generic one pci_generic_config_write() actually expects the real address > as both the function and hardware are capable of byte-aligned writes. > > This currently leads to pci_generic_config_write() writing > to the wrong registers on some ocasions. > > First issue seen due to this: > > - driver ath9k gets loaded > - The driver wants to write value 0xA8 to register PCI_LATENCY_TIMER, located at 0x0D > - cns3xxx_pci_map_bus() aligns the address to 0x0C > - pci_generic_config_write() effectively writes 0xA8 into register 0x0C (CACHE_LINE_SIZE) > > This seems to cause some slight instability when certain PCI devices are used. > > Another issue example caused by this this is the PCI bus numbering, > where the primary bus is higher than the secondary, which is impossible. > > Before: > > 00:00.0 PCI bridge: Cavium, Inc. Device 3400 (rev 01) (prog-if 00 [Normal decode]) > Flags: bus master, fast devsel, latency 0, IRQ 255 > Bus: primary=02, secondary=01, subordinate=ff, sec-latency=0 > > After fix: > > 00:00.0 PCI bridge: Cavium, Inc. Device 3400 (rev 01) (prog-if 00 [Normal decode]) > Flags: bus master, fast devsel, latency 0, IRQ 255 > Bus: primary=00, secondary=01, subordinate=02, sec-latency=0 > > And very likely some more .. > > Fix all by omitting the alignment being done in the mapping function. > > Fixes: 802b7c06adc7 ("ARM: cns3xxx: Convert PCI to use generic config accessors") > Signed-off-by: Koen Vandeputte <koen.vandeputte@xxxxxxxxxxxx> > CC: Arnd Bergmann <arnd@xxxxxxxx> > CC: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> > CC: Krzysztof Halasa <khalasa@xxxxxxx> > CC: Olof Johansson <olof@xxxxxxxxx> > CC: Robin Leblon <robin.leblon@xxxxxxxxxxxx> > CC: Rob Herring <robh@xxxxxxxxxx> > CC: Russell King <linux@xxxxxxxxxxxxxxx> > CC: Tim Harvey <tharvey@xxxxxxxxxxxxx> > CC: stable@xxxxxxxxxxxxxxx # v4.0+ > --- > arch/arm/mach-cns3xxx/pcie.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c > index 318394ed5c7a..5e11ad3164e0 100644 > --- a/arch/arm/mach-cns3xxx/pcie.c > +++ b/arch/arm/mach-cns3xxx/pcie.c > @@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus, > } else /* remote PCI bus */ > base = cnspci->cfg1_regs + ((busno & 0xf) << 20); > > - return base + (where & 0xffc) + (devfn << 12); > + return base + where + (devfn << 12); 802b7c06adc7 replaced cns3xxx_pci_write_config(), which always used __raw_writel() so it only did 32-bit accesses, with pci_generic_config_write(), which uses writeb/writew/writel() depending on the size. 802b7c06adc7 also converted cns3xxx_pci_read_config() from always using __raw_readl() (a 32-bit access) to using pci_generic_config_read32(), which also always does a 32-bit access. This makes me think the cnx3xxx hardware is only capable of 32-bit accesses, and this patch should change the driver to use pci_generic_config_write32() instead of pci_generic_config_write() in addition to the mapping fix above. What do you think? I don't think hardware that only supports 32-bit PCI writes can be quite spec-compliant (see the comments in pci_generic_config_write32()). So (1) you may see an additional dmesg warning when you convert to use it, and (2) it's possible that there may still be instability related to the corruption caused by using a 32-bit write when an 8-bit write was intended. > } > > static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn, > -- > 2.17.1 > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel