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
|
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)
|
||||||
((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)
|
||||||
* 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);
|
||||||
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)
|
||||||
|
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue