Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries/eeh: Fix pseries_eeh_err_inject

VFIO_EEH_PE_INJECT_ERR ioctl is currently failing on pseries
due to missing implementation of err_inject eeh_ops for pseries.
This patch implements pseries_eeh_err_inject in eeh_ops/pseries
eeh_ops. Implements support for injecting MMIO load/store error
for testing from user space.

The check on PCI error type (bus type) code is moved to platform
code, since the eeh_pe_inject_err can be allowed to more error
types depending on platform requirement. Removal of the check for
'type' in eeh_pe_inject_err() doesn't impact PowerNV as
pnv_eeh_err_inject() already has an equivalent check in place.

Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
Reviewed-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20240909140220.529333-1-nnmlinux@linux.ibm.com

authored by

Narayana Murty N and committed by
Michael Ellerman
b0e2b828 8c9c01ce

+44 -5
+1
arch/powerpc/include/asm/eeh.h
··· 308 308 int eeh_pe_configure(struct eeh_pe *pe); 309 309 int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func, 310 310 unsigned long addr, unsigned long mask); 311 + int eeh_pe_inject_mmio_error(struct pci_dev *pdev); 311 312 312 313 /** 313 314 * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
+5 -4
arch/powerpc/kernel/eeh.c
··· 1537 1537 if (!eeh_ops || !eeh_ops->err_inject) 1538 1538 return -ENOENT; 1539 1539 1540 - /* Check on PCI error type */ 1541 - if (type != EEH_ERR_TYPE_32 && type != EEH_ERR_TYPE_64) 1542 - return -EINVAL; 1543 - 1544 1540 /* Check on PCI error function */ 1545 1541 if (func < EEH_ERR_FUNC_MIN || func > EEH_ERR_FUNC_MAX) 1546 1542 return -EINVAL; ··· 1843 1847 .write = eeh_dev_break_write, 1844 1848 .read = eeh_debugfs_dev_usage, 1845 1849 }; 1850 + 1851 + int eeh_pe_inject_mmio_error(struct pci_dev *pdev) 1852 + { 1853 + return eeh_debugfs_break_device(pdev); 1854 + } 1846 1855 1847 1856 static ssize_t eeh_dev_can_recover(struct file *filp, 1848 1857 const char __user *user_buf,
+38 -1
arch/powerpc/platforms/pseries/eeh_pseries.c
··· 784 784 } 785 785 #endif 786 786 787 + /** 788 + * pseries_eeh_err_inject - Inject specified error to the indicated PE 789 + * @pe: the indicated PE 790 + * @type: error type 791 + * @func: specific error type 792 + * @addr: address 793 + * @mask: address mask 794 + * The routine is called to inject specified error, which is 795 + * determined by @type and @func, to the indicated PE 796 + */ 797 + static int pseries_eeh_err_inject(struct eeh_pe *pe, int type, int func, 798 + unsigned long addr, unsigned long mask) 799 + { 800 + struct eeh_dev *pdev; 801 + 802 + /* Check on PCI error type */ 803 + if (type != EEH_ERR_TYPE_32 && type != EEH_ERR_TYPE_64) 804 + return -EINVAL; 805 + 806 + switch (func) { 807 + case EEH_ERR_FUNC_LD_MEM_ADDR: 808 + case EEH_ERR_FUNC_LD_MEM_DATA: 809 + case EEH_ERR_FUNC_ST_MEM_ADDR: 810 + case EEH_ERR_FUNC_ST_MEM_DATA: 811 + /* injects a MMIO error for all pdev's belonging to PE */ 812 + pci_lock_rescan_remove(); 813 + list_for_each_entry(pdev, &pe->edevs, entry) 814 + eeh_pe_inject_mmio_error(pdev->pdev); 815 + pci_unlock_rescan_remove(); 816 + break; 817 + default: 818 + return -ERANGE; 819 + } 820 + 821 + return 0; 822 + } 823 + 787 824 static struct eeh_ops pseries_eeh_ops = { 788 825 .name = "pseries", 789 826 .probe = pseries_eeh_probe, ··· 829 792 .reset = pseries_eeh_reset, 830 793 .get_log = pseries_eeh_get_log, 831 794 .configure_bridge = pseries_eeh_configure_bridge, 832 - .err_inject = NULL, 795 + .err_inject = pseries_eeh_err_inject, 833 796 .read_config = pseries_eeh_read_config, 834 797 .write_config = pseries_eeh_write_config, 835 798 .next_error = NULL,