# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1229698596 0
# Node ID 2dffa6ceb0af954e7f3a9ad7e993b8aee7b7de65
# Parent 738513b106fa262a11cc3254cd6dd67afb3a63e7
Support S3 for MSI interrupt
From: "Jiang, Yunhong" <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/msi.c | 40 ++++++++++++++++++++++++++++++++++++++++
xen/arch/x86/physdev.c | 18 ++++++++++++++++++
xen/include/asm-x86/msi.h | 1 +
xen/include/public/physdev.h | 9 +++++++++
4 files changed, 68 insertions(+)
diff -r 738513b106fa -r 2dffa6ceb0af xen/arch/x86/msi.c
--- a/xen/arch/x86/msi.c Fri Dec 19 14:52:32 2008 +0000
+++ b/xen/arch/x86/msi.c Fri Dec 19 14:56:36 2008 +0000
@@ -741,3 +741,43 @@ void pci_cleanup_msi(struct pci_dev *pde
msi_free_vectors(pdev);
}
+int pci_restore_msi_state(struct pci_dev *pdev)
+{
+ unsigned long flags;
+ int vector;
+ struct msi_desc *entry, *tmp;
+ irq_desc_t *desc;
+
+ ASSERT(spin_is_locked(&pcidevs_lock));
+
+ if (!pdev)
+ return -EINVAL;
+
+ list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list )
+ {
+ vector = entry->vector;
+ desc = &irq_desc[vector];
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ ASSERT(desc->msi_desc == entry);
+
+ if (desc->msi_desc != entry)
+ {
+ dprintk(XENLOG_ERR, "Restore MSI for dev %x:%x not set before?\n",
+ pdev->bus, pdev->devfn);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return -EINVAL;
+ }
+
+ msi_set_enable(pdev, 0);
+ write_msi_msg(entry, &entry->msg);
+
+ msi_set_enable(pdev, 1);
+ msi_set_mask_bit(vector, entry->msi_attrib.masked);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+
+ return 0;
+}
+
diff -r 738513b106fa -r 2dffa6ceb0af xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c Fri Dec 19 14:52:32 2008 +0000
+++ b/xen/arch/x86/physdev.c Fri Dec 19 14:56:36 2008 +0000
@@ -415,6 +415,24 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+ case PHYSDEVOP_restore_msi: {
+ struct physdev_restore_msi restore_msi;
+ struct pci_dev *pdev;
+
+ ret = -EPERM;
+ if ( !IS_PRIV(v->domain) )
+ break;
+
+ ret = -EFAULT;
+ if ( copy_from_guest(&restore_msi, arg, 1) != 0 )
+ break;
+
+ spin_lock(&pcidevs_lock);
+ pdev = pci_get_pdev(restore_msi.bus, restore_msi.devfn);
+ ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
+ spin_unlock(&pcidevs_lock);
+ break;
+ }
default:
ret = -ENOSYS;
break;
diff -r 738513b106fa -r 2dffa6ceb0af xen/include/asm-x86/msi.h
--- a/xen/include/asm-x86/msi.h Fri Dec 19 14:52:32 2008 +0000
+++ b/xen/include/asm-x86/msi.h Fri Dec 19 14:56:36 2008 +0000
@@ -79,6 +79,7 @@ extern int setup_msi_irq(struct pci_dev
extern int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
extern void teardown_msi_vector(int vector);
extern int msi_free_vector(struct msi_desc *entry);
+extern int pci_restore_msi_state(struct pci_dev *pdev);
struct msi_desc {
struct {
diff -r 738513b106fa -r 2dffa6ceb0af xen/include/public/physdev.h
--- a/xen/include/public/physdev.h Fri Dec 19 14:52:32 2008 +0000
+++ b/xen/include/public/physdev.h Fri Dec 19 14:56:36 2008 +0000
@@ -183,6 +183,15 @@ typedef struct physdev_manage_pci physde
typedef struct physdev_manage_pci physdev_manage_pci_t;
DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t);
+#define PHYSDEVOP_restore_msi 19
+struct physdev_restore_msi {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+};
+typedef struct physdev_restore_msi physdev_restore_msi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
+
/*
* Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
* hypercall since 0x00030202.
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|