diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 39f19be..179c7dc 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -1244,30 +1244,38 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos)
 #endif
 #endif
 
-static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t address,
+static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev,
+                                                 uint8_t cap_id,
+                                                 uint32_t address,
                                                  uint32_t val, int len)
 {
-    AssignedDevice *assigned_dev = container_of(pci_dev, AssignedDevice, dev);
+    pci_default_cap_write_config(pci_dev, cap_id, address, val, len);
 
-    pci_default_cap_write_config(pci_dev, address, val, len);
+    switch (cap_id) {
 #ifdef KVM_CAP_IRQ_ROUTING
+    case PCI_CAP_ID_MSI:
 #ifdef KVM_CAP_DEVICE_MSI
-    if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
-        int pos = pci_find_capability(pci_dev, PCI_CAP_ID_MSI);
-        if (ranges_overlap(address, len, pos + PCI_MSI_FLAGS, 1)) {
-            assigned_dev_update_msi(pci_dev, pos + PCI_MSI_FLAGS);
+        {
+            uint8_t cap = pci_find_capability(pci_dev, cap_id);
+            if (ranges_overlap(address - cap, len, PCI_MSI_FLAGS, 1)) {
+                assigned_dev_update_msi(pci_dev, cap + PCI_MSI_FLAGS);
+            }
         }
-    }
 #endif
+        break;
+
+    case PCI_CAP_ID_MSIX:
 #ifdef KVM_CAP_DEVICE_MSIX
-    if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
-        int pos = pci_find_capability(pci_dev, PCI_CAP_ID_MSIX);
-        if (ranges_overlap(address, len, pos + PCI_MSIX_FLAGS + 1, 1)) {
-            assigned_dev_update_msix(pci_dev, pos + PCI_MSIX_FLAGS);
-	}
-    }
+        {
+            uint8_t cap = pci_find_capability(pci_dev, cap_id);
+            if (ranges_overlap(address - cap, len, PCI_MSIX_FLAGS + 1, 1)) {
+                assigned_dev_update_msix(pci_dev, cap + PCI_MSIX_FLAGS);
+            }
+        }
 #endif
+        break;
 #endif
+    }
     return;
 }
 
diff --git a/hw/pci.c b/hw/pci.c
index a0a6126..337afc4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1168,10 +1168,11 @@ static uint32_t pci_read_config(PCIDevice *d,
 uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
+    uint8_t cap_id;
     assert(len == 1 || len == 2 || len == 4);
 
-    if (pci_access_cap_config(d, address, len)) {
-        return d->cap.config_read(d, address, len);
+    if ((cap_id = pci_access_cap_config(d, address, len))) {
+        return d->cap.config_read(d, cap_id, address, len);
     }
 
     return pci_read_config(d, address, len);
@@ -1194,13 +1195,13 @@ int pci_access_cap_config(PCIDevice *pci_dev, uint32_t address, int len)
     return pci_dev->cap_map[address];
 }
 
-uint32_t pci_default_cap_read_config(PCIDevice *pci_dev,
+uint32_t pci_default_cap_read_config(PCIDevice *pci_dev, uint8_t cap_id,
                                      uint32_t address, int len)
 {
     return pci_read_config(pci_dev, address, len);
 }
 
-void pci_default_cap_write_config(PCIDevice *pci_dev,
+void pci_default_cap_write_config(PCIDevice *pci_dev, uint8_t cap_id,
                                   uint32_t address, uint32_t val, int len)
 {
     pci_write_config_with_mask(pci_dev, address, val, len);
@@ -1209,9 +1210,10 @@ void pci_default_cap_write_config(PCIDevice *pci_dev,
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
     int was_irq_disabled = pci_irq_disabled(d);
+    uint8_t cap_id;
 
-    if (pci_access_cap_config(d, addr, l)) {
-        d->cap.config_write(d, addr, val, l);
+    if ((cap_id = pci_access_cap_config(d, addr, l))) {
+        d->cap.config_write(d, cap_id, addr, val, l);
         return;
     }
 
diff --git a/hw/pci.h b/hw/pci.h
index 177008a..3f0b4e0 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -83,9 +83,9 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
                                 pcibus_t addr, pcibus_t size, int type);
 typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
-typedef void PCICapConfigWriteFunc(PCIDevice *pci_dev,
+typedef void PCICapConfigWriteFunc(PCIDevice *pci_dev, uint8_t cap_id,
                                    uint32_t address, uint32_t val, int len);
-typedef uint32_t PCICapConfigReadFunc(PCIDevice *pci_dev,
+typedef uint32_t PCICapConfigReadFunc(PCIDevice *pci_dev, uint8_t cap_id,
                                       uint32_t address, int len);
 
 typedef struct PCIIORegion {
@@ -245,9 +245,9 @@ void pci_default_write_config(PCIDevice *d,
                               uint32_t address, uint32_t val, int len);
 void pci_device_save(PCIDevice *s, QEMUFile *f);
 int pci_device_load(PCIDevice *s, QEMUFile *f);
-uint32_t pci_default_cap_read_config(PCIDevice *pci_dev,
+uint32_t pci_default_cap_read_config(PCIDevice *pci_dev, uint8_t cap_id,
                                      uint32_t address, int len);
-void pci_default_cap_write_config(PCIDevice *pci_dev,
+void pci_default_cap_write_config(PCIDevice *pci_dev, uint8_t cap_id,
                                   uint32_t address, uint32_t val, int len);
 int pci_access_cap_config(PCIDevice *pci_dev, uint32_t address, int len);
 
