Skip to content

Commit

Permalink
s390x/pci: optimize calling s390_get_phb()
Browse files Browse the repository at this point in the history
A function may recursively call device search functions or may call
serveral different device search function. Passing the S390pciState to
search functions as an argument instead of looking up it inside the
search functions lowers the number of calling s390_get_phb().

Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com>
Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
  • Loading branch information
Yi Min Zhao authored and cohuck committed Jan 20, 2017
1 parent e70377d commit a975a24
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 50 deletions.
66 changes: 32 additions & 34 deletions hw/s390x/s390-pci-bus.c
Expand Up @@ -31,7 +31,7 @@
do { } while (0)
#endif

static S390pciState *s390_get_phb(void)
S390pciState *s390_get_phb(void)
{
static S390pciState *phb;

Expand Down Expand Up @@ -91,9 +91,9 @@ int chsc_sei_nt2_have_event(void)
return !QTAILQ_EMPTY(&s->pending_sei);
}

S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev)
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev)
{
S390pciState *s = s390_get_phb();
S390PCIBusDevice *ret = pbdev ? QTAILQ_NEXT(pbdev, link) :
QTAILQ_FIRST(&s->zpci_devs);

Expand All @@ -104,10 +104,9 @@ S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev)
return ret;
}

S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid)
{
S390PCIBusDevice *pbdev;
S390pciState *s = s390_get_phb();

QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
if (pbdev->fid == fid) {
Expand All @@ -121,7 +120,8 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
void s390_pci_sclp_configure(SCCB *sccb)
{
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
be32_to_cpu(psccb->aid));
uint16_t rc;

if (be16_to_cpu(sccb->h.length) < 16) {
Expand Down Expand Up @@ -153,7 +153,8 @@ void s390_pci_sclp_configure(SCCB *sccb)
void s390_pci_sclp_deconfigure(SCCB *sccb)
{
PciCfgSccb *psccb = (PciCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid));
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
be32_to_cpu(psccb->aid));
uint16_t rc;

if (be16_to_cpu(sccb->h.length) < 16) {
Expand Down Expand Up @@ -192,10 +193,9 @@ void s390_pci_sclp_deconfigure(SCCB *sccb)
psccb->header.response_code = cpu_to_be16(rc);
}

static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid)
static S390PCIBusDevice *s390_pci_find_dev_by_uid(S390pciState *s, uint16_t uid)
{
S390PCIBusDevice *pbdev;
S390pciState *s = s390_get_phb();

QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
if (pbdev->uid == uid) {
Expand All @@ -206,10 +206,10 @@ static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid)
return NULL;
}

static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
static S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target)
{
S390PCIBusDevice *pbdev;
S390pciState *s = s390_get_phb();

if (!target) {
return NULL;
Expand All @@ -224,10 +224,9 @@ static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
return NULL;
}

S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx)
{
S390PCIBusDevice *pbdev;
S390pciState *s = s390_get_phb();

QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
if (pbdev->idx == idx) {
Expand All @@ -238,9 +237,8 @@ S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
return NULL;
}

S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh)
S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh)
{
S390pciState *s = s390_get_phb();
S390PCIBusDevice *pbdev;

QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
Expand Down Expand Up @@ -544,7 +542,7 @@ void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
object_unparent(OBJECT(&iommu->iommu_mr));
}

static void s390_pci_iommu_free(PCIBus *bus, int32_t devfn)
static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn)
{
uint64_t key = (uintptr_t)bus;
S390PCIIOMMUTable *table = g_hash_table_lookup(s->iommu_table, &key);
Expand Down Expand Up @@ -638,10 +636,10 @@ static void s390_pci_msix_free(S390PCIBusDevice *pbdev)
object_unparent(OBJECT(&pbdev->msix_notify_mr));
}

static S390PCIBusDevice *s390_pci_device_new(const char *target)
static S390PCIBusDevice *s390_pci_device_new(S390pciState *s,
const char *target)
{
DeviceState *dev = NULL;
S390pciState *s = s390_get_phb();

dev = qdev_try_create(BUS(s->bus), TYPE_S390_PCI_DEVICE);
if (!dev) {
Expand All @@ -654,13 +652,12 @@ static S390PCIBusDevice *s390_pci_device_new(const char *target)
return S390_PCI_DEVICE(dev);
}

static bool s390_pci_alloc_idx(S390PCIBusDevice *pbdev)
static bool s390_pci_alloc_idx(S390pciState *s, S390PCIBusDevice *pbdev)
{
uint32_t idx;
S390pciState *s = s390_get_phb();

idx = s->next_idx;
while (s390_pci_find_dev_by_idx(idx)) {
while (s390_pci_find_dev_by_idx(s, idx)) {
idx = (idx + 1) & FH_MASK_INDEX;
if (idx == s->next_idx) {
return false;
Expand Down Expand Up @@ -692,9 +689,9 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
PCI_FUNC(pdev->devfn));
}

pbdev = s390_pci_find_dev_by_target(dev->id);
pbdev = s390_pci_find_dev_by_target(s, dev->id);
if (!pbdev) {
pbdev = s390_pci_device_new(dev->id);
pbdev = s390_pci_device_new(s, dev->id);
if (!pbdev) {
error_setg(errp, "create zpci device failed");
return;
Expand Down Expand Up @@ -722,7 +719,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
} else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
pbdev = S390_PCI_DEVICE(dev);

if (!s390_pci_alloc_idx(pbdev)) {
if (!s390_pci_alloc_idx(s, pbdev)) {
error_setg(errp, "no slot for plugging zpci device");
return;
}
Expand Down Expand Up @@ -799,7 +796,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
devfn = pci_dev->devfn;
object_unparent(OBJECT(pci_dev));
s390_pci_msix_free(pbdev);
s390_pci_iommu_free(bus, devfn);
s390_pci_iommu_free(s, bus, devfn);
pbdev->pdev = NULL;
pbdev->state = ZPCI_FS_RESERVED;
out:
Expand Down Expand Up @@ -838,26 +835,26 @@ static const TypeInfo s390_pcibus_info = {
.instance_size = sizeof(S390PCIBus),
};

static uint16_t s390_pci_generate_uid(void)
static uint16_t s390_pci_generate_uid(S390pciState *s)
{
uint16_t uid = 0;

do {
uid++;
if (!s390_pci_find_dev_by_uid(uid)) {
if (!s390_pci_find_dev_by_uid(s, uid)) {
return uid;
}
} while (uid < ZPCI_MAX_UID);

return UID_UNDEFINED;
}

static uint32_t s390_pci_generate_fid(Error **errp)
static uint32_t s390_pci_generate_fid(S390pciState *s, Error **errp)
{
uint32_t fid = 0;

do {
if (!s390_pci_find_dev_by_fid(fid)) {
if (!s390_pci_find_dev_by_fid(s, fid)) {
return fid;
}
} while (fid++ != ZPCI_MAX_FID);
Expand All @@ -869,38 +866,39 @@ static uint32_t s390_pci_generate_fid(Error **errp)
static void s390_pci_device_realize(DeviceState *dev, Error **errp)
{
S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev);
S390pciState *s = s390_get_phb();

if (!zpci->target) {
error_setg(errp, "target must be defined");
return;
}

if (s390_pci_find_dev_by_target(zpci->target)) {
if (s390_pci_find_dev_by_target(s, zpci->target)) {
error_setg(errp, "target %s already has an associated zpci device",
zpci->target);
return;
}

if (zpci->uid == UID_UNDEFINED) {
zpci->uid = s390_pci_generate_uid();
zpci->uid = s390_pci_generate_uid(s);
if (!zpci->uid) {
error_setg(errp, "no free uid could be found");
return;
}
} else if (s390_pci_find_dev_by_uid(zpci->uid)) {
} else if (s390_pci_find_dev_by_uid(s, zpci->uid)) {
error_setg(errp, "uid %u already in use", zpci->uid);
return;
}

if (!zpci->fid_defined) {
Error *local_error = NULL;

zpci->fid = s390_pci_generate_fid(&local_error);
zpci->fid = s390_pci_generate_fid(s, &local_error);
if (local_error) {
error_propagate(errp, local_error);
return;
}
} else if (s390_pci_find_dev_by_fid(zpci->fid)) {
} else if (s390_pci_find_dev_by_fid(s, zpci->fid)) {
error_setg(errp, "fid %u already in use", zpci->fid);
return;
}
Expand Down
10 changes: 6 additions & 4 deletions hw/s390x/s390-pci-bus.h
Expand Up @@ -316,6 +316,7 @@ typedef struct S390pciState {
QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
} S390pciState;

S390pciState *s390_get_phb(void);
int chsc_sei_nt2_get_event(void *res);
int chsc_sei_nt2_have_event(void);
void s390_pci_sclp_configure(SCCB *sccb);
Expand All @@ -324,9 +325,10 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
void s390_pci_iommu_disable(S390PCIIOMMU *iommu);
void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
uint64_t faddr, uint32_t e);
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev);
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev);

#endif
24 changes: 13 additions & 11 deletions hw/s390x/s390-pci-inst.c
Expand Up @@ -38,6 +38,7 @@ static void s390_set_status_code(CPUS390XState *env,
static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
{
S390PCIBusDevice *pbdev = NULL;
S390pciState *s = s390_get_phb();
uint32_t res_code, initial_l2, g_l2;
int rc, i;
uint64_t resume_token;
Expand Down Expand Up @@ -65,14 +66,14 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
resume_token = ldq_p(&rrb->request.resume_token);

if (resume_token) {
pbdev = s390_pci_find_dev_by_idx(resume_token);
pbdev = s390_pci_find_dev_by_idx(s, resume_token);
if (!pbdev) {
res_code = CLP_RC_LISTPCI_BADRT;
rc = -EINVAL;
goto out;
}
} else {
pbdev = s390_pci_find_next_avail_dev(NULL);
pbdev = s390_pci_find_next_avail_dev(s, NULL);
}

if (lduw_p(&rrb->response.hdr.len) < 48) {
Expand Down Expand Up @@ -118,7 +119,7 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
lduw_p(&rrb->response.fh_list[i].device_id),
ldl_p(&rrb->response.fh_list[i].fid),
ldl_p(&rrb->response.fh_list[i].fh));
pbdev = s390_pci_find_next_avail_dev(pbdev);
pbdev = s390_pci_find_next_avail_dev(s, pbdev);
i++;
}

Expand Down Expand Up @@ -148,6 +149,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
uint8_t buffer[4096 * 2];
uint8_t cc = 0;
CPUS390XState *env = &cpu->env;
S390pciState *s = s390_get_phb();
int i;

cpu_synchronize_state(CPU(cpu));
Expand Down Expand Up @@ -202,7 +204,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
ClpReqSetPci *reqsetpci = (ClpReqSetPci *)reqh;
ClpRspSetPci *ressetpci = (ClpRspSetPci *)resh;

pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqsetpci->fh));
pbdev = s390_pci_find_dev_by_fh(s, ldl_p(&reqsetpci->fh));
if (!pbdev) {
stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FH);
goto out;
Expand Down Expand Up @@ -253,7 +255,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
ClpReqQueryPci *reqquery = (ClpReqQueryPci *)reqh;
ClpRspQueryPci *resquery = (ClpRspQueryPci *)resh;

pbdev = s390_pci_find_dev_by_fh(ldl_p(&reqquery->fh));
pbdev = s390_pci_find_dev_by_fh(s, ldl_p(&reqquery->fh));
if (!pbdev) {
DPRINTF("query pci no pci dev\n");
stw_p(&resquery->hdr.rsp, CLP_RC_SETPCIFN_FH);
Expand Down Expand Up @@ -338,7 +340,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
len = env->regs[r2] & 0xf;
offset = env->regs[r2 + 1];

pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("pcilg no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
Expand Down Expand Up @@ -471,7 +473,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
len = env->regs[r2] & 0xf;
offset = env->regs[r2 + 1];

pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("pcistg no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
Expand Down Expand Up @@ -576,7 +578,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
start = env->regs[r2];
end = start + env->regs[r2 + 1];

pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("rpcit no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
Expand Down Expand Up @@ -679,7 +681,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
return 0;
}

pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("pcistb no pci dev fh 0x%x\n", fh);
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
Expand Down Expand Up @@ -845,7 +847,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
return 0;
}

pbdev = s390_pci_find_dev_by_fh(fh);
pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh);
if (!pbdev) {
DPRINTF("mpcifc no pci dev fh 0x%x\n", fh);
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
Expand Down Expand Up @@ -990,7 +992,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
return 0;
}

pbdev = s390_pci_find_dev_by_idx(fh & FH_MASK_INDEX);
pbdev = s390_pci_find_dev_by_idx(s390_get_phb(), fh & FH_MASK_INDEX);
if (!pbdev) {
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
return 0;
Expand Down
2 changes: 1 addition & 1 deletion target/s390x/kvm.c
Expand Up @@ -2301,7 +2301,7 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
uint32_t vec = data & ZPCI_MSI_VEC_MASK;

pbdev = s390_pci_find_dev_by_idx(idx);
pbdev = s390_pci_find_dev_by_idx(s390_get_phb(), idx);
if (!pbdev) {
DPRINTF("add_msi_route no dev\n");
return -ENODEV;
Expand Down

0 comments on commit a975a24

Please sign in to comment.