ia64/xen-unstable

changeset 18947:2dffa6ceb0af

Support S3 for MSI interrupt

From: "Jiang, Yunhong" <yunhong.jiang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Dec 19 14:56:36 2008 +0000 (2008-12-19)
parents 738513b106fa
children 4d5203f95498
files xen/arch/x86/msi.c xen/arch/x86/physdev.c xen/include/asm-x86/msi.h xen/include/public/physdev.h
line diff
     1.1 --- a/xen/arch/x86/msi.c	Fri Dec 19 14:52:32 2008 +0000
     1.2 +++ b/xen/arch/x86/msi.c	Fri Dec 19 14:56:36 2008 +0000
     1.3 @@ -741,3 +741,43 @@ void pci_cleanup_msi(struct pci_dev *pde
     1.4      msi_free_vectors(pdev);
     1.5  }
     1.6  
     1.7 +int pci_restore_msi_state(struct pci_dev *pdev)
     1.8 +{
     1.9 +    unsigned long flags;
    1.10 +    int vector;
    1.11 +    struct msi_desc *entry, *tmp;
    1.12 +    irq_desc_t *desc;
    1.13 +
    1.14 +    ASSERT(spin_is_locked(&pcidevs_lock));
    1.15 +
    1.16 +    if (!pdev)
    1.17 +        return -EINVAL;
    1.18 +
    1.19 +    list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list )
    1.20 +    {
    1.21 +        vector = entry->vector;
    1.22 +        desc = &irq_desc[vector];
    1.23 +
    1.24 +        spin_lock_irqsave(&desc->lock, flags);
    1.25 +
    1.26 +        ASSERT(desc->msi_desc == entry);
    1.27 +
    1.28 +        if (desc->msi_desc != entry)
    1.29 +        {
    1.30 +            dprintk(XENLOG_ERR, "Restore MSI for dev %x:%x not set before?\n",
    1.31 +                                pdev->bus, pdev->devfn);
    1.32 +            spin_unlock_irqrestore(&desc->lock, flags);
    1.33 +            return -EINVAL;
    1.34 +        }
    1.35 +
    1.36 +        msi_set_enable(pdev, 0);
    1.37 +        write_msi_msg(entry, &entry->msg);
    1.38 +
    1.39 +        msi_set_enable(pdev, 1);
    1.40 +        msi_set_mask_bit(vector, entry->msi_attrib.masked);
    1.41 +        spin_unlock_irqrestore(&desc->lock, flags);
    1.42 +    }
    1.43 +
    1.44 +    return 0;
    1.45 +}
    1.46 +
     2.1 --- a/xen/arch/x86/physdev.c	Fri Dec 19 14:52:32 2008 +0000
     2.2 +++ b/xen/arch/x86/physdev.c	Fri Dec 19 14:56:36 2008 +0000
     2.3 @@ -415,6 +415,24 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
     2.4          break;
     2.5      }
     2.6  
     2.7 +    case PHYSDEVOP_restore_msi: {
     2.8 +        struct physdev_restore_msi restore_msi;
     2.9 +        struct pci_dev *pdev;
    2.10 +
    2.11 +        ret = -EPERM;
    2.12 +        if ( !IS_PRIV(v->domain) )
    2.13 +            break;
    2.14 +
    2.15 +        ret = -EFAULT;
    2.16 +        if ( copy_from_guest(&restore_msi, arg, 1) != 0 )
    2.17 +            break;
    2.18 +
    2.19 +        spin_lock(&pcidevs_lock);
    2.20 +        pdev = pci_get_pdev(restore_msi.bus, restore_msi.devfn);
    2.21 +        ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
    2.22 +        spin_unlock(&pcidevs_lock);
    2.23 +        break;
    2.24 +    }
    2.25      default:
    2.26          ret = -ENOSYS;
    2.27          break;
     3.1 --- a/xen/include/asm-x86/msi.h	Fri Dec 19 14:52:32 2008 +0000
     3.2 +++ b/xen/include/asm-x86/msi.h	Fri Dec 19 14:56:36 2008 +0000
     3.3 @@ -79,6 +79,7 @@ extern void pci_cleanup_msi(struct pci_d
     3.4  extern int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
     3.5  extern void teardown_msi_vector(int vector);
     3.6  extern int msi_free_vector(struct msi_desc *entry);
     3.7 +extern int pci_restore_msi_state(struct pci_dev *pdev);
     3.8  
     3.9  struct msi_desc {
    3.10  	struct {
     4.1 --- a/xen/include/public/physdev.h	Fri Dec 19 14:52:32 2008 +0000
     4.2 +++ b/xen/include/public/physdev.h	Fri Dec 19 14:56:36 2008 +0000
     4.3 @@ -183,6 +183,15 @@ struct physdev_manage_pci {
     4.4  typedef struct physdev_manage_pci physdev_manage_pci_t;
     4.5  DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t);
     4.6  
     4.7 +#define PHYSDEVOP_restore_msi            19
     4.8 +struct physdev_restore_msi {
     4.9 +    /* IN */
    4.10 +    uint8_t bus;
    4.11 +    uint8_t devfn;
    4.12 +};
    4.13 +typedef struct physdev_restore_msi physdev_restore_msi_t;
    4.14 +DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
    4.15 +
    4.16  /*
    4.17   * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
    4.18   * hypercall since 0x00030202.