diff options
author | Yu Zhao <yu.zhao@intel.com> | 2009-06-13 03:52:14 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-06-16 17:30:16 -0400 |
commit | f85876ba82281f15bc4da11e41b94243a8b2b5b4 (patch) | |
tree | 8a2b9143123a8aa319bbe2e3078d8ea65aeb77da /drivers/pci/pci.c | |
parent | 8c1c699fec9e9021bf6ff0285dee086bb27aec90 (diff) |
PCI: support PM D0hot->D3 transition reset
PCI PM 1.2 specifies that the device will perform an internal reset upon
transitioning from D3hot to D0 when the NO_SOFT_RESET bit is clear. This
method can be used to reset a function if neither PCIe FLR nor PCI AF FLR
are supported.
Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Yu Zhao <yu.zhao@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6a052ada3fe8..2e58acc66a8c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2132,6 +2132,36 @@ clear: | |||
2132 | return 0; | 2132 | return 0; |
2133 | } | 2133 | } |
2134 | 2134 | ||
2135 | static int pci_pm_reset(struct pci_dev *dev, int probe) | ||
2136 | { | ||
2137 | u16 csr; | ||
2138 | |||
2139 | if (!dev->pm_cap) | ||
2140 | return -ENOTTY; | ||
2141 | |||
2142 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); | ||
2143 | if (csr & PCI_PM_CTRL_NO_SOFT_RESET) | ||
2144 | return -ENOTTY; | ||
2145 | |||
2146 | if (probe) | ||
2147 | return 0; | ||
2148 | |||
2149 | if (dev->current_state != PCI_D0) | ||
2150 | return -EINVAL; | ||
2151 | |||
2152 | csr &= ~PCI_PM_CTRL_STATE_MASK; | ||
2153 | csr |= PCI_D3hot; | ||
2154 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); | ||
2155 | msleep(pci_pm_d3_delay); | ||
2156 | |||
2157 | csr &= ~PCI_PM_CTRL_STATE_MASK; | ||
2158 | csr |= PCI_D0; | ||
2159 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); | ||
2160 | msleep(pci_pm_d3_delay); | ||
2161 | |||
2162 | return 0; | ||
2163 | } | ||
2164 | |||
2135 | static int pci_dev_reset(struct pci_dev *dev, int probe) | 2165 | static int pci_dev_reset(struct pci_dev *dev, int probe) |
2136 | { | 2166 | { |
2137 | int rc; | 2167 | int rc; |
@@ -2149,6 +2179,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
2149 | goto done; | 2179 | goto done; |
2150 | 2180 | ||
2151 | rc = pci_af_flr(dev, probe); | 2181 | rc = pci_af_flr(dev, probe); |
2182 | if (rc != -ENOTTY) | ||
2183 | goto done; | ||
2184 | |||
2185 | rc = pci_pm_reset(dev, probe); | ||
2152 | done: | 2186 | done: |
2153 | if (!probe) { | 2187 | if (!probe) { |
2154 | up(&dev->dev.sem); | 2188 | up(&dev->dev.sem); |