diff options
author | Isaku Yamahata <yamahata@valinux.co.jp> | 2010-11-19 18:56:03 +0900 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2010-11-22 10:00:07 +0200 |
commit | a5fce077b134a486794b77b49f4eae1d3c9b960c (patch) | |
tree | 62634df303355039bce2770af1b9d8f18b0ee4e7 /hw/pci_bridge.c | |
parent | 9bb3358627d87d8de25fb41b7276575539d799a7 (diff) |
pci bridge: implement secondary bus reset
Trigger secondary bus reset when secondary bus reset bit
value changes from 0 to 1.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/pci_bridge.c')
-rw-r--r-- | hw/pci_bridge.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 58cc2e4cee..464d89708f 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -139,6 +139,10 @@ pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type) void pci_bridge_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len) { + PCIBridge *s = container_of(d, PCIBridge, dev); + uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL); + uint16_t newctl; + pci_default_write_config(d, address, val, len); if (/* io base/limit */ @@ -147,9 +151,14 @@ void pci_bridge_write_config(PCIDevice *d, /* memory base/limit, prefetchable base/limit and io base/limit upper 16 */ ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) { - PCIBridge *s = container_of(d, PCIBridge, dev); pci_bridge_update_mappings(&s->sec_bus); } + + newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL); + if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) { + /* Trigger hot reset on 0->1 transition. */ + pci_bus_reset(&s->sec_bus); + } } void pci_bridge_disable_base_limit(PCIDevice *dev) |