From: Yi Min Zhao Date: Wed, 9 Nov 2016 13:30:50 +0000 (+0800) Subject: s390x/pci: use hashtable to look up zpci via fh X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=df8dd91b99ed7d27c1cf9a0e6283b2452192d9a1;p=qemu.git s390x/pci: use hashtable to look up zpci via fh 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 Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index ce29320592..c2ae01c9a6 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -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)); } diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index fbdc64febf..b82b18eb07 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -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;