From: Ajay Kaher <akaher@vmware.com>
To: bhelgaas@google.com, helgaas@kernel.org, gregkh@linuxfoundation.org
Cc: ymcavikas@gmail.com, akaher@vmware.com, amakhalov@vmware.com,
anishs@vmware.com, linux-kernel@vger.kernel.org,
linux-pci@vger.kernel.org, srinidhir@vmware.com,
srivatsa@csail.mit.edu, srivatsab@vmware.com,
vsirnapalli@vmware.com, Vikash Bansal <bvikas@vmware.com>
Subject: [PATCH v3] PCI: Speed up device init by parsing capabilities all at once
Date: Wed, 23 Feb 2022 17:04:09 +0530 [thread overview]
Message-ID: <1645616049-19712-1-git-send-email-akaher@vmware.com> (raw)
In-Reply-To: <6827AF44-4412-4ABA-A66B-562D7E86C847@vmware.com>
From: Vikash Bansal <bvikas@vmware.com>
In the current implementation, the PCI capability list is parsed from
the beginning to find each capability, which results in a large number
of redundant PCI reads.
Instead, we can parse the complete list just once, store it in the
pci_dev structure, and get the offset of each capability directly from
the pci_dev structure.
This implementation improves pci devices initialization time by ~2-3%
(from 270ms to 261ms) in case of bare metal and 7-8% (From 201ms to 184ms)
in case of VM running on ESXi.
It also adds a memory overhead of 20bytes (value of PCI_CAP_ID_MAX) per
PCI device.
Ran pahole for pci_dev structure. This patch is not adding any padding
bytes.
Signed-off-by: Vikash Bansal <bvikas@vmware.com>
Signed-off-by: Ajay Kaher <akaher@vmware.com>
---
Changes in v3:
- Added check before access cap_off from pci_find_capability().
- Moved declaration of pci_find_all_capabilities() to drivers/pci/pci.h.
Changes in v2:
- Ran pahole tool.
- Modified comments to add "clock time".
- Removed comments before call to pci_find_all_capabilities.
---
drivers/pci/pci.c | 44 +++++++++++++++++++++++++++++++++++++-------
drivers/pci/pci.h | 1 +
drivers/pci/probe.c | 1 +
include/linux/pci.h | 1 +
4 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3d2fb39..cf54811 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -469,6 +469,40 @@ static u8 __pci_bus_find_cap_start(struct pci_bus *bus,
}
/**
+ * pci_find_all_capabilities - Read all capabilities
+ * @dev: the PCI device
+ *
+ * Read all capabilities and store offsets in cap_off
+ * array in pci_dev structure.
+ */
+void pci_find_all_capabilities(struct pci_dev *dev)
+{
+ int ttl = PCI_FIND_CAP_TTL;
+ u16 ent;
+ u8 pos;
+ u8 id;
+
+ pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
+ if (!pos)
+ return;
+ pci_bus_read_config_byte(dev->bus, dev->devfn, pos, &pos);
+ while (ttl--) {
+ if (pos < 0x40)
+ break;
+ pos &= ~3;
+ pci_bus_read_config_word(dev->bus, dev->devfn, pos, &ent);
+ id = ent & 0xff;
+ if (id == 0xff)
+ break;
+
+ /* Read first instance of capability */
+ if (!(dev->cap_off[id]))
+ dev->cap_off[id] = pos;
+ pos = (ent >> 8);
+ }
+}
+
+/**
* pci_find_capability - query for devices' capabilities
* @dev: PCI device to query
* @cap: capability code
@@ -489,13 +523,9 @@ static u8 __pci_bus_find_cap_start(struct pci_bus *bus,
*/
u8 pci_find_capability(struct pci_dev *dev, int cap)
{
- u8 pos;
-
- pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
- if (pos)
- pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
-
- return pos;
+ if(cap >= PCI_CAP_ID_MAX)
+ return 0;
+ return dev->cap_off[cap];
}
EXPORT_SYMBOL(pci_find_capability);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 3d60cab..3cb70d5 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -87,6 +87,7 @@ bool pci_bridge_d3_possible(struct pci_dev *dev);
void pci_bridge_d3_update(struct pci_dev *dev);
void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev);
void pci_bridge_reconfigure_ltr(struct pci_dev *dev);
+void pci_find_all_capabilities(struct pci_dev *dev);
static inline void pci_wakeup_event(struct pci_dev *dev)
{
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 087d365..d75e1fa 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1839,6 +1839,7 @@ int pci_setup_device(struct pci_dev *dev)
dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal;
+ pci_find_all_capabilities(dev);
set_pcie_port_type(dev);
pci_set_of_node(dev);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 18a75c8..bd61cee 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -326,6 +326,7 @@ struct pci_dev {
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
u8 revision; /* PCI revision, low byte of class word */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
+ u8 cap_off[PCI_CAP_ID_MAX]; /* Offsets of all pci capabilities */
#ifdef CONFIG_PCIEAER
u16 aer_cap; /* AER capability offset */
struct aer_stats *aer_stats; /* AER stats for this device */
--
2.7.4
next prev parent reply other threads:[~2022-02-23 11:50 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-28 4:51 [PATCH v2] PCI: Speed up device init by parsing capabilities all at once Vikash Bansal
2022-02-02 21:35 ` Bjorn Helgaas
2022-02-03 5:52 ` Vikash Bansal
2022-02-23 11:34 ` Ajay Kaher [this message]
2022-05-05 11:27 ` [PATCH v3] " Ajay Kaher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1645616049-19712-1-git-send-email-akaher@vmware.com \
--to=akaher@vmware.com \
--cc=amakhalov@vmware.com \
--cc=anishs@vmware.com \
--cc=bhelgaas@google.com \
--cc=bvikas@vmware.com \
--cc=gregkh@linuxfoundation.org \
--cc=helgaas@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=srinidhir@vmware.com \
--cc=srivatsa@csail.mit.edu \
--cc=srivatsab@vmware.com \
--cc=vsirnapalli@vmware.com \
--cc=ymcavikas@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.