On Wed, May 21, 2014 at 03:07:26PM +0200, Alexander Graf wrote:
>
>On 21.05.14 07:03, Gavin Shan wrote:
>>The patch adds new IOCTL command VFIO_EEH_OP to VFIO PCI device
>>to support EEH functionality for PCI devices, which have been
>>passed from host to guest via VFIO.
>>
>>Signed-off-by: Gavin Shan <gws...@linux.vnet.ibm.com>
>>---
>>  Documentation/vfio.txt         |   6 +-
>>  arch/powerpc/include/asm/eeh.h |  10 ++
>>  arch/powerpc/kernel/eeh.c      | 323 
>> +++++++++++++++++++++++++++++++++++++++++
>>  drivers/vfio/pci/vfio_pci.c    |  99 ++++++++++++-
>>  include/uapi/linux/vfio.h      |  43 ++++++
>>  5 files changed, 474 insertions(+), 7 deletions(-)
>>
>>diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt
>>index b9ca023..bb17ec7 100644
>>--- a/Documentation/vfio.txt
>>+++ b/Documentation/vfio.txt
>>@@ -305,7 +305,10 @@ faster, the map/unmap handling has been implemented in 
>>real mode which provides
>>  an excellent performance which has limitations such as inability to do
>>  locked pages accounting in real time.
>>-So 3 additional ioctls have been added:
>>+4) PPC64 guests detect PCI errors and recover from them via EEH RTAS 
>>services,
>>+which works on the basis of additional ioctl command VFIO_EEH_OP.
>>+
>>+So 4 additional ioctls have been added:
>>      VFIO_IOMMU_SPAPR_TCE_GET_INFO - returns the size and the start
>>              of the DMA window on the PCI bus.
>>@@ -316,6 +319,7 @@ So 3 additional ioctls have been added:
>>      VFIO_IOMMU_DISABLE - disables the container.
>>+     VFIO_EEH_OP - EEH dependent operations
>
>Please document exactly what the ioctl does. In an ideal world, a
>VFIO user will just look at the documentation and be able to write a
>program against the API with it.
>

Ok. I'll amend it. Also, I'll split it to 5 ioctl commands in next revision.

>>  The code flow from the example above should be slightly changed:
>>diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
>>index 34a2d83..93922ef 100644
>>--- a/arch/powerpc/include/asm/eeh.h
>>+++ b/arch/powerpc/include/asm/eeh.h
>>@@ -305,6 +305,16 @@ void eeh_add_device_late(struct pci_dev *);
>>  void eeh_add_device_tree_late(struct pci_bus *);
>>  void eeh_add_sysfs_files(struct pci_bus *);
>>  void eeh_remove_device(struct pci_dev *);
>>+#ifdef CONFIG_VFIO_PCI_EEH
>>+int eeh_vfio_open(struct pci_dev *pdev);
>>+void eeh_vfio_release(struct pci_dev *pdev);
>>+int eeh_vfio_set_pe_option(struct pci_dev *pdev, int option, int *retval);
>>+int eeh_vfio_get_pe_addr(struct pci_dev *pdev, int option,
>>+                      int *retval, int *info);
>>+int eeh_vfio_get_pe_state(struct pci_dev *pdev, int *retval, int *state);
>>+int eeh_vfio_reset_pe(struct pci_dev *pdev, int option, int *retval);
>>+int eeh_vfio_configure_pe(struct pci_dev *pdev, int *retval);
>>+#endif
>>  /**
>>   * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
>>diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
>>index 9c6b899..2aaf90e 100644
>>--- a/arch/powerpc/kernel/eeh.c
>>+++ b/arch/powerpc/kernel/eeh.c
>>@@ -1098,6 +1098,329 @@ void eeh_remove_device(struct pci_dev *dev)
>>      edev->mode &= ~EEH_DEV_SYSFS;
>>  }
>>+#ifdef CONFIG_VFIO_PCI_EEH
>>+int eeh_vfio_open(struct pci_dev *pdev)
>
>Why vfio? Also that config option will not be set if vfio is compiled
>as a module.
>

The interface is expected to be used by VFIO-PCI. I'll change the function
names to following ones in next revision. No "VFIO" will be seen :-)

eeh_dev_open();
eeh_dev_release();
static eeh_dev_check();
eeh_pe_set_option();
eeh_pe_get_addr();
eeh_pe_get_state();
eeh_pe_reset();
eeh_pe_configure(); 

Yeah, "#ifdef CONFIG_VFIO_PCI_EEH" can be removed safely in next revision.

>>+{
>>+     struct eeh_dev *edev;
>>+
>>+     /* No PCI device ? */
>>+     if (!pdev)
>>+             return -ENODEV;
>>+
>>+     /* No EEH device ? */
>>+     edev = pci_dev_to_eeh_dev(pdev);
>>+     if (!edev || !edev->pe)
>>+             return -ENODEV;
>>+
>>+     eeh_dev_set_passed(edev, true);
>>+     eeh_pe_set_passed(edev->pe, true);
>>+
>>+     return 0;
>>+}
>>+EXPORT_SYMBOL_GPL(eeh_vfio_open);
>>+
>>+void eeh_vfio_release(struct pci_dev *pdev)
>>+{
>>+     bool release_pe = true;
>>+     struct eeh_pe *pe = NULL;
>>+     struct eeh_dev *tmp, *edev;
>>+
>>+     /* No PCI device ? */
>>+     if (!pdev)
>>+             return;
>>+
>>+     /* No EEH device ? */
>>+     edev = pci_dev_to_eeh_dev(pdev);
>>+     if (!edev || !eeh_dev_passed(edev) ||
>>+         !edev->pe || !eeh_pe_passed(pe))
>>+             return;
>>+
>>+     /* Release device */
>>+     pe = edev->pe;
>>+     eeh_dev_set_passed(edev, false);
>>+
>>+     /* Release PE */
>>+     eeh_pe_for_each_dev(pe, edev, tmp) {
>>+             if (eeh_dev_passed(edev)) {
>>+                     release_pe = false;
>>+                     break;
>>+             }
>>+     }
>>+
>>+     if (release_pe)
>>+             eeh_pe_set_passed(pe, false);
>>+}
>>+EXPORT_SYMBOL(eeh_vfio_release);
>>+
>>+static int eeh_vfio_check_dev(struct pci_dev *pdev,
>>+                           struct eeh_dev **pedev,
>>+                           struct eeh_pe **ppe)
>>+{
>>+     struct eeh_dev *edev;
>>+
>>+     /* No device ? */
>>+     if (!pdev)
>>+             return -ENODEV;
>>+
>>+     edev = pci_dev_to_eeh_dev(pdev);
>>+     if (!edev || !eeh_dev_passed(edev) ||
>>+         !edev->pe || !eeh_pe_passed(edev->pe))
>>+             return -ENODEV;
>>+
>>+     if (pedev)
>>+             *pedev = edev;
>>+     if (ppe)
>>+             *ppe = edev->pe;
>>+
>>+     return 0;
>>+}
>>+
>>+int eeh_vfio_set_pe_option(struct pci_dev *pdev, int option, int *retval)
>>+{
>>+     struct eeh_dev *edev;
>>+     struct eeh_pe *pe;
>>+     int ret = 0;
>>+
>>+     /* Device existing ? */
>>+     ret = eeh_vfio_check_dev(pdev, &edev, &pe);
>>+     if (ret) {
>>+             pr_debug("%s: Cannot find device %s\n",
>>+                     __func__, pdev ? pci_name(pdev) : "NULL");
>>+             *retval = -7;
>
>What are these? Please use proper kernel internal return values for
>errors. I don't want to see anything even remotely tied to RTAS in
>any of these patches.
>

It's the return value for RTAS call "ibm,set-eeh-option". Yeah, it
makes sense to return kernel internal values for errors and will
amend in next revision.

>>+             goto out;
>>+     }
>>+
>>+     /* Invalid option ? */
>>+     if (option < EEH_OPT_DISABLE ||
>>+         option > EEH_OPT_THAW_DMA) {
>
>This is quite confusing to read because it's not obvious what is in
>between these. Just make this a switch() statement that lists the
>allowed options. Gcc will be smart enough to optimize that into a
>bounds check.
>

Ok. Will use "switch()" in next revision.

>>+             pr_debug("%s: Option %d out of range (%d, %d)\n",
>>+                     __func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA);
>>+             *retval = -3;
>>+             ret = -EINVAL;
>>+             goto out;
>>+     }
>>+
>>+     if (option == EEH_OPT_DISABLE ||
>>+         option == EEH_OPT_ENABLE) {
>>+             *retval = 0;
>>+     } else {
>>+             if (!eeh_ops || !eeh_ops->set_option) {
>>+                     *retval = -7;
>>+                     ret = -ENOENT;
>>+                     goto out;
>>+             }
>>+
>>+             ret = eeh_ops->set_option(pe, option);
>>+             if (ret) {
>>+                     pr_debug("%s: Failure %d from backend\n",
>>+                             __func__, ret);
>>+                     *retval = -1;
>>+                     goto out;
>>+             }
>>+
>>+             *retval = 0;
>>+     }
>>+out:
>>+     return ret;
>>+}
>>+EXPORT_SYMBOL_GPL(eeh_vfio_set_pe_option);
>>+
>>+int eeh_vfio_get_pe_addr(struct pci_dev *pdev, int option,
>>+                      int *retval, int *info)
>>+{
>>+     struct pci_bus *bus;
>>+     struct eeh_dev *edev;
>>+     struct eeh_pe *pe;
>>+     int ret = 0;
>>+
>>+     /* Device existing ? */
>>+     ret = eeh_vfio_check_dev(pdev, &edev, &pe);
>>+     if (ret) {
>>+             *retval = -3;
>>+             goto out;
>>+     }
>>+
>>+     /* Invalid option ? */
>>+     if (option != 0 && option != 1) {
>
>0? 1? What? Don't these have names? And again, please use a switch()
>for this function.
>

Will have names in next revision and use "switch()", thanks.

>>+             pr_debug("%s: option %d out of range (0, 1)\n",
>>+                     __func__, option);
>>+             *retval = -3;
>>+             ret = -EINVAL;
>>+             goto out;
>>+     }
>>+
>>+     /*
>>+      * Fill result according to option. We don't differentiate
>>+      * PCI bus and device dependent PE here. So all PEs are
>>+      * built in "shared" mode. Also, the PE address has the format
>>+      * of "00BBSS00".
>>+      */
>>+     if (option == 0) {
>>+             bus = eeh_pe_bus_get(pe);
>>+             if (!bus) {
>>+                     *retval = -3;
>>+                     ret = -ENODEV;
>>+                     goto out;
>>+             }
>>+
>>+             *retval = 0;
>>+             *info = bus->number << 16;
>
>How about positive numbers for the number and negative ones for errors?
>

We needn't carry error numbers by "info" because "retval" or "ret" already
had that information :-)

>>+     } else {
>>+             *retval = 0;
>>+             *info = 1;
>>+     }
>>+out:
>>+     return ret;
>>+}
>>+EXPORT_SYMBOL_GPL(eeh_vfio_get_pe_addr);
>>+
>>+int eeh_vfio_get_pe_state(struct pci_dev *pdev, int *retval, int *state)
>>+{
>>+     struct eeh_dev *edev;
>>+     struct eeh_pe *pe;
>>+     int result, ret = 0;
>>+
>>+     /* Device existing ? */
>>+     ret = eeh_vfio_check_dev(pdev, &edev, &pe);
>>+     if (ret) {
>>+             *retval = -3;
>>+             goto out;
>>+     }
>>+
>>+     if (!eeh_ops || !eeh_ops->get_state) {
>>+             pr_debug("%s: Unsupported request\n",
>>+                     __func__);
>>+             ret = -ENOENT;
>>+             *retval = -3;
>>+             goto out;
>>+     }
>>+
>>+     result = eeh_ops->get_state(pe, NULL);
>>+     if (!(result & EEH_STATE_RESET_ACTIVE) &&
>>+          (result & EEH_STATE_DMA_ENABLED) &&
>>+          (result & EEH_STATE_MMIO_ENABLED))
>>+             *state = 0;
>>+     else if (result & EEH_STATE_RESET_ACTIVE)
>>+             *state = 1;
>>+     else if (!(result & EEH_STATE_RESET_ACTIVE) &&
>>+              !(result & EEH_STATE_DMA_ENABLED) &&
>>+              !(result & EEH_STATE_MMIO_ENABLED))
>>+             *state = 2;
>>+     else if (!(result & EEH_STATE_RESET_ACTIVE) &&
>>+              (result & EEH_STATE_DMA_ENABLED) &&
>>+              !(result & EEH_STATE_MMIO_ENABLED))
>>+             *state = 4;
>>+     else
>>+             *state = 5;
>
>What are these numbers?
>

Will have names in next revision :)

>>+
>>+     *retval = 0;
>>+out:
>>+     return ret;
>>+}
>>+EXPORT_SYMBOL_GPL(eeh_vfio_get_pe_state);
>>+
>>+int eeh_vfio_reset_pe(struct pci_dev *pdev, int option, int *retval)
>>+{
>>+     struct eeh_dev *edev;
>>+     struct eeh_pe *pe;
>>+     int ret = 0;
>>+
>>+     /* Device existing ? */
>>+     ret = eeh_vfio_check_dev(pdev, &edev, &pe);
>>+     if (ret) {
>>+             *retval = -3;
>>+             goto out;
>>+     }
>>+
>>+     /* Invalid option ? */
>>+     if (option != EEH_RESET_DEACTIVATE &&
>>+         option != EEH_RESET_HOT &&
>>+         option != EEH_RESET_FUNDAMENTAL) {
>>+             pr_debug("%s: Unsupported option %d\n",
>>+                     __func__, option);
>>+             ret = -EINVAL;
>>+             *retval = -3;
>>+             goto out;
>>+     }
>>+
>>+     if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset) {
>>+             pr_debug("%s: Unsupported request\n",
>>+                     __func__);
>>+             ret = -ENOENT;
>>+             *retval = -7;
>>+             goto out;
>>+     }
>>+
>>+     ret = eeh_ops->reset(pe, option);
>>+     if (ret) {
>>+             pr_debug("%s: Failure %d from backend\n",
>>+                      __func__, ret);
>>+             *retval = -1;
>>+             goto out;
>>+     }
>>+
>>+     /*
>>+      * The PE is still in frozen state and we need clear that.
>>+      * It's good to clear frozen state after deassert to avoid
>>+      * messy IO access during reset, which might cause recrusive
>
>recursive
>

Thanks.

>>+      * frozen PE.
>>+      */
>>+     if (option == EEH_RESET_DEACTIVATE) {
>>+             ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO);
>>+             if (ret) {
>>+                     pr_debug("%s: Cannot enable IO for PHB#%d-PE#%d (%d)\n",
>>+                             __func__, pe->phb->global_number, pe->addr, 
>>ret);
>>+                     *retval = -1;
>>+                     goto out;
>>+             }
>>+
>>+             ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA);
>>+             if (ret) {
>>+                     pr_debug("%s: Cannot enable DMA for PHB#%d-PE#%d 
>>(%d)\n",
>>+                             __func__, pe->phb->global_number, pe->addr, 
>>ret);
>>+                     *retval = -1;
>>+                     goto out;
>>+             }
>>+
>>+             eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
>>+     }
>>+
>>+     *retval = 0;
>>+out:
>>+     return ret;
>>+}
>>+EXPORT_SYMBOL_GPL(eeh_vfio_reset_pe);
>>+
>>+int eeh_vfio_configure_pe(struct pci_dev *pdev, int *retval)
>>+{
>>+     struct eeh_dev *edev;
>>+     struct eeh_pe *pe;
>>+     int ret = 0;
>>+
>>+     /* Device existing ? */
>>+     ret = eeh_vfio_check_dev(pdev, &edev, &pe);
>>+     if (ret) {
>>+             *retval = -3;
>>+             goto out;
>>+     }
>>+
>>+     /*
>>+      * The access to PCI config space on VFIO device has some
>>+      * limitations. Part of PCI config space, including BAR
>>+      * registers are not readable and writable. So the guest
>>+      * should have stale values for those registers and we have
>>+      * to restore them in host side.
>
>I don't understand this comment. When is "configure_pe" called in the
>first place? Please provide proper function descriptions for each of
>these exported functions that tell someone who may want to use them
>what they do.
>

Yeah, I'll add the description here (also in Documentation/vfio.txt).

>Also, don't mention VFIO or guests in any function inside this file.
>

Ok. I'll avoid mentioning "VFIO" and "guest".

>>+      */
>>+     eeh_pe_restore_bars(pe);
>>+     *retval = 0;
>>+
>>+out:
>>+     return ret;
>>+}
>>+EXPORT_SYMBOL_GPL(eeh_vfio_configure_pe);
>>+
>>+#endif /* CONFIG_VFIO_PCI_EEH */
>>+
>>  static int proc_eeh_show(struct seq_file *m, void *v)
>>  {
>>      if (!eeh_enabled()) {
>>diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
>>index 7ba0424..05c3dde 100644
>>--- a/drivers/vfio/pci/vfio_pci.c
>>+++ b/drivers/vfio/pci/vfio_pci.c
>>@@ -25,6 +25,9 @@
>>  #include <linux/types.h>
>>  #include <linux/uaccess.h>
>>  #include <linux/vfio.h>
>>+#ifdef CONFIG_VFIO_PCI_EEH
>>+#include <asm/eeh.h>
>>+#endif
>>  #include "vfio_pci_private.h"
>>@@ -152,32 +155,57 @@ static void vfio_pci_disable(struct vfio_pci_device 
>>*vdev)
>>      pci_restore_state(pdev);
>>  }
>>+static void vfio_eeh_pci_release(struct pci_dev *pdev)
>>+{
>>+#ifdef CONFIG_VFIO_PCI_EEH
>>+     eeh_vfio_release(pdev);
>>+#endif
>>+}
>>+
>>  static void vfio_pci_release(void *device_data)
>>  {
>>      struct vfio_pci_device *vdev = device_data;
>>-     if (atomic_dec_and_test(&vdev->refcnt))
>>+     if (atomic_dec_and_test(&vdev->refcnt)) {
>>+             vfio_eeh_pci_release(vdev->pdev);
>>              vfio_pci_disable(vdev);
>>+     }
>>      module_put(THIS_MODULE);
>>  }
>>+static int vfio_eeh_pci_open(struct pci_dev *pdev)
>>+{
>>+     int ret = 0;
>>+
>>+#ifdef CONFIG_VFIO_PCI_EEH
>>+     ret = eeh_vfio_open(pdev);
>>+#endif
>>+     return ret;
>>+}
>>+
>>  static int vfio_pci_open(void *device_data)
>>  {
>>      struct vfio_pci_device *vdev = device_data;
>>+     int ret;
>>      if (!try_module_get(THIS_MODULE))
>>              return -ENODEV;
>>      if (atomic_inc_return(&vdev->refcnt) == 1) {
>>-             int ret = vfio_pci_enable(vdev);
>>-             if (ret) {
>>-                     module_put(THIS_MODULE);
>>-                     return ret;
>>-             }
>>+             ret = vfio_pci_enable(vdev);
>>+             if (ret)
>>+                     goto error;
>>+
>>+             ret = vfio_eeh_pci_open(vdev->pdev);
>>+             if (ret)
>>+                     goto error;
>>      }
>>      return 0;
>>+error:
>>+     module_put(THIS_MODULE);
>>+     return ret;
>>  }
>>  static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int 
>> irq_type)
>>@@ -321,6 +349,51 @@ static int vfio_pci_for_each_slot_or_bus(struct pci_dev 
>>*pdev,
>>      return walk.ret;
>>  }
>>+static int vfio_eeh_pci_ioctl(struct pci_dev *pdev, struct vfio_eeh_op *info)
>
>I still don't like the idea of that multiplexing ioctl. I don't see
>any benefit in it whatsoever. Just create 5 individual ioctls with
>their own simple interfaces.
>

Ok. Will split in next revision. Thanks.

>Also, this interface has nothing to do with RTAS. So don't sneak in
>RTAS error numbers anywhere ;). It's QEMU's task to convert from
>kernel error codes to RTAS error codes.
>

Ok. Will do in next revision. Thanks for your comments and time, Alex :-)

Thanks,
Gavin

>>+{
>>+     int ret = 0;
>>+
>>+#ifdef CONFIG_VFIO_PCI_EEH
>>+     switch (info->op) {
>>+     case VFIO_EEH_OP_SET_OPTION:
>>+             ret = eeh_vfio_set_pe_option(pdev,
>>+                                          info->option.option,
>>+                                          &info->option.ret);
>>+             break;
>>+     case VFIO_EEH_OP_GET_ADDR:
>>+             ret = eeh_vfio_get_pe_addr(pdev,
>>+                                        info->addr.option,
>>+                                        &info->addr.ret,
>>+                                        &info->addr.info);
>>+             break;
>>+     case VFIO_EEH_OP_GET_STATE:
>>+             ret = eeh_vfio_get_pe_state(pdev,
>>+                                         &info->state.ret,
>>+                                         &info->state.reset_state);
>>+             info->state.cfg_cap = 1;
>>+             info->state.pe_unavail_info = 1000;
>>+             info->state.pe_recovery_info = 0;
>>+             break;
>>+     case VFIO_EEH_OP_PE_RESET:
>>+             ret = eeh_vfio_reset_pe(pdev,
>>+                                     info->reset.option,
>>+                                     &info->reset.ret);
>>+             break;
>>+     case VFIO_EEH_OP_PE_CONFIG:
>>+             ret = eeh_vfio_configure_pe(pdev,
>>+                                         &info->config.ret);
>>+     default:
>>+             ret = -EINVAL;
>>+             pr_debug("%s: Cannot handle op#%d\n",
>>+                     __func__, info->op);
>>+     }
>>+#else
>>+     ret = -ENOENT;
>>+#endif
>>+
>>+     return ret;
>>+}
>>+
>>  static long vfio_pci_ioctl(void *device_data,
>>                         unsigned int cmd, unsigned long arg)
>>  {
>>@@ -682,6 +755,20 @@ hot_reset_release:
>>              kfree(groups);
>>              return ret;
>>+     } else if (cmd == VFIO_EEH_OP) {
>>+             struct vfio_eeh_op info;
>>+             int ret = 0;
>>+
>>+             minsz = sizeof(info);
>>+             if (copy_from_user(&info, (void __user *)arg, minsz))
>>+                     return -EFAULT;
>>+             if (info.argsz < minsz)
>>+                     return -EINVAL;
>>+
>>+             ret = vfio_eeh_pci_ioctl(vdev->pdev, &info);
>>+             if (copy_to_user((void __user *)arg, &info, minsz))
>>+                     ret = -EFAULT;
>>+             return ret;
>>      }
>>      return -ENOTTY;
>>diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
>>index cb9023d..518961d 100644
>>--- a/include/uapi/linux/vfio.h
>>+++ b/include/uapi/linux/vfio.h
>>@@ -455,6 +455,49 @@ struct vfio_iommu_spapr_tce_info {
>>  #define VFIO_IOMMU_SPAPR_TCE_GET_INFO       _IO(VFIO_TYPE, VFIO_BASE + 12)
>>+/*
>>+ * The VFIO operation struct provides way to support EEH functionality
>>+ * for PCI device that is passed from host to guest via VFIO.
>>+ */
>>+#define VFIO_EEH_OP_SET_OPTION       0
>>+#define VFIO_EEH_OP_GET_ADDR 1
>>+#define VFIO_EEH_OP_GET_STATE        2
>>+#define VFIO_EEH_OP_PE_RESET 3
>>+#define VFIO_EEH_OP_PE_CONFIG        4
>>+
>>+struct vfio_eeh_op {
>>+     __u32 argsz;
>>+     __u32 op;
>>+
>>+     union {
>>+             struct vfio_eeh_set_option {
>>+                     __u32 option;
>>+                     __s32 ret;
>>+             } option;
>>+             struct vfio_eeh_pe_addr {
>>+                     __u32 option;
>>+                     __s32 ret;
>>+                     __u32 info;
>>+             } addr;
>>+             struct vfio_eeh_pe_state {
>>+                     __s32 ret;
>>+                     __u32 reset_state;
>>+                     __u32 cfg_cap;
>>+                     __u32 pe_unavail_info;
>>+                     __u32 pe_recovery_info;
>>+             } state;
>>+             struct vfio_eeh_reset {
>>+                     __u32 option;
>>+                     __s32 ret;
>>+             } reset;
>>+             struct vfio_eeh_config {
>>+                     __s32 ret;
>>+             } config;
>>+     };
>>+};
>>+
>>+#define VFIO_EEH_OP  _IO(VFIO_TYPE, VFIO_BASE + 21)
>>+
>>  /* ***************************************************************** */
>>  #endif /* _UAPIVFIO_H */
>
>--
>To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
>the body of a message to majord...@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to