|
22 | 22 |
|
23 | 23 | #define PCI_BRIDGE_CONF_END PCI_STD_HEADER_SIZEOF
|
24 | 24 | #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) |
27 | 25 | #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) |
30 | 26 |
|
31 | 27 | /**
|
32 | 28 | * 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)
|
324 | 320 | switch (reg) {
|
325 | 321 | case PCI_CAP_LIST_ID:
|
326 | 322 | *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); |
328 | 324 | return PCI_BRIDGE_EMUL_HANDLED;
|
329 | 325 |
|
330 | 326 | case PCI_SSVID_VENDOR_ID:
|
@@ -365,18 +361,33 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
|
365 | 361 | if (!bridge->pci_regs_behavior)
|
366 | 362 | return -ENOMEM;
|
367 | 363 |
|
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); |
374 | 383 |
|
375 | 384 | if (bridge->conf.capabilities_pointer)
|
376 | 385 | bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
|
377 | 386 |
|
378 | 387 | if (bridge->has_pcie) {
|
379 | 388 | 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; |
380 | 391 | bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
|
381 | 392 | bridge->pcie_cap_regs_behavior =
|
382 | 393 | kmemdup(pcie_cap_regs_behavior,
|
@@ -459,15 +470,17 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where,
|
459 | 470 | read_op = bridge->ops->read_base;
|
460 | 471 | cfgspace = (__le32 *) &bridge->conf;
|
461 | 472 | 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) { |
463 | 475 | /* Emulated PCI Bridge Subsystem Vendor ID capability */
|
464 |
| - reg -= PCI_CAP_SSID_START; |
| 476 | + reg -= bridge->ssid_start; |
465 | 477 | read_op = pci_bridge_emul_read_ssid;
|
466 | 478 | cfgspace = NULL;
|
467 | 479 | 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) { |
469 | 482 | /* Our emulated PCIe capability */
|
470 |
| - reg -= PCI_CAP_PCIE_START; |
| 483 | + reg -= bridge->pcie_start; |
471 | 484 | read_op = bridge->ops->read_pcie;
|
472 | 485 | cfgspace = (__le32 *) &bridge->pcie_conf;
|
473 | 486 | behavior = bridge->pcie_cap_regs_behavior;
|
@@ -538,9 +551,10 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where,
|
538 | 551 | write_op = bridge->ops->write_base;
|
539 | 552 | cfgspace = (__le32 *) &bridge->conf;
|
540 | 553 | 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) { |
542 | 556 | /* Our emulated PCIe capability */
|
543 |
| - reg -= PCI_CAP_PCIE_START; |
| 557 | + reg -= bridge->pcie_start; |
544 | 558 | write_op = bridge->ops->write_pcie;
|
545 | 559 | cfgspace = (__le32 *) &bridge->pcie_conf;
|
546 | 560 | behavior = bridge->pcie_cap_regs_behavior;
|
|
0 commit comments