linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] pci: Wait for up to 1000ms after FLR reset
@ 2016-02-16 20:53 Alex Williamson
  2016-02-19 21:57 ` Alex Williamson
  0 siblings, 1 reply; 2+ messages in thread
From: Alex Williamson @ 2016-02-16 20:53 UTC (permalink / raw)
  To: linux-pci; +Cc: allen.m.kay, linux-kernel, kvm

Some devices take longer than the spec indicates to return from FLR
reset, a notable case of this is Intel integrated graphics (IGD),
which can often take an additional 300ms powering down an attached
LCD panel as part of the FLR.  Allow devices up to 1000ms, testing
every 100ms whether the first dword of config space is read as -1.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

v2: Change loop to incorporate initial 100ms delay, replace delay in
    callee functions, add comment.

 drivers/pci/pci.c |   26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 602eb42..0ce153c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3414,6 +3414,28 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 
+/*
+ * We should only need to wait 100ms after FLR, but some devices take longer.
+ * Wait for up to 1000ms for config space to return something other than -1.
+ * Intel IGD requires this when an LCD panel is attached.
+ */
+static void pci_flr_wait(struct pci_dev *dev)
+{
+	int i = 0;
+	u32 id;
+
+	do {
+		msleep(100);
+		pci_read_config_dword(dev, PCI_VENDOR_ID, &id);
+	} while (i++ < 10 && id == ~0);
+
+	if (id == ~0)
+		dev_warn(&dev->dev, "Failed to return from FLR\n");
+	else if (i > 1)
+		dev_info(&dev->dev, "Required additional "
+			 "%dms to return from FLR\n", (i - 1) * 100);
+}
+
 static int pcie_flr(struct pci_dev *dev, int probe)
 {
 	u32 cap;
@@ -3429,7 +3451,7 @@ static int pcie_flr(struct pci_dev *dev, int probe)
 		dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
 
 	pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-	msleep(100);
+	pci_flr_wait(dev);
 	return 0;
 }
 
@@ -3459,7 +3481,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
 		dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
 
 	pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
-	msleep(100);
+	pci_flr_wait(dev);
 	return 0;
 }
 

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] pci: Wait for up to 1000ms after FLR reset
  2016-02-16 20:53 [PATCH v2] pci: Wait for up to 1000ms after FLR reset Alex Williamson
@ 2016-02-19 21:57 ` Alex Williamson
  0 siblings, 0 replies; 2+ messages in thread
From: Alex Williamson @ 2016-02-19 21:57 UTC (permalink / raw)
  To: linux-pci; +Cc: allen.m.kay, linux-kernel, kvm

On Tue, 16 Feb 2016 13:53:19 -0700
Alex Williamson <alex.williamson@redhat.com> wrote:

> Some devices take longer than the spec indicates to return from FLR
> reset, a notable case of this is Intel integrated graphics (IGD),
> which can often take an additional 300ms powering down an attached
> LCD panel as part of the FLR.  Allow devices up to 1000ms, testing
> every 100ms whether the first dword of config space is read as -1.
> 
> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> ---

Self nak on this one, didn't account for VFs not implementing the first
dword.  Thanks,

Alex
 
> v2: Change loop to incorporate initial 100ms delay, replace delay in
>     callee functions, add comment.
> 
>  drivers/pci/pci.c |   26 ++++++++++++++++++++++++--
>  1 file changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 602eb42..0ce153c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3414,6 +3414,28 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev)
>  }
>  EXPORT_SYMBOL(pci_wait_for_pending_transaction);
>  
> +/*
> + * We should only need to wait 100ms after FLR, but some devices take longer.
> + * Wait for up to 1000ms for config space to return something other than -1.
> + * Intel IGD requires this when an LCD panel is attached.
> + */
> +static void pci_flr_wait(struct pci_dev *dev)
> +{
> +	int i = 0;
> +	u32 id;
> +
> +	do {
> +		msleep(100);
> +		pci_read_config_dword(dev, PCI_VENDOR_ID, &id);
> +	} while (i++ < 10 && id == ~0);
> +
> +	if (id == ~0)
> +		dev_warn(&dev->dev, "Failed to return from FLR\n");
> +	else if (i > 1)
> +		dev_info(&dev->dev, "Required additional "
> +			 "%dms to return from FLR\n", (i - 1) * 100);
> +}
> +
>  static int pcie_flr(struct pci_dev *dev, int probe)
>  {
>  	u32 cap;
> @@ -3429,7 +3451,7 @@ static int pcie_flr(struct pci_dev *dev, int probe)
>  		dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
>  
>  	pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
> -	msleep(100);
> +	pci_flr_wait(dev);
>  	return 0;
>  }
>  
> @@ -3459,7 +3481,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
>  		dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
>  
>  	pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
> -	msleep(100);
> +	pci_flr_wait(dev);
>  	return 0;
>  }
>  
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-02-19 21:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-16 20:53 [PATCH v2] pci: Wait for up to 1000ms after FLR reset Alex Williamson
2016-02-19 21:57 ` Alex Williamson

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).