From: Bjorn Helgaas <bhelgaas@google.com>
To: Alexander Duyck <alexander.h.duyck@intel.com>
Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
jeffrey.t.kirsher@intel.com
Subject: Re: [PATCH] pci: Save and restore VFs as a part of a reset
Date: Tue, 27 May 2014 16:22:56 -0600 [thread overview]
Message-ID: <20140527222256.GC11907@google.com> (raw)
In-Reply-To: <20140505212346.18767.34117.stgit@ahduyck-cp2.jf.intel.com>
On Mon, May 05, 2014 at 02:25:17PM -0700, Alexander Duyck wrote:
> This fixes an issue I found in which triggering a reset via the PCI sysfs
> reset while SR-IOV was enabled would leave the VFs in a state in which the
> BME and MSI-X enable bits were all cleared.
>
> To correct that I have added code so that the VF state is saved and restored
> as a part of the PF save and restore state functions. By doing this the VF
> state is restored as well as the IOV state allowing the VFs to resume function
> following a reset.
>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
> drivers/pci/iov.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
> drivers/pci/pci.c | 2 ++
> drivers/pci/pci.h | 5 +++++
> 3 files changed, 53 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
> index de7a747..645ed71 100644
> --- a/drivers/pci/iov.c
> +++ b/drivers/pci/iov.c
> @@ -521,13 +521,57 @@ resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
> }
>
> /**
> + * pci_save_iov_state - Save the state of the VF configurations
> + * @dev: the PCI device
> + */
> +int pci_save_iov_state(struct pci_dev *dev)
> +{
> + struct pci_dev *vfdev = NULL;
> + unsigned short dev_id;
> +
> + /* only search if we are a PF */
> + if (!dev->is_physfn)
> + return 0;
> +
> + /* retrieve VF device ID */
> + pci_read_config_word(dev, dev->sriov->pos + PCI_SRIOV_VF_DID, &dev_id);
This is just an optimization to reduce the number of things you get
back from pci_get_device(), and hence reduce the number of times the
"vfdev->is_virtfn && (vfdev->physfn == dev)" condition is false, right?
> + /* loop through all the VFs and save their state information */
> + while ((vfdev = pci_get_device(dev->vendor, dev_id, vfdev))) {
> + if (vfdev->is_virtfn && (vfdev->physfn == dev)) {
> + int err = pci_save_state(vfdev);
It makes me uneasy to operate on another device (we're resetting A, and
here we save state for B). I know B is dependent on A, since B is a VF
related to PF A, but what synchronization is there to serialize this
against any other save/restore operations that may be in progress by B's
driver or by a sysfs operation on B?
Is there anything in the reset path that pays attention to whether
resetting this PF will clobber VFs? Do we care whether those VFs are in
use? I assume they might be in use by guests?
> + if (err)
> + return err;
> + }
> + }
pci_get_device() acquires a reference on each device it returns, so this
strategy would require a pci_dev_put().
But I'm not really keen on pci_get_device() in the first place. It works
by iterating over all PCI devices in the system, which seems like a
sledgehammer approach. It *is* widely used, but mostly in quirk-type code
from which I avert my eyes.
Maybe you could do something based on pci_walk_bus()? If you did that, I
think the PCI_SRIOV_VF_DID would become superfluous.
> +
> + return 0;
> +}
> +
> +/**
> * pci_restore_iov_state - restore the state of the IOV capability
> * @dev: the PCI device
> */
> void pci_restore_iov_state(struct pci_dev *dev)
> {
> - if (dev->is_physfn)
> - sriov_restore_state(dev);
> + struct pci_dev *vfdev = NULL;
> + unsigned short dev_id;
> +
> + if (!dev->is_physfn)
> + return;
> +
> + sriov_restore_state(dev);
> +
> + /* retrieve VF device ID */
> + pci_read_config_word(dev, dev->sriov->pos + PCI_SRIOV_VF_DID, &dev_id);
> +
> + /* loop through all VFs and restore state for any of our VFs */
> + while ((vfdev = pci_get_device(dev->vendor, dev_id, vfdev))) {
> + if (vfdev->is_virtfn && (vfdev->physfn == dev))
> + pci_restore_state(vfdev);
> + }
> +
> + return 0;
> }
>
> /**
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 7325d43..120a432 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1015,6 +1015,8 @@ pci_save_state(struct pci_dev *dev)
> return i;
> if ((i = pci_save_vc_state(dev)) != 0)
> return i;
> + if ((i = pci_save_iov_state(dev)) != 0)
> + return i;
> return 0;
> }
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 6bd0822..9185edd 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -254,6 +254,7 @@ void pci_iov_release(struct pci_dev *dev);
> int pci_iov_resource_bar(struct pci_dev *dev, int resno,
> enum pci_bar_type *type);
> resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
> +int pci_save_iov_state(struct pci_dev *dev);
> void pci_restore_iov_state(struct pci_dev *dev);
> int pci_iov_bus_range(struct pci_bus *bus);
>
> @@ -271,6 +272,10 @@ static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno,
> {
> return 0;
> }
> +static inline void pci_save_iov_state(struct pci_dev *dev)
> +{
> + return 0;
> +}
> static inline void pci_restore_iov_state(struct pci_dev *dev)
> {
> }
>
next prev parent reply other threads:[~2014-05-27 22:23 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-05 21:25 [PATCH] pci: Save and restore VFs as a part of a reset Alexander Duyck
2014-05-27 22:22 ` Bjorn Helgaas [this message]
2014-05-27 23:53 ` Alexander Duyck
2014-05-28 1:19 ` Bjorn Helgaas
2014-05-28 4:12 ` Alex Williamson
2014-05-28 16:39 ` Alexander Duyck
2014-05-28 17:03 ` Alex Williamson
2014-05-28 20:14 ` Bjorn Helgaas
2014-05-28 20:34 ` Don Dutile
2014-05-28 22:23 ` Alexander Duyck
-- strict thread matches above, loose matches on Subject: below --
2014-04-21 17:38 Alexander Duyck
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=20140527222256.GC11907@google.com \
--to=bhelgaas@google.com \
--cc=alexander.h.duyck@intel.com \
--cc=jeffrey.t.kirsher@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).