Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * EEH functionality support for VFIO devices. The feature is only
0004  * available on sPAPR compatible platforms.
0005  *
0006  * Copyright Gavin Shan, IBM Corporation 2014.
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/uaccess.h>
0011 #include <linux/vfio.h>
0012 #include <asm/eeh.h>
0013 
0014 #define DRIVER_VERSION  "0.1"
0015 #define DRIVER_AUTHOR   "Gavin Shan, IBM Corporation"
0016 #define DRIVER_DESC "VFIO IOMMU SPAPR EEH"
0017 
0018 /* We might build address mapping here for "fast" path later */
0019 void vfio_spapr_pci_eeh_open(struct pci_dev *pdev)
0020 {
0021     eeh_dev_open(pdev);
0022 }
0023 EXPORT_SYMBOL_GPL(vfio_spapr_pci_eeh_open);
0024 
0025 void vfio_spapr_pci_eeh_release(struct pci_dev *pdev)
0026 {
0027     eeh_dev_release(pdev);
0028 }
0029 EXPORT_SYMBOL_GPL(vfio_spapr_pci_eeh_release);
0030 
0031 long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group,
0032                 unsigned int cmd, unsigned long arg)
0033 {
0034     struct eeh_pe *pe;
0035     struct vfio_eeh_pe_op op;
0036     unsigned long minsz;
0037     long ret = -EINVAL;
0038 
0039     switch (cmd) {
0040     case VFIO_CHECK_EXTENSION:
0041         if (arg == VFIO_EEH)
0042             ret = eeh_enabled() ? 1 : 0;
0043         else
0044             ret = 0;
0045         break;
0046     case VFIO_EEH_PE_OP:
0047         pe = eeh_iommu_group_to_pe(group);
0048         if (!pe)
0049             return -ENODEV;
0050 
0051         minsz = offsetofend(struct vfio_eeh_pe_op, op);
0052         if (copy_from_user(&op, (void __user *)arg, minsz))
0053             return -EFAULT;
0054         if (op.argsz < minsz || op.flags)
0055             return -EINVAL;
0056 
0057         switch (op.op) {
0058         case VFIO_EEH_PE_DISABLE:
0059             ret = eeh_pe_set_option(pe, EEH_OPT_DISABLE);
0060             break;
0061         case VFIO_EEH_PE_ENABLE:
0062             ret = eeh_pe_set_option(pe, EEH_OPT_ENABLE);
0063             break;
0064         case VFIO_EEH_PE_UNFREEZE_IO:
0065             ret = eeh_pe_set_option(pe, EEH_OPT_THAW_MMIO);
0066             break;
0067         case VFIO_EEH_PE_UNFREEZE_DMA:
0068             ret = eeh_pe_set_option(pe, EEH_OPT_THAW_DMA);
0069             break;
0070         case VFIO_EEH_PE_GET_STATE:
0071             ret = eeh_pe_get_state(pe);
0072             break;
0073         case VFIO_EEH_PE_RESET_DEACTIVATE:
0074             ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE, true);
0075             break;
0076         case VFIO_EEH_PE_RESET_HOT:
0077             ret = eeh_pe_reset(pe, EEH_RESET_HOT, true);
0078             break;
0079         case VFIO_EEH_PE_RESET_FUNDAMENTAL:
0080             ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL, true);
0081             break;
0082         case VFIO_EEH_PE_CONFIGURE:
0083             ret = eeh_pe_configure(pe);
0084             break;
0085         case VFIO_EEH_PE_INJECT_ERR:
0086             minsz = offsetofend(struct vfio_eeh_pe_op, err.mask);
0087             if (op.argsz < minsz)
0088                 return -EINVAL;
0089             if (copy_from_user(&op, (void __user *)arg, minsz))
0090                 return -EFAULT;
0091 
0092             ret = eeh_pe_inject_err(pe, op.err.type, op.err.func,
0093                         op.err.addr, op.err.mask);
0094             break;
0095         default:
0096             ret = -EINVAL;
0097         }
0098     }
0099 
0100     return ret;
0101 }
0102 EXPORT_SYMBOL_GPL(vfio_spapr_iommu_eeh_ioctl);
0103 
0104 MODULE_VERSION(DRIVER_VERSION);
0105 MODULE_LICENSE("GPL v2");
0106 MODULE_AUTHOR(DRIVER_AUTHOR);
0107 MODULE_DESCRIPTION(DRIVER_DESC);