Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: pci-bridge-emul: Extend pci_bridge_emul_init() with flags

Depending on the capabilities of the PCI controller/platform, the
PCI-to-PCI bridge emulation behavior might need to be different. For
example, on platforms that use the pci-mvebu code, we currently don't
support prefetchable memory BARs, so the corresponding fields in the
PCI-to-PCI bridge configuration space should be read-only.

To implement this, extend pci_bridge_emul_init() to take a "flags"
argument, with currently one flag supported:

PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR

that will make the prefetchable memory base and limit registers
read-only.

The pci-mvebu and pci-aardvark drivers are updated accordingly.

Fixes: 1f08673eef123 ("PCI: mvebu: Convert to PCI emulated bridge config space")
Reported-by: Luís Mendes <luis.p.mendes@gmail.com>
Reported-by: Leigh Brown <leigh@solinno.co.uk>
Tested-by: Leigh Brown <leigh@solinno.co.uk>
Tested-by: Luis Mendes <luis.p.mendes@gmail.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: stable@vger.kernel.org
Cc: Luís Mendes <luis.p.mendes@gmail.com>
Cc: Leigh Brown <leigh@solinno.co.uk>

authored by

Thomas Petazzoni and committed by
Lorenzo Pieralisi
33776d05 59f81c35

+15 -4
+1 -1
drivers/pci/controller/pci-aardvark.c
··· 499 499 bridge->data = pcie; 500 500 bridge->ops = &advk_pci_bridge_emul_ops; 501 501 502 - pci_bridge_emul_init(bridge); 502 + pci_bridge_emul_init(bridge, 0); 503 503 504 504 } 505 505
+1 -1
drivers/pci/controller/pci-mvebu.c
··· 583 583 bridge->data = port; 584 584 bridge->ops = &mvebu_pci_bridge_emul_ops; 585 585 586 - pci_bridge_emul_init(bridge); 586 + pci_bridge_emul_init(bridge, PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR); 587 587 } 588 588 589 589 static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys)
+7 -1
drivers/pci/pci-bridge-emul.c
··· 267 267 * (typically at least vendor, device, revision), the ->ops pointer, 268 268 * and optionally ->data and ->has_pcie. 269 269 */ 270 - int pci_bridge_emul_init(struct pci_bridge_emul *bridge) 270 + int pci_bridge_emul_init(struct pci_bridge_emul *bridge, 271 + unsigned int flags) 271 272 { 272 273 bridge->conf.class_revision |= PCI_CLASS_BRIDGE_PCI << 16; 273 274 bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; ··· 294 293 kfree(bridge->pci_regs_behavior); 295 294 return -ENOMEM; 296 295 } 296 + } 297 + 298 + if (flags & PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR) { 299 + bridge->pci_regs_behavior[PCI_PREF_MEMORY_BASE / 4].ro = ~0; 300 + bridge->pci_regs_behavior[PCI_PREF_MEMORY_BASE / 4].rw = 0; 297 301 } 298 302 299 303 return 0;
+6 -1
drivers/pci/pci-bridge-emul.h
··· 119 119 bool has_pcie; 120 120 }; 121 121 122 - int pci_bridge_emul_init(struct pci_bridge_emul *bridge); 122 + enum { 123 + PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR = BIT(0), 124 + }; 125 + 126 + int pci_bridge_emul_init(struct pci_bridge_emul *bridge, 127 + unsigned int flags); 123 128 void pci_bridge_emul_cleanup(struct pci_bridge_emul *bridge); 124 129 125 130 int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,