Skip to content

Commit 658aea3

Browse files
paliLorenzo Pieralisi
authored andcommitted
PCI: pci-bridge-emul: Set position of PCI capabilities to real HW value
mvebu and aardvark HW have PCIe capabilities on different offset in PCI config space. Extend pci-bridge-emul.c code to allow setting custom driver custom value where PCIe capabilities starts. With this change PCIe capabilities of both drivers are reported at the same location as where they are reported by U-Boot - in their real HW offset. Link: https://lore.kernel.org/r/20220824112124.21675-1-pali@kernel.org Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
1 parent 568035b commit 658aea3

File tree

4 files changed

+35
-17
lines changed

4 files changed

+35
-17
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,7 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
10781078
bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
10791079

10801080
bridge->has_pcie = true;
1081+
bridge->pcie_start = PCIE_CORE_PCIEXP_CAP;
10811082
bridge->data = pcie;
10821083
bridge->ops = &advk_pci_bridge_emul_ops;
10831084

drivers/pci/controller/pci-mvebu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
946946
bridge->subsystem_vendor_id = ssdev_id & 0xffff;
947947
bridge->subsystem_id = ssdev_id >> 16;
948948
bridge->has_pcie = true;
949+
bridge->pcie_start = PCIE_CAP_PCIEXP;
949950
bridge->data = port;
950951
bridge->ops = &mvebu_pci_bridge_emul_ops;
951952

drivers/pci/pci-bridge-emul.c

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@
2222

2323
#define PCI_BRIDGE_CONF_END PCI_STD_HEADER_SIZEOF
2424
#define PCI_CAP_SSID_SIZEOF (PCI_SSVID_DEVICE_ID + 2)
25-
#define PCI_CAP_SSID_START PCI_BRIDGE_CONF_END
26-
#define PCI_CAP_SSID_END (PCI_CAP_SSID_START + PCI_CAP_SSID_SIZEOF)
2725
#define PCI_CAP_PCIE_SIZEOF (PCI_EXP_SLTSTA2 + 2)
28-
#define PCI_CAP_PCIE_START PCI_CAP_SSID_END
29-
#define PCI_CAP_PCIE_END (PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
3026

3127
/**
3228
* struct pci_bridge_reg_behavior - register bits behaviors
@@ -324,7 +320,7 @@ pci_bridge_emul_read_ssid(struct pci_bridge_emul *bridge, int reg, u32 *value)
324320
switch (reg) {
325321
case PCI_CAP_LIST_ID:
326322
*value = PCI_CAP_ID_SSVID |
327-
(bridge->has_pcie ? (PCI_CAP_PCIE_START << 8) : 0);
323+
((bridge->pcie_start > bridge->ssid_start) ? (bridge->pcie_start << 8) : 0);
328324
return PCI_BRIDGE_EMUL_HANDLED;
329325

330326
case PCI_SSVID_VENDOR_ID:
@@ -365,18 +361,33 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
365361
if (!bridge->pci_regs_behavior)
366362
return -ENOMEM;
367363

368-
if (bridge->subsystem_vendor_id)
369-
bridge->conf.capabilities_pointer = PCI_CAP_SSID_START;
370-
else if (bridge->has_pcie)
371-
bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
372-
else
373-
bridge->conf.capabilities_pointer = 0;
364+
/* If ssid_start and pcie_start were not specified then choose the lowest possible value. */
365+
if (!bridge->ssid_start && !bridge->pcie_start) {
366+
if (bridge->subsystem_vendor_id)
367+
bridge->ssid_start = PCI_BRIDGE_CONF_END;
368+
if (bridge->has_pcie)
369+
bridge->pcie_start = bridge->ssid_start + PCI_CAP_SSID_SIZEOF;
370+
} else if (!bridge->ssid_start && bridge->subsystem_vendor_id) {
371+
if (bridge->pcie_start - PCI_BRIDGE_CONF_END >= PCI_CAP_SSID_SIZEOF)
372+
bridge->ssid_start = PCI_BRIDGE_CONF_END;
373+
else
374+
bridge->ssid_start = bridge->pcie_start + PCI_CAP_PCIE_SIZEOF;
375+
} else if (!bridge->pcie_start && bridge->has_pcie) {
376+
if (bridge->ssid_start - PCI_BRIDGE_CONF_END >= PCI_CAP_PCIE_SIZEOF)
377+
bridge->pcie_start = PCI_BRIDGE_CONF_END;
378+
else
379+
bridge->pcie_start = bridge->ssid_start + PCI_CAP_SSID_SIZEOF;
380+
}
381+
382+
bridge->conf.capabilities_pointer = min(bridge->ssid_start, bridge->pcie_start);
374383

375384
if (bridge->conf.capabilities_pointer)
376385
bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
377386

378387
if (bridge->has_pcie) {
379388
bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
389+
bridge->pcie_conf.next = (bridge->ssid_start > bridge->pcie_start) ?
390+
bridge->ssid_start : 0;
380391
bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
381392
bridge->pcie_cap_regs_behavior =
382393
kmemdup(pcie_cap_regs_behavior,
@@ -459,15 +470,17 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
459470
read_op = bridge->ops->read_base;
460471
cfgspace = (__le32 *) &bridge->conf;
461472
behavior = bridge->pci_regs_behavior;
462-
} else if (reg >= PCI_CAP_SSID_START && reg < PCI_CAP_SSID_END && bridge->subsystem_vendor_id) {
473+
} else if (reg >= bridge->ssid_start && reg < bridge->ssid_start + PCI_CAP_SSID_SIZEOF &&
474+
bridge->subsystem_vendor_id) {
463475
/* Emulated PCI Bridge Subsystem Vendor ID capability */
464-
reg -= PCI_CAP_SSID_START;
476+
reg -= bridge->ssid_start;
465477
read_op = pci_bridge_emul_read_ssid;
466478
cfgspace = NULL;
467479
behavior = NULL;
468-
} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
480+
} else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF &&
481+
bridge->has_pcie) {
469482
/* Our emulated PCIe capability */
470-
reg -= PCI_CAP_PCIE_START;
483+
reg -= bridge->pcie_start;
471484
read_op = bridge->ops->read_pcie;
472485
cfgspace = (__le32 *) &bridge->pcie_conf;
473486
behavior = bridge->pcie_cap_regs_behavior;
@@ -538,9 +551,10 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
538551
write_op = bridge->ops->write_base;
539552
cfgspace = (__le32 *) &bridge->conf;
540553
behavior = bridge->pci_regs_behavior;
541-
} else if (reg >= PCI_CAP_PCIE_START && reg < PCI_CAP_PCIE_END && bridge->has_pcie) {
554+
} else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF &&
555+
bridge->has_pcie) {
542556
/* Our emulated PCIe capability */
543-
reg -= PCI_CAP_PCIE_START;
557+
reg -= bridge->pcie_start;
544558
write_op = bridge->ops->write_pcie;
545559
cfgspace = (__le32 *) &bridge->pcie_conf;
546560
behavior = bridge->pcie_cap_regs_behavior;

drivers/pci/pci-bridge-emul.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ struct pci_bridge_emul {
131131
struct pci_bridge_reg_behavior *pci_regs_behavior;
132132
struct pci_bridge_reg_behavior *pcie_cap_regs_behavior;
133133
void *data;
134+
u8 pcie_start;
135+
u8 ssid_start;
134136
bool has_pcie;
135137
u16 subsystem_vendor_id;
136138
u16 subsystem_id;

0 commit comments

Comments
 (0)