There are various way to do function granularity reset. PCI-e and PCI Advanced Feature have Function Level Reset(FLR) support. Introduce __pci_check_reset_function_cap() to find out which method device supported to reset the function. Signed-off-by: Sheng Yang <sheng@xxxxxxxxxxxxxxx> --- drivers/pci/pci.c | 46 ++++++++++++++++++++++++++++++---------------- 1 files changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9adf1ad..ad89c74 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1751,6 +1751,22 @@ int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask) EXPORT_SYMBOL(pci_set_dma_seg_boundary); #endif +#define PCI_RESET_FUNC_CAP_PCIE_FLR 0 +static int __pci_check_reset_function_cap(struct pci_dev *dev) +{ + int cappos; + u32 cap; + + cappos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (cappos) { + pci_read_config_dword(dev, cappos + PCI_EXP_DEVCAP, &cap); + if (cap & PCI_EXP_DEVCAP_FLR) + return PCI_RESET_FUNC_CAP_PCIE_FLR; + } + + return -ENOTTY; +} + static int __pcie_flr(struct pci_dev *dev) { int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP); @@ -1801,21 +1817,23 @@ static int __pcie_flr(struct pci_dev *dev) */ int pci_execute_reset_function(struct pci_dev *dev) { - u32 cap; - int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP); + int reset_cap; + int r; - if (!exppos) - return -ENOTTY; - pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap); - if (!(cap & PCI_EXP_DEVCAP_FLR)) - return -ENOTTY; + reset_cap = __pci_check_reset_function_cap(dev); + if (reset_cap < 0) + return reset_cap; + r = 0; pci_block_user_cfg_access(dev); - __pcie_flr(dev); + if (reset_cap == PCI_RESET_FUNC_CAP_PCIE_FLR) + r = __pcie_flr(dev); + else + r = -ENOTTY; pci_unblock_user_cfg_access(dev); - return 0; + return r; } EXPORT_SYMBOL_GPL(pci_execute_reset_function); @@ -1837,15 +1855,11 @@ EXPORT_SYMBOL_GPL(pci_execute_reset_function); */ int pci_reset_function(struct pci_dev *dev) { - u32 cap; - int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP); int r; - if (!exppos) - return -ENOTTY; - pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap); - if (!(cap & PCI_EXP_DEVCAP_FLR)) - return -ENOTTY; + r = __pci_check_reset_function_cap(dev); + if (r < 0) + return r; if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) disable_irq(dev->irq); -- 1.5.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html