Skip to content

Commit

Permalink
pci: Add bitmap to know if a pci device has cfg reg filters
Browse files Browse the repository at this point in the history
This avoids doing a search through the list of all devices on
every config space access to every device under a PHB.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
  • Loading branch information
ozbenh authored and stewartsmith committed Jun 6, 2017
1 parent 2589789 commit acd94a9
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 7 deletions.
1 change: 1 addition & 0 deletions core/pci-iov.c
Expand Up @@ -184,6 +184,7 @@ static void pci_iov_init_VF(struct pci_device *pd, struct pci_device *vf)
vf->dn = NULL;
vf->slot = NULL;
vf->parent = pd;
vf->phb = pd->phb;
list_head_init(&vf->pcrf);
list_head_init(&vf->children);
}
Expand Down
10 changes: 10 additions & 0 deletions core/pci.c
Expand Up @@ -247,6 +247,7 @@ static struct pci_device *pci_scan_one(struct phb *phb, struct pci_device *paren
PCIERR(phb, bdfn,"Failed to allocate structure pci_device !\n");
goto fail;
}
pd->phb = phb;
pd->bdfn = bdfn;
pd->vdid = vdid;
pci_cfg_read32(phb, bdfn, PCI_CFG_SUBSYS_VENDOR_ID, &pd->sub_vdid);
Expand Down Expand Up @@ -951,6 +952,9 @@ int64_t pci_register_phb(struct phb *phb, int opal_id)
init_lock(&phb->lock);
list_head_init(&phb->devices);

phb->filter_map = zalloc(BITMAP_BYTES(0x10000));
assert(phb->filter_map);

return OPAL_SUCCESS;
}

Expand Down Expand Up @@ -1764,6 +1768,11 @@ struct pci_cfg_reg_filter *pci_find_cfg_reg_filter(struct pci_device *pd,
return NULL;
}

bool pci_device_has_cfg_reg_filters(struct phb *phb, uint16_t bdfn)
{
return bitmap_tst_bit(*phb->filter_map, bdfn);
}

struct pci_cfg_reg_filter *pci_add_cfg_reg_filter(struct pci_device *pd,
uint32_t start, uint32_t len,
uint32_t flags,
Expand Down Expand Up @@ -1793,6 +1802,7 @@ struct pci_cfg_reg_filter *pci_add_cfg_reg_filter(struct pci_device *pd,
if (pd->pcrf_end < (start + len))
pd->pcrf_end = start + len;
list_add_tail(&pd->pcrf, &pcrf->link);
bitmap_set_bit(*pd->phb->filter_map, pd->bdfn);

return pcrf;
}
9 changes: 2 additions & 7 deletions hw/phb3.c
Expand Up @@ -236,13 +236,8 @@ static void phb3_pcicfg_filter(struct phb *phb, uint32_t bdfn,
return;
}

/* FIXME: It harms the performance to search the PCI
* device which doesn't have any filters at all. So
* it's worthy to maintain a table in PHB to indicate
* the PCI devices who have filters. However, bitmap
* seems not supported by skiboot yet. To implement
* it after bitmap is supported.
*/
if (!pci_device_has_cfg_reg_filters(phb, bdfn))
return;
pd = pci_find_dev(phb, bdfn);
pcrf = pd ? pci_find_cfg_reg_filter(pd, offset, len) : NULL;
if (!pcrf || !pcrf->func)
Expand Down
4 changes: 4 additions & 0 deletions include/pci.h
Expand Up @@ -20,6 +20,7 @@
#include <opal.h>
#include <device.h>
#include <lock.h>
#include <bitmap.h>
#include <ccan/list/list.h>

struct pci_device;
Expand Down Expand Up @@ -87,6 +88,7 @@ struct pci_device {
struct dt_node *dn;
struct pci_slot *slot;
struct pci_device *parent;
struct phb *phb;
struct list_head children;
struct list_node link;
};
Expand Down Expand Up @@ -343,6 +345,7 @@ struct phb {
const struct phb_ops *ops;
struct pci_lsi_state lstate;
uint32_t mps;
bitmap_t *filter_map;

/* PCI-X only slot info, for PCI-E this is in the RC bridge */
struct pci_slot *slot;
Expand Down Expand Up @@ -424,6 +427,7 @@ extern struct pci_device *pci_walk_dev(struct phb *phb,
void *userdata);
extern struct pci_device *pci_find_dev(struct phb *phb, uint16_t bdfn);
extern void pci_restore_bridge_buses(struct phb *phb, struct pci_device *pd);
extern bool pci_device_has_cfg_reg_filters(struct phb *phb, uint16_t bdfn);
extern struct pci_cfg_reg_filter *pci_find_cfg_reg_filter(struct pci_device *pd,
uint32_t start, uint32_t len);
extern struct pci_cfg_reg_filter *pci_add_cfg_reg_filter(struct pci_device *pd,
Expand Down

0 comments on commit acd94a9

Please sign in to comment.