[Skiboot] [PATCH 1/8] pci: Add bitmap to know if a pci device has cfg reg filters
Benjamin Herrenschmidt
benh at kernel.crashing.org
Tue Jun 6 08:59:17 AEST 2017
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 at kernel.crashing.org>
---
core/pci-iov.c | 1 +
core/pci.c | 10 ++++++++++
hw/phb3.c | 9 ++-------
include/pci.h | 4 ++++
4 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/core/pci-iov.c b/core/pci-iov.c
index 14c810b..6abb85a 100644
--- a/core/pci-iov.c
+++ b/core/pci-iov.c
@@ -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);
}
diff --git a/core/pci.c b/core/pci.c
index 0adc6d2..5671b69 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -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);
@@ -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;
}
@@ -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,
@@ -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;
}
diff --git a/hw/phb3.c b/hw/phb3.c
index b33ed7b..c99f1de 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -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)
diff --git a/include/pci.h b/include/pci.h
index dc418a9..1e84b51 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -20,6 +20,7 @@
#include <opal.h>
#include <device.h>
#include <lock.h>
+#include <bitmap.h>
#include <ccan/list/list.h>
struct pci_device;
@@ -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;
};
@@ -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;
@@ -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,
--
2.9.4
More information about the Skiboot
mailing list