]> Git Repo - qemu.git/commitdiff
s390x/pci: use hashtable to look up zpci via fh
authorYi Min Zhao <[email protected]>
Wed, 9 Nov 2016 13:30:50 +0000 (21:30 +0800)
committerCornelia Huck <[email protected]>
Fri, 20 Jan 2017 09:02:02 +0000 (10:02 +0100)
After PCI multibus is supported, more than 32 PCI devices could be
plugged. The current implementation of s390_pci_find_dev_by_fh()
appears low performance if there's a huge number of PCI devices
plugged. Therefore we introduce a hashtable using idx as key to store
zpci device's pointer on account of translating fh to idx very easily.

Signed-off-by: Yi Min Zhao <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Signed-off-by: Cornelia Huck <[email protected]>
hw/s390x/s390-pci-bus.c
hw/s390x/s390-pci-bus.h

index ce29320592e1c4247687be3ad034d2faa7319240..c2ae01c9a613926459c6119ca87191f95ee1d630 100644 (file)
@@ -227,25 +227,16 @@ static S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
 
 S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx)
 {
-    S390PCIBusDevice *pbdev;
-
-    QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
-        if (pbdev->idx == idx) {
-            return pbdev;
-        }
-    }
-
-    return NULL;
+    return g_hash_table_lookup(s->zpci_table, &idx);
 }
 
 S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh)
 {
-    S390PCIBusDevice *pbdev;
+    uint32_t idx = FH_MASK_INDEX & fh;
+    S390PCIBusDevice *pbdev = s390_pci_find_dev_by_idx(s, idx);
 
-    QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
-        if (pbdev->fh == fh) {
-            return pbdev;
-        }
+    if (pbdev && pbdev->fh == fh) {
+        return pbdev;
     }
 
     return NULL;
@@ -584,6 +575,7 @@ static int s390_pcihost_init(SysBusDevice *dev)
 
     s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
                                            NULL, g_free);
+    s->zpci_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL);
     QTAILQ_INIT(&s->pending_sei);
     QTAILQ_INIT(&s->zpci_devs);
     return 0;
@@ -735,6 +727,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
         }
         pbdev->fh = pbdev->idx;
         QTAILQ_INSERT_TAIL(&s->zpci_devs, pbdev, link);
+        g_hash_table_insert(s->zpci_table, &pbdev->idx, pbdev);
     }
 }
 
@@ -815,6 +808,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
 out:
     pbdev->fid = 0;
     QTAILQ_REMOVE(&s->zpci_devs, pbdev, link);
+    g_hash_table_remove(s->zpci_table, &pbdev->idx);
     object_unparent(OBJECT(pbdev));
 }
 
index fbdc64febf7c659dd90ee6a6ee64f022fe1ebb1e..b82b18eb078fe8730e9ed98552bf9f14927da6ea 100644 (file)
@@ -312,6 +312,7 @@ typedef struct S390pciState {
     uint32_t next_idx;
     S390PCIBus *bus;
     GHashTable *iommu_table;
+    GHashTable *zpci_table;
     QTAILQ_HEAD(, SeiContainer) pending_sei;
     QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
 } S390pciState;
This page took 0.029488 seconds and 4 git commands to generate.