Skip to content

Commit 84aabff

Browse files
committed
Merge branch 'remotes/lorenzo/pci/bridge-emul'
- In an emulated PCI bridge, set Capability offsets so they match the hardware offsets shown by U-Boot (Pali Rohár) * remotes/lorenzo/pci/bridge-emul: PCI: pci-bridge-emul: Set position of PCI capabilities to real HW value
2 parents 9d17bec + 658aea3 commit 84aabff

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
@@ -1081,6 +1081,7 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
10811081
bridge->subsystem_vendor_id = advk_readl(pcie, PCIE_CORE_SSDEV_ID_REG) & 0xffff;
10821082
bridge->subsystem_id = advk_readl(pcie, PCIE_CORE_SSDEV_ID_REG) >> 16;
10831083
bridge->has_pcie = true;
1084+
bridge->pcie_start = PCIE_CORE_PCIEXP_CAP;
10841085
bridge->data = pcie;
10851086
bridge->ops = &advk_pci_bridge_emul_ops;
10861087

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)