Commit 6a479079 authored by Ben Hutchings's avatar Ben Hutchings Committed by Jesse Barnes

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Reviewed-by: default avatarMatthew Wilcox <willy@linux.intel.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent b8d9cb2a
...@@ -294,7 +294,8 @@ NOTE: pci_enable_device() can fail! Check the return value. ...@@ -294,7 +294,8 @@ NOTE: pci_enable_device() can fail! Check the return value.
pci_set_master() will enable DMA by setting the bus master bit pci_set_master() will enable DMA by setting the bus master bit
in the PCI_COMMAND register. It also fixes the latency timer value if in the PCI_COMMAND register. It also fixes the latency timer value if
it's set to something bogus by the BIOS. it's set to something bogus by the BIOS. pci_clear_master() will
disable DMA by clearing the bus master bit.
If the PCI device can use the PCI Memory-Write-Invalidate transaction, If the PCI device can use the PCI Memory-Write-Invalidate transaction,
call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
......
...@@ -1667,6 +1667,22 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) ...@@ -1667,6 +1667,22 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
((1 << 6) - 1), res_name); ((1 << 6) - 1), res_name);
} }
static void __pci_set_master(struct pci_dev *dev, bool enable)
{
u16 old_cmd, cmd;
pci_read_config_word(dev, PCI_COMMAND, &old_cmd);
if (enable)
cmd = old_cmd | PCI_COMMAND_MASTER;
else
cmd = old_cmd & ~PCI_COMMAND_MASTER;
if (cmd != old_cmd) {
dev_dbg(&dev->dev, "%s bus mastering\n",
enable ? "enabling" : "disabling");
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
dev->is_busmaster = enable;
}
/** /**
* pci_set_master - enables bus-mastering for device dev * 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,21 +1691,21 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
* Enables bus-mastering on the device and calls pcibios_set_master() * Enables bus-mastering on the device and calls pcibios_set_master()
* to do the needed arch specific settings. * to do the needed arch specific settings.
*/ */
void void pci_set_master(struct pci_dev *dev)
pci_set_master(struct pci_dev *dev)
{ {
u16 cmd; __pci_set_master(dev, true);
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (! (cmd & PCI_COMMAND_MASTER)) {
dev_dbg(&dev->dev, "enabling bus mastering\n");
cmd |= PCI_COMMAND_MASTER;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
dev->is_busmaster = 1;
pcibios_set_master(dev); pcibios_set_master(dev);
} }
/**
* pci_clear_master - disables bus-mastering for device dev
* @dev: the PCI device to disable
*/
void pci_clear_master(struct pci_dev *dev)
{
__pci_set_master(dev, false);
}
#ifdef PCI_DISABLE_MWI #ifdef PCI_DISABLE_MWI
int pci_set_mwi(struct pci_dev *dev) int pci_set_mwi(struct pci_dev *dev)
{ {
...@@ -2346,6 +2362,7 @@ EXPORT_SYMBOL(pci_release_selected_regions); ...@@ -2346,6 +2362,7 @@ EXPORT_SYMBOL(pci_release_selected_regions);
EXPORT_SYMBOL(pci_request_selected_regions); EXPORT_SYMBOL(pci_request_selected_regions);
EXPORT_SYMBOL(pci_request_selected_regions_exclusive); EXPORT_SYMBOL(pci_request_selected_regions_exclusive);
EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_clear_master);
EXPORT_SYMBOL(pci_set_mwi); EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_try_set_mwi); EXPORT_SYMBOL(pci_try_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi); EXPORT_SYMBOL(pci_clear_mwi);
......
...@@ -642,6 +642,7 @@ static inline int pci_is_managed(struct pci_dev *pdev) ...@@ -642,6 +642,7 @@ static inline int pci_is_managed(struct pci_dev *pdev)
void pci_disable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev);
void pci_set_master(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev);
void pci_clear_master(struct pci_dev *dev);
int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
#define HAVE_PCI_SET_MWI #define HAVE_PCI_SET_MWI
int __must_check pci_set_mwi(struct pci_dev *dev); int __must_check pci_set_mwi(struct pci_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment