aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2014-03-05 11:14:34 +0800
committerEli Qiao <taget@linux.vnet.ibm.com>2014-03-05 12:03:47 +0800
commit9762b507ade95f9a7b533e1f1317c0a6d5ad8abf (patch)
tree5920c4c3cdd1c2fc98eb183a75f4c2c838e03c5d
parent35c294c8cedb1ad99c49994d23b1814a3b4ec536 (diff)
downloadpowerkvm-9762b507ade95f9a7b533e1f1317c0a6d5ad8abf.tar.gz
drivers/vfio/pci: Fix MSIx message lost
The problem is specific to the case of BIST issued to IPR adapter on the guest side. The IPR driver does something like this: pci_save_state(), BIST reset and then pci_save_state(). we lose everything in MSIx table with BIST reset and we never have chance to restore MSIx table under the case. pci_restore_msix_state() called by pci_save_state() mask all MSIx vectors by MSIx capability, restore MSIx table, and then unmask all MSIx vectors. We force the host kernel to restore the MSIx vector in the step of unmasking all MSIx vectors to fix the issue. The patch is under review this moment in Linux community. It'd better to have ack from Ben and Alexey if we really want this to be Frobisher. It's responsing to bug#103589. Reported-by: Wen Xiong <wenxiong@us.ibm.com> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 641bc87bdb96a..bbe1ec0469ee3 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/eventfd.h>
#include <linux/pci.h>
+#include <linux/msi.h>
#include <linux/file.h>
#include <linux/poll.h>
#include <linux/vfio.h>
@@ -517,6 +518,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
struct pci_dev *pdev = vdev->pdev;
int irq = msix ? vdev->msix[vector].vector : pdev->irq + vector;
char *name = msix ? "vfio-msix" : "vfio-msi";
+ struct msi_msg msg;
struct eventfd_ctx *trigger;
int ret;
@@ -544,6 +546,23 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
return PTR_ERR(trigger);
}
+ /* We possiblly lose the MSI/MSIx message in some cases.
+ * For example, BIST reset on IPR adapter. The MSIx table
+ * is cleaned out. However, we never get chance to put
+ * MSIx messages to MSIx table because all MSIx stuff is
+ * being cached in QEMU. Here, we had the trick to put the
+ * MSI/MSIx message back.
+ *
+ * Basically, we needn't worry about MSI messages. However,
+ * it's not harmful and there might be cases of PCI config data
+ * lost because of cached PCI config data in QEMU again.
+ *
+ * Note that we should flash the message prior to enabling
+ * the corresponding interrupt by request_irq().
+ */
+ get_cached_msi_msg(irq, &msg);
+ write_msi_msg(irq, &msg);
+
ret = request_irq(irq, vfio_msihandler, 0,
vdev->ctx[vector].name, trigger);
if (ret) {