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>
This commit is contained in:
parent
b8d9cb2a22
commit
6a479079c0
3 changed files with 31 additions and 12 deletions
|
@ -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
|
||||
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,
|
||||
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)
|
|||
((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
|
||||
|
@ -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()
|
||||
* to do the needed arch specific settings.
|
||||
*/
|
||||
void
|
||||
pci_set_master(struct pci_dev *dev)
|
||||
void pci_set_master(struct pci_dev *dev)
|
||||
{
|
||||
u16 cmd;
|
||||
|
||||
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;
|
||||
__pci_set_master(dev, true);
|
||||
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
|
||||
int pci_set_mwi(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -2346,6 +2362,7 @@ EXPORT_SYMBOL(pci_release_selected_regions);
|
|||
EXPORT_SYMBOL(pci_request_selected_regions);
|
||||
EXPORT_SYMBOL(pci_request_selected_regions_exclusive);
|
||||
EXPORT_SYMBOL(pci_set_master);
|
||||
EXPORT_SYMBOL(pci_clear_master);
|
||||
EXPORT_SYMBOL(pci_set_mwi);
|
||||
EXPORT_SYMBOL(pci_try_set_mwi);
|
||||
EXPORT_SYMBOL(pci_clear_mwi);
|
||||
|
|
|
@ -642,6 +642,7 @@ static inline int pci_is_managed(struct pci_dev *pdev)
|
|||
|
||||
void pci_disable_device(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);
|
||||
#define HAVE_PCI_SET_MWI
|
||||
int __must_check pci_set_mwi(struct pci_dev *dev);
|
||||
|
|
Loading…
Reference in a new issue