summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2009-02-09 14:53:47 +0800
committerJesse Barnes <jbarnes@hobbes.lan>2009-03-19 19:29:31 -0700
commit5fe5db05f64d0d10b563b1c13b58e4a52b190686 (patch)
tree76f014e83e2246c8d5df81fcdbcdaecc22dfb52f
parent4c9c16867e4980fbd7d1fcc9516c9269ecb4d06f (diff)
downloadop-kernel-dev-5fe5db05f64d0d10b563b1c13b58e4a52b190686.zip
op-kernel-dev-5fe5db05f64d0d10b563b1c13b58e4a52b190686.tar.gz
PCI: Speed up device reset function
For all devices need to do function level reset, currently we need wait for at least 200ms, which can be too long if we have lots of devices... The patch checked pending bit before msleep() to skip some unnecessary sleeping interval. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/pci.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5737b8a..0b3e20f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2028,18 +2028,24 @@ static int __pcie_flr(struct pci_dev *dev, int probe)
pci_block_user_cfg_access(dev);
/* Wait for Transaction Pending bit clean */
+ pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
+ if (!(status & PCI_EXP_DEVSTA_TRPND))
+ goto transaction_done;
+
msleep(100);
pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
- if (status & PCI_EXP_DEVSTA_TRPND) {
- dev_info(&dev->dev, "Busy after 100ms while trying to reset; "
+ if (!(status & PCI_EXP_DEVSTA_TRPND))
+ goto transaction_done;
+
+ dev_info(&dev->dev, "Busy after 100ms while trying to reset; "
"sleeping for 1 second\n");
- ssleep(1);
- pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
- if (status & PCI_EXP_DEVSTA_TRPND)
- dev_info(&dev->dev, "Still busy after 1s; "
+ ssleep(1);
+ pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
+ if (status & PCI_EXP_DEVSTA_TRPND)
+ dev_info(&dev->dev, "Still busy after 1s; "
"proceeding with reset anyway\n");
- }
+transaction_done:
pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_BCR_FLR);
mdelay(100);
@@ -2066,18 +2072,24 @@ static int __pci_af_flr(struct pci_dev *dev, int probe)
pci_block_user_cfg_access(dev);
/* Wait for Transaction Pending bit clean */
+ pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
+ if (!(status & PCI_AF_STATUS_TP))
+ goto transaction_done;
+
msleep(100);
pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
- if (status & PCI_AF_STATUS_TP) {
- dev_info(&dev->dev, "Busy after 100ms while trying to"
- " reset; sleeping for 1 second\n");
- ssleep(1);
- pci_read_config_byte(dev,
- cappos + PCI_AF_STATUS, &status);
- if (status & PCI_AF_STATUS_TP)
- dev_info(&dev->dev, "Still busy after 1s; "
- "proceeding with reset anyway\n");
- }
+ if (!(status & PCI_AF_STATUS_TP))
+ goto transaction_done;
+
+ dev_info(&dev->dev, "Busy after 100ms while trying to"
+ " reset; sleeping for 1 second\n");
+ ssleep(1);
+ pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
+ if (status & PCI_AF_STATUS_TP)
+ dev_info(&dev->dev, "Still busy after 1s; "
+ "proceeding with reset anyway\n");
+
+transaction_done:
pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
mdelay(100);
OpenPOWER on IntegriCloud