From ec5d9e87842a43be3a10ada0d5f560bbd3f31d5d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 29 Feb 2020 23:24:23 +0100 Subject: [PATCH] PCI: Add pci_status_get_and_clear_errors Several drivers use the following code sequence: 1. Read PCI_STATUS 2. Mask out non-error bits 3. Action based on error bits set 4. Write back set error bits to clear them As this is a repeated pattern, add a helper to the PCI core. Signed-off-by: Heiner Kallweit Acked-by: Bjorn Helgaas Signed-off-by: David S. Miller --- drivers/pci/pci.c | 23 +++++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d828ca835a98c..c16b0ba2a895c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -173,6 +173,29 @@ unsigned char pci_bus_max_busnr(struct pci_bus *bus) } EXPORT_SYMBOL_GPL(pci_bus_max_busnr); +/** + * pci_status_get_and_clear_errors - return and clear error bits in PCI_STATUS + * @pdev: the PCI device + * + * Returns error bits set in PCI_STATUS and clears them. + */ +int pci_status_get_and_clear_errors(struct pci_dev *pdev) +{ + u16 status; + int ret; + + ret = pci_read_config_word(pdev, PCI_STATUS, &status); + if (ret != PCIBIOS_SUCCESSFUL) + return -EIO; + + status &= PCI_STATUS_ERROR_BITS; + if (status) + pci_write_config_word(pdev, PCI_STATUS, status); + + return status; +} +EXPORT_SYMBOL_GPL(pci_status_get_and_clear_errors); + #ifdef CONFIG_HAS_IOMEM void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 101d71e0ad0d7..7beaf51e98ec3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1210,6 +1210,7 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags); bool pci_device_is_present(struct pci_dev *pdev); void pci_ignore_hotplug(struct pci_dev *dev); struct pci_dev *pci_real_dma_dev(struct pci_dev *dev); +int pci_status_get_and_clear_errors(struct pci_dev *pdev); int __printf(6, 7) pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler, irq_handler_t thread_fn, void *dev_id, -- 2.39.5