diff options
author | Yu Zhao <yu.zhao@intel.com> | 2009-06-13 03:52:15 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-06-16 17:30:16 -0400 |
commit | c12ff1df5f114484e3d8abd028769a624cc3399f (patch) | |
tree | 410cb0adf85a52772d5acf6621b421c33b44820a /drivers/pci/pci.c | |
parent | f85876ba82281f15bc4da11e41b94243a8b2b5b4 (diff) |
PCI: support Secondary Bus Reset
PCI-to-PCI Bridge 1.2 specifies that the Secondary Bus Reset bit can
force the assertion of RST# on the secondary interface, which can be
used to reset all devices including subordinates under this bus. This
can be used to reset a function if this function is the only device
under this bus.
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 | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2e58acc66a8c..c56a4a0355a8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2162,6 +2162,33 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) | |||
2162 | return 0; | 2162 | return 0; |
2163 | } | 2163 | } |
2164 | 2164 | ||
2165 | static int pci_parent_bus_reset(struct pci_dev *dev, int probe) | ||
2166 | { | ||
2167 | u16 ctrl; | ||
2168 | struct pci_dev *pdev; | ||
2169 | |||
2170 | if (dev->subordinate) | ||
2171 | return -ENOTTY; | ||
2172 | |||
2173 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | ||
2174 | if (pdev != dev) | ||
2175 | return -ENOTTY; | ||
2176 | |||
2177 | if (probe) | ||
2178 | return 0; | ||
2179 | |||
2180 | pci_read_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, &ctrl); | ||
2181 | ctrl |= PCI_BRIDGE_CTL_BUS_RESET; | ||
2182 | pci_write_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, ctrl); | ||
2183 | msleep(100); | ||
2184 | |||
2185 | ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; | ||
2186 | pci_write_config_word(dev->bus->self, PCI_BRIDGE_CONTROL, ctrl); | ||
2187 | msleep(100); | ||
2188 | |||
2189 | return 0; | ||
2190 | } | ||
2191 | |||
2165 | static int pci_dev_reset(struct pci_dev *dev, int probe) | 2192 | static int pci_dev_reset(struct pci_dev *dev, int probe) |
2166 | { | 2193 | { |
2167 | int rc; | 2194 | int rc; |
@@ -2183,6 +2210,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
2183 | goto done; | 2210 | goto done; |
2184 | 2211 | ||
2185 | rc = pci_pm_reset(dev, probe); | 2212 | rc = pci_pm_reset(dev, probe); |
2213 | if (rc != -ENOTTY) | ||
2214 | goto done; | ||
2215 | |||
2216 | rc = pci_parent_bus_reset(dev, probe); | ||
2186 | done: | 2217 | done: |
2187 | if (!probe) { | 2218 | if (!probe) { |
2188 | up(&dev->dev.sem); | 2219 | up(&dev->dev.sem); |