diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-22 22:08:29 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-01-07 14:13:23 -0500 |
commit | 6a479079c07211bf348ac8a79754f26bea258f26 (patch) | |
tree | 1587c0ed9446c7d0d6ab8a38d1524132e2faae35 | |
parent | b8d9cb2a2226118fd71f657c80b06b670a653022 (diff) |
PCI: Add pci_clear_master() as opposite of pci_set_master()
During an online device reset it may be useful to disable bus-mastering.
pci_disable_device() does that, and far more besides, so is not suitable
for an online reset.
Add pci_clear_master() which does just this.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Reviewed-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r-- | Documentation/PCI/pci.txt | 3 | ||||
-rw-r--r-- | drivers/pci/pci.c | 39 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
3 files changed, 31 insertions, 12 deletions
diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt index fd4907a2968c..7f6de6ea5b47 100644 --- a/Documentation/PCI/pci.txt +++ b/Documentation/PCI/pci.txt | |||
@@ -294,7 +294,8 @@ NOTE: pci_enable_device() can fail! Check the return value. | |||
294 | 294 | ||
295 | pci_set_master() will enable DMA by setting the bus master bit | 295 | pci_set_master() will enable DMA by setting the bus master bit |
296 | in the PCI_COMMAND register. It also fixes the latency timer value if | 296 | in the PCI_COMMAND register. It also fixes the latency timer value if |
297 | it's set to something bogus by the BIOS. | 297 | it's set to something bogus by the BIOS. pci_clear_master() will |
298 | disable DMA by clearing the bus master bit. | ||
298 | 299 | ||
299 | If the PCI device can use the PCI Memory-Write-Invalidate transaction, | 300 | If the PCI device can use the PCI Memory-Write-Invalidate transaction, |
300 | call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval | 301 | call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c824dc8d617c..f3fd55df67db 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1667,6 +1667,22 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) | |||
1667 | ((1 << 6) - 1), res_name); | 1667 | ((1 << 6) - 1), res_name); |
1668 | } | 1668 | } |
1669 | 1669 | ||
1670 | static void __pci_set_master(struct pci_dev *dev, bool enable) | ||
1671 | { | ||
1672 | u16 old_cmd, cmd; | ||
1673 | |||
1674 | pci_read_config_word(dev, PCI_COMMAND, &old_cmd); | ||
1675 | if (enable) | ||
1676 | cmd = old_cmd | PCI_COMMAND_MASTER; | ||
1677 | else | ||
1678 | cmd = old_cmd & ~PCI_COMMAND_MASTER; | ||
1679 | if (cmd != old_cmd) { | ||
1680 | dev_dbg(&dev->dev, "%s bus mastering\n", | ||
1681 | enable ? "enabling" : "disabling"); | ||
1682 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
1683 | } | ||
1684 | dev->is_busmaster = enable; | ||
1685 | } | ||
1670 | 1686 | ||
1671 | /** | 1687 | /** |
1672 | * pci_set_master - enables bus-mastering for device dev | 1688 | * pci_set_master - enables bus-mastering for device dev |
@@ -1675,21 +1691,21 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) | |||
1675 | * Enables bus-mastering on the device and calls pcibios_set_master() | 1691 | * Enables bus-mastering on the device and calls pcibios_set_master() |
1676 | * to do the needed arch specific settings. | 1692 | * to do the needed arch specific settings. |
1677 | */ | 1693 | */ |
1678 | void | 1694 | void pci_set_master(struct pci_dev *dev) |
1679 | pci_set_master(struct pci_dev *dev) | ||
1680 | { | 1695 | { |
1681 | u16 cmd; | 1696 | __pci_set_master(dev, true); |
1682 | |||
1683 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
1684 | if (! (cmd & PCI_COMMAND_MASTER)) { | ||
1685 | dev_dbg(&dev->dev, "enabling bus mastering\n"); | ||
1686 | cmd |= PCI_COMMAND_MASTER; | ||
1687 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
1688 | } | ||
1689 | dev->is_busmaster = 1; | ||
1690 | pcibios_set_master(dev); | 1697 | pcibios_set_master(dev); |
1691 | } | 1698 | } |
1692 | 1699 | ||
1700 | /** | ||
1701 | * pci_clear_master - disables bus-mastering for device dev | ||
1702 | * @dev: the PCI device to disable | ||
1703 | */ | ||
1704 | void pci_clear_master(struct pci_dev *dev) | ||
1705 | { | ||
1706 | __pci_set_master(dev, false); | ||
1707 | } | ||
1708 | |||
1693 | #ifdef PCI_DISABLE_MWI | 1709 | #ifdef PCI_DISABLE_MWI |
1694 | int pci_set_mwi(struct pci_dev *dev) | 1710 | int pci_set_mwi(struct pci_dev *dev) |
1695 | { | 1711 | { |
@@ -2346,6 +2362,7 @@ EXPORT_SYMBOL(pci_release_selected_regions); | |||
2346 | EXPORT_SYMBOL(pci_request_selected_regions); | 2362 | EXPORT_SYMBOL(pci_request_selected_regions); |
2347 | EXPORT_SYMBOL(pci_request_selected_regions_exclusive); | 2363 | EXPORT_SYMBOL(pci_request_selected_regions_exclusive); |
2348 | EXPORT_SYMBOL(pci_set_master); | 2364 | EXPORT_SYMBOL(pci_set_master); |
2365 | EXPORT_SYMBOL(pci_clear_master); | ||
2349 | EXPORT_SYMBOL(pci_set_mwi); | 2366 | EXPORT_SYMBOL(pci_set_mwi); |
2350 | EXPORT_SYMBOL(pci_try_set_mwi); | 2367 | EXPORT_SYMBOL(pci_try_set_mwi); |
2351 | EXPORT_SYMBOL(pci_clear_mwi); | 2368 | EXPORT_SYMBOL(pci_clear_mwi); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 7cbecef19bb6..0f6d2bb1df9c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -642,6 +642,7 @@ static inline int pci_is_managed(struct pci_dev *pdev) | |||
642 | 642 | ||
643 | void pci_disable_device(struct pci_dev *dev); | 643 | void pci_disable_device(struct pci_dev *dev); |
644 | void pci_set_master(struct pci_dev *dev); | 644 | void pci_set_master(struct pci_dev *dev); |
645 | void pci_clear_master(struct pci_dev *dev); | ||
645 | int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); | 646 | int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); |
646 | #define HAVE_PCI_SET_MWI | 647 | #define HAVE_PCI_SET_MWI |
647 | int __must_check pci_set_mwi(struct pci_dev *dev); | 648 | int __must_check pci_set_mwi(struct pci_dev *dev); |