Merge tag 'dt-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[cascardo/linux.git] / drivers / vfio / vfio_spapr_eeh.c
1 /*
2  * EEH functionality support for VFIO devices. The feature is only
3  * available on sPAPR compatible platforms.
4  *
5  * Copyright Gavin Shan, IBM Corporation 2014.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/uaccess.h>
13 #include <linux/vfio.h>
14 #include <asm/eeh.h>
15
16 /* We might build address mapping here for "fast" path later */
17 int vfio_spapr_pci_eeh_open(struct pci_dev *pdev)
18 {
19         return eeh_dev_open(pdev);
20 }
21
22 void vfio_spapr_pci_eeh_release(struct pci_dev *pdev)
23 {
24         eeh_dev_release(pdev);
25 }
26
27 long vfio_spapr_iommu_eeh_ioctl(struct iommu_group *group,
28                                 unsigned int cmd, unsigned long arg)
29 {
30         struct eeh_pe *pe;
31         struct vfio_eeh_pe_op op;
32         unsigned long minsz;
33         long ret = -EINVAL;
34
35         switch (cmd) {
36         case VFIO_CHECK_EXTENSION:
37                 if (arg == VFIO_EEH)
38                         ret = eeh_enabled() ? 1 : 0;
39                 else
40                         ret = 0;
41                 break;
42         case VFIO_EEH_PE_OP:
43                 pe = eeh_iommu_group_to_pe(group);
44                 if (!pe)
45                         return -ENODEV;
46
47                 minsz = offsetofend(struct vfio_eeh_pe_op, op);
48                 if (copy_from_user(&op, (void __user *)arg, minsz))
49                         return -EFAULT;
50                 if (op.argsz < minsz || op.flags)
51                         return -EINVAL;
52
53                 switch (op.op) {
54                 case VFIO_EEH_PE_DISABLE:
55                         ret = eeh_pe_set_option(pe, EEH_OPT_DISABLE);
56                         break;
57                 case VFIO_EEH_PE_ENABLE:
58                         ret = eeh_pe_set_option(pe, EEH_OPT_ENABLE);
59                         break;
60                 case VFIO_EEH_PE_UNFREEZE_IO:
61                         ret = eeh_pe_set_option(pe, EEH_OPT_THAW_MMIO);
62                         break;
63                 case VFIO_EEH_PE_UNFREEZE_DMA:
64                         ret = eeh_pe_set_option(pe, EEH_OPT_THAW_DMA);
65                         break;
66                 case VFIO_EEH_PE_GET_STATE:
67                         ret = eeh_pe_get_state(pe);
68                         break;
69                 case VFIO_EEH_PE_RESET_DEACTIVATE:
70                         ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
71                         break;
72                 case VFIO_EEH_PE_RESET_HOT:
73                         ret = eeh_pe_reset(pe, EEH_RESET_HOT);
74                         break;
75                 case VFIO_EEH_PE_RESET_FUNDAMENTAL:
76                         ret = eeh_pe_reset(pe, EEH_RESET_FUNDAMENTAL);
77                         break;
78                 case VFIO_EEH_PE_CONFIGURE:
79                         ret = eeh_pe_configure(pe);
80                         break;
81                 default:
82                         ret = -EINVAL;
83                 }
84         }
85
86         return ret;
87 }