ia64/linux-2.6.18-xen.hg

changeset 529:9f9b4214bec8

MSI 6/6: add MSI support to domain0/domainU

Signed-off-by: Jiang Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Shan Haitao <haitao.shan@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 01 10:35:30 2008 +0100 (2008-05-01)
parents 81c5a517a42b
children 3da869d5095b
files drivers/pci/Kconfig drivers/pci/msi-xen.c drivers/pci/msi.h drivers/xen/pciback/Makefile drivers/xen/pciback/conf_space_capability_msi.c drivers/xen/pciback/pci_stub.c drivers/xen/pciback/pciback.h drivers/xen/pciback/pciback_ops.c drivers/xen/pcifront/pci_op.c include/asm-i386/io_apic.h include/asm-x86_64/io_apic.h include/asm-x86_64/msi.h include/linux/pci.h include/xen/evtchn.h include/xen/interface/io/pciif.h include/xen/interface/physdev.h
line diff
     1.1 --- a/drivers/pci/Kconfig	Tue Apr 22 18:56:27 2008 +0100
     1.2 +++ b/drivers/pci/Kconfig	Thu May 01 10:35:30 2008 +0100
     1.3 @@ -5,7 +5,6 @@ config PCI_MSI
     1.4  	bool "Message Signaled Interrupts (MSI and MSI-X)"
     1.5  	depends on PCI
     1.6  	depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
     1.7 -	depends on !XEN
     1.8  	help
     1.9  	   This allows device drivers to enable MSI (Message Signaled
    1.10  	   Interrupts).  Message Signaled Interrupts enable a device to
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/drivers/pci/msi-xen.c	Thu May 01 10:35:30 2008 +0100
     2.3 @@ -0,0 +1,710 @@
     2.4 +/*
     2.5 + * File:	msi.c
     2.6 + * Purpose:	PCI Message Signaled Interrupt (MSI)
     2.7 + *
     2.8 + * Copyright (C) 2003-2004 Intel
     2.9 + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
    2.10 + */
    2.11 +
    2.12 +#include <linux/mm.h>
    2.13 +#include <linux/irq.h>
    2.14 +#include <linux/interrupt.h>
    2.15 +#include <linux/init.h>
    2.16 +#include <linux/ioport.h>
    2.17 +#include <linux/smp_lock.h>
    2.18 +#include <linux/pci.h>
    2.19 +#include <linux/proc_fs.h>
    2.20 +
    2.21 +#include <asm/errno.h>
    2.22 +#include <asm/io.h>
    2.23 +#include <asm/smp.h>
    2.24 +
    2.25 +#include "pci.h"
    2.26 +#include "msi.h"
    2.27 +
    2.28 +static int pci_msi_enable = 1;
    2.29 +
    2.30 +static struct msi_ops *msi_ops;
    2.31 +
    2.32 +int msi_register(struct msi_ops *ops)
    2.33 +{
    2.34 +	msi_ops = ops;
    2.35 +	return 0;
    2.36 +}
    2.37 +
    2.38 +static struct list_head msi_dev_head;
    2.39 +static int msi_dev_head_inited = 0;
    2.40 +DEFINE_SPINLOCK(msi_dev_lock);
    2.41 +
    2.42 +struct msi_dev_list {
    2.43 +	struct pci_dev *dev;
    2.44 +	struct list_head list;
    2.45 +	spinlock_t pirq_list_lock;
    2.46 +	struct list_head pirq_list_head;
    2.47 +};
    2.48 +
    2.49 +struct msi_pirq_entry {
    2.50 +	struct list_head list;
    2.51 +	int pirq;
    2.52 +	int entry_nr;
    2.53 +};
    2.54 +
    2.55 +static struct msi_dev_list *get_msi_dev_pirq_list(struct pci_dev *dev)
    2.56 +{
    2.57 +	struct msi_dev_list *msi_dev_list, *ret = NULL;
    2.58 +	unsigned long flags;
    2.59 +
    2.60 +	if (!msi_dev_head_inited) {
    2.61 +		INIT_LIST_HEAD(&msi_dev_head);
    2.62 +		msi_dev_head_inited = 1;
    2.63 +	}
    2.64 +
    2.65 +	spin_lock_irqsave(&msi_dev_lock, flags);
    2.66 +
    2.67 +	list_for_each_entry(msi_dev_list, &msi_dev_head, list)
    2.68 +		if ( msi_dev_list->dev == dev )
    2.69 +			ret = msi_dev_list;
    2.70 +
    2.71 +	if ( ret ) {
    2.72 +		spin_unlock_irqrestore(&msi_dev_lock, flags);
    2.73 +		return ret;
    2.74 +	}
    2.75 +
    2.76 +	/* Has not allocate msi_dev until now. */
    2.77 +	ret = kmalloc(sizeof(struct msi_dev_list), GFP_ATOMIC);
    2.78 +
    2.79 +	/* Failed to allocate msi_dev structure */
    2.80 +	if ( !ret ) {
    2.81 +		spin_unlock_irqrestore(&msi_dev_lock, flags);
    2.82 +		return NULL;
    2.83 +	}
    2.84 +
    2.85 +	list_add_tail(&ret->list, &msi_dev_head);
    2.86 +	spin_unlock_irqrestore(&msi_dev_lock, flags);
    2.87 +	spin_lock_init(&ret->pirq_list_lock);
    2.88 +	INIT_LIST_HEAD(&ret->pirq_list_head);
    2.89 +	return ret;
    2.90 +}
    2.91 +
    2.92 +static int attach_pirq_entry(int pirq, int entry_nr,
    2.93 +                             struct msi_dev_list *msi_dev_entry)
    2.94 +{
    2.95 +	struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
    2.96 +	unsigned long flags;
    2.97 +
    2.98 +	if (!entry)
    2.99 +		return -ENOMEM;
   2.100 +	entry->pirq = pirq;
   2.101 +	entry->entry_nr = entry_nr;
   2.102 +	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   2.103 +	list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
   2.104 +	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   2.105 +	return 0;
   2.106 +}
   2.107 +
   2.108 +/*
   2.109 + * pciback will provide device's owner
   2.110 + */
   2.111 +int (*get_owner)(struct pci_dev *dev);
   2.112 +
   2.113 +int register_msi_get_owner(int (*func)(struct pci_dev *dev))
   2.114 +{
   2.115 +	if (get_owner) {
   2.116 +		printk(KERN_WARNING "register msi_get_owner again\n");
   2.117 +		return -EEXIST;
   2.118 +	}
   2.119 +	get_owner = func;
   2.120 +	return 0;
   2.121 +}
   2.122 +
   2.123 +int unregister_msi_get_owner(int (*func)(struct pci_dev *dev))
   2.124 +{
   2.125 +	if (get_owner == func)
   2.126 +		get_owner = NULL;
   2.127 +	return 0;
   2.128 +}
   2.129 +
   2.130 +static int msi_get_dev_owner(struct pci_dev *dev)
   2.131 +{
   2.132 +	int owner = DOMID_SELF;
   2.133 +
   2.134 +	BUG_ON(!is_initial_xendomain());
   2.135 +	if (get_owner && (owner = get_owner(dev)) >=0 ) {
   2.136 +		printk(KERN_INFO "get owner for dev %x get %x \n",
   2.137 +				    dev->devfn, owner);
   2.138 +		return owner;
   2.139 +	}
   2.140 +	else
   2.141 +		return DOMID_SELF;
   2.142 +}
   2.143 +
   2.144 +static int msi_unmap_pirq(struct pci_dev *dev, int pirq)
   2.145 +{
   2.146 +	struct physdev_unmap_pirq unmap;
   2.147 +	int rc;
   2.148 +	domid_t domid = DOMID_SELF;
   2.149 +
   2.150 +	domid = msi_get_dev_owner(dev);
   2.151 +	unmap.domid = domid;
   2.152 +	unmap.pirq = pirq;
   2.153 +
   2.154 +	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
   2.155 +		printk(KERN_WARNING "unmap irq %x failed\n", pirq);
   2.156 +
   2.157 +	if (rc < 0)
   2.158 +		return rc;
   2.159 +    return 0;
   2.160 +}
   2.161 +
   2.162 +/*
   2.163 + * Protected by msi_lock
   2.164 + */
   2.165 +static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq,
   2.166 +                                  int entry_nr, int msi)
   2.167 +{
   2.168 +	struct physdev_map_pirq map_irq;
   2.169 +	int rc;
   2.170 +	domid_t domid = DOMID_SELF;
   2.171 +
   2.172 +	domid = msi_get_dev_owner(dev);
   2.173 +
   2.174 +	map_irq.domid = domid;
   2.175 +	map_irq.type = MAP_PIRQ_TYPE_MSI;
   2.176 +	map_irq.index = -1;
   2.177 +	map_irq.pirq = pirq;
   2.178 +    map_irq.msi_info.bus = dev->bus->number;
   2.179 +    map_irq.msi_info.devfn = dev->devfn;
   2.180 +	map_irq.msi_info.entry_nr = entry_nr;
   2.181 +    map_irq.msi_info.msi = msi;
   2.182 +
   2.183 +	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq)))
   2.184 +		printk(KERN_WARNING "map irq failed\n");
   2.185 +
   2.186 +	if (rc < 0)
   2.187 +		return rc;
   2.188 +
   2.189 +	return map_irq.pirq;
   2.190 +}
   2.191 +
   2.192 +static int msi_map_vector(struct pci_dev *dev, int entry_nr, int msi)
   2.193 +{
   2.194 +	return msi_map_pirq_to_vector(dev, -1, entry_nr, msi);
   2.195 +}
   2.196 +
   2.197 +static int msi_init(void)
   2.198 +{
   2.199 +	static int status = 0;
   2.200 +
   2.201 +	if (pci_msi_quirk) {
   2.202 +		pci_msi_enable = 0;
   2.203 +		printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
   2.204 +		status = -EINVAL;
   2.205 +	}
   2.206 +
   2.207 +	return status;
   2.208 +}
   2.209 +
   2.210 +void pci_scan_msi_device(struct pci_dev *dev) { }
   2.211 +
   2.212 +void disable_msi_mode(struct pci_dev *dev, int pos, int type)
   2.213 +{
   2.214 +	u16 control;
   2.215 +
   2.216 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   2.217 +	if (type == PCI_CAP_ID_MSI) {
   2.218 +		/* Set enabled bits to single MSI & enable MSI_enable bit */
   2.219 +		msi_disable(control);
   2.220 +		pci_write_config_word(dev, msi_control_reg(pos), control);
   2.221 +		dev->msi_enabled = 0;
   2.222 +	} else {
   2.223 +		msix_disable(control);
   2.224 +		pci_write_config_word(dev, msi_control_reg(pos), control);
   2.225 +		dev->msix_enabled = 0;
   2.226 +	}
   2.227 +    	if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
   2.228 +		/* PCI Express Endpoint device detected */
   2.229 +		pci_intx(dev, 1);  /* enable intx */
   2.230 +	}
   2.231 +}
   2.232 +
   2.233 +static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
   2.234 +{
   2.235 +	u16 control;
   2.236 +
   2.237 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   2.238 +	if (type == PCI_CAP_ID_MSI) {
   2.239 +		/* Set enabled bits to single MSI & enable MSI_enable bit */
   2.240 +		msi_enable(control, 1);
   2.241 +		pci_write_config_word(dev, msi_control_reg(pos), control);
   2.242 +		dev->msi_enabled = 1;
   2.243 +	} else {
   2.244 +		msix_enable(control);
   2.245 +		pci_write_config_word(dev, msi_control_reg(pos), control);
   2.246 +		dev->msix_enabled = 1;
   2.247 +	}
   2.248 +    	if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
   2.249 +		/* PCI Express Endpoint device detected */
   2.250 +		pci_intx(dev, 0);  /* disable intx */
   2.251 +	}
   2.252 +}
   2.253 +
   2.254 +#ifdef CONFIG_PM
   2.255 +int pci_save_msi_state(struct pci_dev *dev)
   2.256 +{
   2.257 +	int pos;
   2.258 +
   2.259 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
   2.260 +	if (pos <= 0 || dev->no_msi)
   2.261 +		return 0;
   2.262 +
   2.263 +	if (!dev->msi_enabled)
   2.264 +		return 0;
   2.265 +
   2.266 +	/* Restore dev->irq to its default pin-assertion vector */
   2.267 +	msi_unmap_pirq(dev, dev->irq);
   2.268 +	/* Disable MSI mode */
   2.269 +	disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
   2.270 +	/* Set the flags for use of restore */
   2.271 +	dev->msi_enabled = 1;
   2.272 +	return 0;
   2.273 +}
   2.274 +
   2.275 +void pci_restore_msi_state(struct pci_dev *dev)
   2.276 +{
   2.277 +	int pos, pirq;
   2.278 +
   2.279 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
   2.280 +	if (pos <= 0)
   2.281 +		return;
   2.282 +
   2.283 +	if (!dev->msi_enabled)
   2.284 +		return;
   2.285 +
   2.286 +	pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 1);
   2.287 +	if (pirq < 0)
   2.288 +		return;
   2.289 +	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
   2.290 +}
   2.291 +
   2.292 +int pci_save_msix_state(struct pci_dev *dev)
   2.293 +{
   2.294 +	int pos;
   2.295 +	unsigned long flags;
   2.296 +	struct msi_dev_list *msi_dev_entry;
   2.297 +	struct msi_pirq_entry *pirq_entry, *tmp;
   2.298 +
   2.299 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   2.300 +	if (pos <= 0 || dev->no_msi)
   2.301 +		return 0;
   2.302 +
   2.303 +	/* save the capability */
   2.304 +	if (!dev->msix_enabled)
   2.305 +		return 0;
   2.306 +
   2.307 +	msi_dev_entry = get_msi_dev_pirq_list(dev);
   2.308 +
   2.309 +	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   2.310 +	if (!list_empty_careful(&msi_dev_entry->pirq_list_head))
   2.311 +		list_for_each_entry_safe(pirq_entry, tmp,
   2.312 +		                         &msi_dev_entry->pirq_list_head, list)
   2.313 +			msi_unmap_pirq(dev, pirq_entry->pirq);
   2.314 +	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   2.315 +
   2.316 +	disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   2.317 +	/* Set the flags for use of restore */
   2.318 +	dev->msix_enabled = 1;
   2.319 +
   2.320 +	return 0;
   2.321 +}
   2.322 +
   2.323 +void pci_restore_msix_state(struct pci_dev *dev)
   2.324 +{
   2.325 +	int pos;
   2.326 +	unsigned long flags;
   2.327 +	struct msi_dev_list *msi_dev_entry;
   2.328 +	struct msi_pirq_entry *pirq_entry, *tmp;
   2.329 +
   2.330 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   2.331 +	if (pos <= 0)
   2.332 +		return;
   2.333 +
   2.334 +	if (!dev->msix_enabled)
   2.335 +		return;
   2.336 +
   2.337 +	msi_dev_entry = get_msi_dev_pirq_list(dev);
   2.338 +
   2.339 +	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   2.340 +	list_for_each_entry_safe(pirq_entry, tmp,
   2.341 +							 &msi_dev_entry->pirq_list_head, list)
   2.342 +		msi_map_pirq_to_vector(dev, pirq_entry->pirq, pirq_entry->entry_nr, 0);
   2.343 +	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   2.344 +
   2.345 +	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   2.346 +}
   2.347 +#endif
   2.348 +
   2.349 +/**
   2.350 + * msi_capability_init - configure device's MSI capability structure
   2.351 + * @dev: pointer to the pci_dev data structure of MSI device function
   2.352 + *
   2.353 + * Setup the MSI capability structure of device function with a single
   2.354 + * MSI vector, regardless of device function is capable of handling
   2.355 + * multiple messages. A return of zero indicates the successful setup
   2.356 + * of an entry zero with the new MSI vector or non-zero for otherwise.
   2.357 + **/
   2.358 +static int msi_capability_init(struct pci_dev *dev)
   2.359 +{
   2.360 +	int pos, pirq;
   2.361 +	u16 control;
   2.362 +
   2.363 +   	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
   2.364 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   2.365 +
   2.366 +	pirq = msi_map_vector(dev, 0, 1);
   2.367 +	if (pirq < 0)
   2.368 +		return -EBUSY;
   2.369 +
   2.370 +	dev->irq = pirq;
   2.371 +	/* Set MSI enabled bits	 */
   2.372 +	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
   2.373 +	dev->msi_enabled = 1;
   2.374 +
   2.375 +	return 0;
   2.376 +}
   2.377 +
   2.378 +/**
   2.379 + * msix_capability_init - configure device's MSI-X capability
   2.380 + * @dev: pointer to the pci_dev data structure of MSI-X device function
   2.381 + * @entries: pointer to an array of struct msix_entry entries
   2.382 + * @nvec: number of @entries
   2.383 + *
   2.384 + * Setup the MSI-X capability structure of device function with a
   2.385 + * single MSI-X vector. A return of zero indicates the successful setup of
   2.386 + * requested MSI-X entries with allocated vectors or non-zero for otherwise.
   2.387 + **/
   2.388 +static int msix_capability_init(struct pci_dev *dev,
   2.389 +				struct msix_entry *entries, int nvec)
   2.390 +{
   2.391 +	int pirq, i, pos;
   2.392 +	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
   2.393 +	struct msi_pirq_entry *pirq_entry, *tmp;
   2.394 +	unsigned long flags;
   2.395 +
   2.396 +	if (!msi_dev_entry)
   2.397 +		return -ENOMEM;
   2.398 +
   2.399 +	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   2.400 +	if (!list_empty_careful(&msi_dev_entry->pirq_list_head))
   2.401 +	{
   2.402 +		printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not freed \
   2.403 +		       before acquire again.\n", dev->bus->number, PCI_SLOT(dev->devfn),
   2.404 +			   PCI_FUNC(dev->devfn));
   2.405 +		list_for_each_entry_safe(pirq_entry, tmp,
   2.406 +		                         &msi_dev_entry->pirq_list_head, list) {
   2.407 +			msi_unmap_pirq(dev, pirq_entry->pirq);
   2.408 +			list_del(&pirq_entry->list);
   2.409 +			kfree(pirq_entry);
   2.410 +		}
   2.411 +	}
   2.412 +	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   2.413 +
   2.414 +	/* MSI-X Table Initialization */
   2.415 +	for (i = 0; i < nvec; i++) {
   2.416 +		pirq = msi_map_vector(dev, entries[i].entry, 0);
   2.417 +		if (pirq < 0)
   2.418 +			break;
   2.419 +		attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
   2.420 +		dev->irq = pirq;
   2.421 +		(entries + i)->vector = pirq;
   2.422 +	}
   2.423 +	if (i != nvec) {
   2.424 +		msi_unmap_pirq(dev, dev->irq);
   2.425 +		(entries + i)->vector = 0;
   2.426 +		return -EBUSY;
   2.427 +	}
   2.428 +
   2.429 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   2.430 +	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   2.431 +	dev->msix_enabled = 1;
   2.432 +
   2.433 +	return 0;
   2.434 +}
   2.435 +
   2.436 +/**
   2.437 + * pci_enable_msi - configure device's MSI capability structure
   2.438 + * @dev: pointer to the pci_dev data structure of MSI device function
   2.439 + *
   2.440 + * Setup the MSI capability structure of device function with
   2.441 + * a single MSI vector upon its software driver call to request for
   2.442 + * MSI mode enabled on its hardware device function. A return of zero
   2.443 + * indicates the successful setup of an entry zero with the new MSI
   2.444 + * vector or non-zero for otherwise.
   2.445 + **/
   2.446 +extern int pci_frontend_enable_msi(struct pci_dev *dev);
   2.447 +int pci_enable_msi(struct pci_dev* dev)
   2.448 +{
   2.449 +	struct pci_bus *bus;
   2.450 +	int pos, temp, status = -EINVAL;
   2.451 +
   2.452 +	if (!pci_msi_enable || !dev)
   2.453 + 		return status;
   2.454 +
   2.455 +	if (dev->no_msi)
   2.456 +		return status;
   2.457 +
   2.458 +	for (bus = dev->bus; bus; bus = bus->parent)
   2.459 +		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
   2.460 +			return -EINVAL;
   2.461 +
   2.462 +	status = msi_init();
   2.463 +	if (status < 0)
   2.464 +		return status;
   2.465 +
   2.466 +#ifdef CONFIG_XEN_PCIDEV_FRONTEND
   2.467 +	if (!is_initial_xendomain())
   2.468 +	{
   2.469 +		int ret;
   2.470 +
   2.471 +		temp = dev->irq;
   2.472 +		ret = pci_frontend_enable_msi(dev);
   2.473 +		if (ret)
   2.474 +			return ret;
   2.475 +
   2.476 +		dev->irq_old = temp;
   2.477 +
   2.478 +		return ret;
   2.479 +	}
   2.480 +#endif
   2.481 +
   2.482 +	temp = dev->irq;
   2.483 +
   2.484 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
   2.485 +	if (!pos)
   2.486 +		return -EINVAL;
   2.487 +
   2.488 +	/* Check whether driver already requested for MSI-X vectors */
   2.489 +	if (dev->msix_enabled) {
   2.490 +		printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
   2.491 +			   "Device already has MSI-X vectors assigned\n",
   2.492 +			   pci_name(dev));
   2.493 +		dev->irq = temp;
   2.494 +		return -EINVAL;
   2.495 +	}
   2.496 +
   2.497 +	status = msi_capability_init(dev);
   2.498 +	if ( !status )
   2.499 +		dev->irq_old = temp;
   2.500 +    else
   2.501 +		dev->irq = temp;
   2.502 +
   2.503 +	return status;
   2.504 +}
   2.505 +
   2.506 +extern void pci_frontend_disable_msi(struct pci_dev* dev);
   2.507 +void pci_disable_msi(struct pci_dev* dev)
   2.508 +{
   2.509 +	int pos;
   2.510 +	int pirq;
   2.511 +
   2.512 +	if (!pci_msi_enable)
   2.513 +		return;
   2.514 +	if (!dev)
   2.515 +		return;
   2.516 +
   2.517 +#ifdef CONFIG_XEN_PCIDEV_FRONTEND
   2.518 +	if (!is_initial_xendomain()) {
   2.519 +		pci_frontend_disable_msi(dev);
   2.520 +		dev->irq = dev->irq_old;
   2.521 +		return;
   2.522 +	}
   2.523 +#endif
   2.524 +
   2.525 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
   2.526 +	if (!pos)
   2.527 +		return;
   2.528 +
   2.529 +	pirq = dev->irq;
   2.530 +	/* Restore dev->irq to its default pin-assertion vector */
   2.531 +	dev->irq = dev->irq_old;
   2.532 +	msi_unmap_pirq(dev, pirq);
   2.533 +
   2.534 +	/* Disable MSI mode */
   2.535 +	disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
   2.536 +}
   2.537 +
   2.538 +/**
   2.539 + * pci_enable_msix - configure device's MSI-X capability structure
   2.540 + * @dev: pointer to the pci_dev data structure of MSI-X device function
   2.541 + * @entries: pointer to an array of MSI-X entries
   2.542 + * @nvec: number of MSI-X vectors requested for allocation by device driver
   2.543 + *
   2.544 + * Setup the MSI-X capability structure of device function with the number
   2.545 + * of requested vectors upon its software driver call to request for
   2.546 + * MSI-X mode enabled on its hardware device function. A return of zero
   2.547 + * indicates the successful configuration of MSI-X capability structure
   2.548 + * with new allocated MSI-X vectors. A return of < 0 indicates a failure.
   2.549 + * Or a return of > 0 indicates that driver request is exceeding the number
   2.550 + * of vectors available. Driver should use the returned value to re-send
   2.551 + * its request.
   2.552 + **/
   2.553 +extern int pci_frontend_enable_msix(struct pci_dev *dev,
   2.554 +		struct msix_entry *entries, int nvec);
   2.555 +int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
   2.556 +{
   2.557 +	struct pci_bus *bus;
   2.558 +	int status, pos, nr_entries;
   2.559 +	int i, j, temp;
   2.560 +	u16 control;
   2.561 +
   2.562 +	if (!pci_msi_enable || !dev || !entries)
   2.563 + 		return -EINVAL;
   2.564 +
   2.565 +	if (dev->no_msi)
   2.566 +		return -EINVAL;
   2.567 +
   2.568 +	for (bus = dev->bus; bus; bus = bus->parent)
   2.569 +		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
   2.570 +			return -EINVAL;
   2.571 +
   2.572 +#ifdef CONFIG_XEN_PCIDEV_FRONTEND
   2.573 +	if (!is_initial_xendomain()) {
   2.574 +		int ret;
   2.575 +
   2.576 +		ret = pci_frontend_enable_msix(dev, entries, nvec);
   2.577 +		if (ret) {
   2.578 +			printk("get %x from pci_frontend_enable_msix\n", ret);
   2.579 +			return ret;
   2.580 +		}
   2.581 +
   2.582 +        return 0;
   2.583 +	}
   2.584 +#endif
   2.585 +
   2.586 +	status = msi_init();
   2.587 +	if (status < 0)
   2.588 +		return status;
   2.589 +
   2.590 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   2.591 +	if (!pos)
   2.592 + 		return -EINVAL;
   2.593 +
   2.594 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   2.595 +	nr_entries = multi_msix_capable(control);
   2.596 +	if (nvec > nr_entries)
   2.597 +		return -EINVAL;
   2.598 +
   2.599 +	/* Check for any invalid entries */
   2.600 +	for (i = 0; i < nvec; i++) {
   2.601 +		if (entries[i].entry >= nr_entries)
   2.602 +			return -EINVAL;		/* invalid entry */
   2.603 +		for (j = i + 1; j < nvec; j++) {
   2.604 +			if (entries[i].entry == entries[j].entry)
   2.605 +				return -EINVAL;	/* duplicate entry */
   2.606 +		}
   2.607 +	}
   2.608 +
   2.609 +	temp = dev->irq;
   2.610 +	/* Check whether driver already requested for MSI vector */
   2.611 +	if (dev->msi_enabled) {
   2.612 +		printk(KERN_INFO "PCI: %s: Can't enable MSI-X.  "
   2.613 +		       "Device already has an MSI vector assigned\n",
   2.614 +		       pci_name(dev));
   2.615 +		dev->irq = temp;
   2.616 +		return -EINVAL;
   2.617 +	}
   2.618 +
   2.619 +	status = msix_capability_init(dev, entries, nvec);
   2.620 +
   2.621 +	if ( !status )
   2.622 +		dev->irq_old = temp;
   2.623 +	else
   2.624 +		dev->irq = temp;
   2.625 +
   2.626 +	return status;
   2.627 +}
   2.628 +
   2.629 +extern void pci_frontend_disable_msix(struct pci_dev* dev);
   2.630 +void pci_disable_msix(struct pci_dev* dev)
   2.631 +{
   2.632 +	int pos;
   2.633 +	u16 control;
   2.634 +
   2.635 +
   2.636 +	if (!pci_msi_enable)
   2.637 +		return;
   2.638 +	if (!dev)
   2.639 +		return;
   2.640 +
   2.641 +#ifdef CONFIG_XEN_PCIDEV_FRONTEND
   2.642 +	if (!is_initial_xendomain()) {
   2.643 +		pci_frontend_disable_msix(dev);
   2.644 +		dev->irq = dev->irq_old;
   2.645 +		return;
   2.646 +	}
   2.647 +#endif
   2.648 +
   2.649 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   2.650 +	if (!pos)
   2.651 +		return;
   2.652 +
   2.653 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   2.654 +	if (!(control & PCI_MSIX_FLAGS_ENABLE))
   2.655 +		return;
   2.656 +
   2.657 +	msi_remove_pci_irq_vectors(dev);
   2.658 +
   2.659 +	/* Disable MSI mode */
   2.660 +	disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   2.661 +}
   2.662 +
   2.663 +/**
   2.664 + * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
   2.665 + * @dev: pointer to the pci_dev data structure of MSI(X) device function
   2.666 + *
   2.667 + * Being called during hotplug remove, from which the device function
   2.668 + * is hot-removed. All previous assigned MSI/MSI-X vectors, if
   2.669 + * allocated for this device function, are reclaimed to unused state,
   2.670 + * which may be used later on.
   2.671 + **/
   2.672 +void msi_remove_pci_irq_vectors(struct pci_dev* dev)
   2.673 +{
   2.674 +	unsigned long flags;
   2.675 +	struct msi_dev_list *msi_dev_entry;
   2.676 +	struct msi_pirq_entry *pirq_entry, *tmp;
   2.677 +
   2.678 +	if (!pci_msi_enable || !dev)
   2.679 + 		return;
   2.680 +
   2.681 +	msi_dev_entry = get_msi_dev_pirq_list(dev);
   2.682 +
   2.683 +	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   2.684 +	if (!list_empty_careful(&msi_dev_entry->pirq_list_head))
   2.685 +	{
   2.686 +		printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not freed \
   2.687 +		       before acquire again.\n", dev->bus->number, PCI_SLOT(dev->devfn),
   2.688 +			   PCI_FUNC(dev->devfn));
   2.689 +		list_for_each_entry_safe(pirq_entry, tmp,
   2.690 +		                         &msi_dev_entry->pirq_list_head, list) {
   2.691 +			msi_unmap_pirq(dev, pirq_entry->pirq);
   2.692 +			list_del(&pirq_entry->list);
   2.693 +			kfree(pirq_entry);
   2.694 +		}
   2.695 +	}
   2.696 +	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   2.697 +	dev->irq = dev->irq_old;
   2.698 +}
   2.699 +
   2.700 +void pci_no_msi(void)
   2.701 +{
   2.702 +	pci_msi_enable = 0;
   2.703 +}
   2.704 +
   2.705 +EXPORT_SYMBOL(pci_enable_msi);
   2.706 +EXPORT_SYMBOL(pci_disable_msi);
   2.707 +EXPORT_SYMBOL(pci_enable_msix);
   2.708 +EXPORT_SYMBOL(pci_disable_msix);
   2.709 +#ifdef CONFIG_XEN
   2.710 +EXPORT_SYMBOL(register_msi_get_owner);
   2.711 +EXPORT_SYMBOL(unregister_msi_get_owner);
   2.712 +#endif
   2.713 +
     3.1 --- a/drivers/pci/msi.h	Tue Apr 22 18:56:27 2008 +0100
     3.2 +++ b/drivers/pci/msi.h	Thu May 01 10:35:30 2008 +0100
     3.3 @@ -84,6 +84,11 @@ extern int vector_irq[NR_VECTORS];
     3.4  extern void (*interrupt[NR_IRQS])(void);
     3.5  extern int pci_vector_resources(int last, int nr_released);
     3.6  
     3.7 +#ifdef CONFIG_XEN
     3.8 +extern int unregister_msi_get_owner(int (*func)(struct pci_dev *dev));
     3.9 +extern int register_msi_get_owner(int (*func)(struct pci_dev *dev));
    3.10 +#endif
    3.11 +
    3.12  /*
    3.13   * MSI-X Address Register
    3.14   */
     4.1 --- a/drivers/xen/pciback/Makefile	Tue Apr 22 18:56:27 2008 +0100
     4.2 +++ b/drivers/xen/pciback/Makefile	Thu May 01 10:35:30 2008 +0100
     4.3 @@ -6,6 +6,7 @@ pciback-y += conf_space.o conf_space_hea
     4.4  	     conf_space_capability_vpd.o \
     4.5  	     conf_space_capability_pm.o \
     4.6               conf_space_quirks.o
     4.7 +pciback-$(CONFIG_PCI_MSI) += conf_space_capability_msi.o
     4.8  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
     4.9  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o
    4.10  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/drivers/xen/pciback/conf_space_capability_msi.c	Thu May 01 10:35:30 2008 +0100
     5.3 @@ -0,0 +1,60 @@
     5.4 +/*
     5.5 + * PCI Backend -- Configuration overlay for MSI capability
     5.6 + */
     5.7 +#include <linux/pci.h>
     5.8 +#include "conf_space.h"
     5.9 +#include "conf_space_capability.h"
    5.10 +#include <xen/interface/io/pciif.h>
    5.11 +#include "pciback.h"
    5.12 +
    5.13 +int pciback_enable_msi(struct pciback_device *pdev,
    5.14 +		struct pci_dev *dev, struct xen_pci_op *op)
    5.15 +{
    5.16 +	int otherend = pdev->xdev->otherend_id;
    5.17 +	int irq;
    5.18 +	int status;
    5.19 +
    5.20 +	status = pci_enable_msi(dev);
    5.21 +
    5.22 +	if (status) {
    5.23 +		printk("error enable msi for guest %x status %x\n", otherend, status);
    5.24 +		op->value = 0;
    5.25 +		return XEN_PCI_ERR_op_failed;
    5.26 +	}
    5.27 +
    5.28 +	op->value = dev->irq;
    5.29 +	return 0;
    5.30 +}
    5.31 +
    5.32 +int pciback_disable_msi(struct pciback_device *pdev,
    5.33 +		struct pci_dev *dev, struct xen_pci_op *op)
    5.34 +{
    5.35 +	int old_irq = dev->irq;
    5.36 +
    5.37 +	pci_disable_msi(dev);
    5.38 +
    5.39 +	op->value = dev->irq;
    5.40 +	return 0;
    5.41 +}
    5.42 +
    5.43 +int pciback_enable_msix(struct pciback_device *pdev,
    5.44 +		struct pci_dev *dev, struct xen_pci_op *op)
    5.45 +{
    5.46 +	int otherend = pdev->xdev->otherend_id, result, i;
    5.47 +
    5.48 +	result = pci_enable_msix(dev, op->msix_entries, op->value);
    5.49 +
    5.50 +	op->value = result;
    5.51 +	return result;
    5.52 +}
    5.53 +
    5.54 +int pciback_disable_msix(struct pciback_device *pdev,
    5.55 +		struct pci_dev *dev, struct xen_pci_op *op)
    5.56 +{
    5.57 +
    5.58 +	pci_disable_msix(dev);
    5.59 +
    5.60 +	op->value = dev->irq;
    5.61 +	return 0;
    5.62 +}
    5.63 +
     6.1 --- a/drivers/xen/pciback/pci_stub.c	Tue Apr 22 18:56:27 2008 +0100
     6.2 +++ b/drivers/xen/pciback/pci_stub.c	Thu May 01 10:35:30 2008 +0100
     6.3 @@ -805,6 +805,23 @@ static ssize_t permissive_show(struct de
     6.4  
     6.5  DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
     6.6  
     6.7 +#ifdef CONFIG_PCI_MSI
     6.8 +
     6.9 +int pciback_get_owner(struct pci_dev *dev)
    6.10 +{
    6.11 +	struct pcistub_device *psdev;
    6.12 +
    6.13 +	psdev = pcistub_device_find(pci_domain_nr(dev->bus), dev->bus->number,
    6.14 +			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
    6.15 +	/* XXX will other domain has pciback support ??? */
    6.16 +	if (!psdev || !psdev->pdev) {
    6.17 +		printk(KERN_WARNING "no ownder\n");
    6.18 +		return -1;
    6.19 +	}
    6.20 +	return psdev->pdev->xdev->otherend_id;
    6.21 +}
    6.22 +#endif
    6.23 +
    6.24  static void pcistub_exit(void)
    6.25  {
    6.26  	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot);
    6.27 @@ -815,6 +832,9 @@ static void pcistub_exit(void)
    6.28  	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
    6.29  
    6.30  	pci_unregister_driver(&pciback_pci_driver);
    6.31 +#ifdef CONFIG_PCI_MSI
    6.32 +	unregister_msi_get_owner(pciback_get_owner);
    6.33 +#endif
    6.34  }
    6.35  
    6.36  static int __init pcistub_init(void)
    6.37 @@ -872,6 +892,10 @@ static int __init pcistub_init(void)
    6.38  		err = driver_create_file(&pciback_pci_driver.driver,
    6.39  					 &driver_attr_permissive);
    6.40  
    6.41 +#ifdef CONFIG_PCI_MSI
    6.42 +	if (!err)
    6.43 +		err = register_msi_get_owner(pciback_get_owner);
    6.44 +#endif
    6.45  	if (err)
    6.46  		pcistub_exit();
    6.47  
     7.1 --- a/drivers/xen/pciback/pciback.h	Tue Apr 22 18:56:27 2008 +0100
     7.2 +++ b/drivers/xen/pciback/pciback.h	Thu May 01 10:35:30 2008 +0100
     7.3 @@ -93,5 +93,19 @@ void pciback_do_op(void *data);
     7.4  int pciback_xenbus_register(void);
     7.5  void pciback_xenbus_unregister(void);
     7.6  
     7.7 +#ifdef CONFIG_PCI_MSI
     7.8 +int pciback_enable_msi(struct pciback_device *pdev,
     7.9 +                       struct pci_dev *dev, struct xen_pci_op *op);
    7.10 +
    7.11 +int pciback_disable_msi(struct pciback_device *pdev,
    7.12 +                         struct pci_dev *dev, struct xen_pci_op *op);
    7.13 +
    7.14 +
    7.15 +int pciback_enable_msix(struct pciback_device *pdev,
    7.16 +                        struct pci_dev *dev, struct xen_pci_op *op);
    7.17 +
    7.18 +int pciback_disable_msix(struct pciback_device *pdev,
    7.19 +                        struct pci_dev *dev, struct xen_pci_op *op);
    7.20 +#endif
    7.21  extern int verbose_request;
    7.22  #endif
     8.1 --- a/drivers/xen/pciback/pciback_ops.c	Tue Apr 22 18:56:27 2008 +0100
     8.2 +++ b/drivers/xen/pciback/pciback_ops.c	Thu May 01 10:35:30 2008 +0100
     8.3 @@ -61,15 +61,37 @@ void pciback_do_op(void *data)
     8.4  
     8.5  	if (dev == NULL)
     8.6  		op->err = XEN_PCI_ERR_dev_not_found;
     8.7 -	else if (op->cmd == XEN_PCI_OP_conf_read)
     8.8 -		op->err = pciback_config_read(dev, op->offset, op->size,
     8.9 -					      &op->value);
    8.10 -	else if (op->cmd == XEN_PCI_OP_conf_write)
    8.11 -		op->err = pciback_config_write(dev, op->offset, op->size,
    8.12 -					       op->value);
    8.13  	else
    8.14 -		op->err = XEN_PCI_ERR_not_implemented;
    8.15 -
    8.16 +	{
    8.17 +		switch (op->cmd)
    8.18 +		{
    8.19 +			case XEN_PCI_OP_conf_read:
    8.20 +				op->err = pciback_config_read(dev,
    8.21 +					  op->offset, op->size, &op->value);
    8.22 +				break;
    8.23 +			case XEN_PCI_OP_conf_write:
    8.24 +				op->err = pciback_config_write(dev,
    8.25 +					  op->offset, op->size,	op->value);
    8.26 +				break;
    8.27 +#ifdef CONFIG_PCI_MSI
    8.28 +			case XEN_PCI_OP_enable_msi:
    8.29 +				op->err = pciback_enable_msi(pdev, dev, op);
    8.30 +				break;
    8.31 +			case XEN_PCI_OP_disable_msi:
    8.32 +				op->err = pciback_disable_msi(pdev, dev, op);
    8.33 +				break;
    8.34 +			case XEN_PCI_OP_enable_msix:
    8.35 +				op->err = pciback_enable_msix(pdev, dev, op);
    8.36 +				break;
    8.37 +			case XEN_PCI_OP_disable_msix:
    8.38 +				op->err = pciback_disable_msix(pdev, dev, op);
    8.39 +				break;
    8.40 +#endif
    8.41 +			default:
    8.42 +				op->err = XEN_PCI_ERR_not_implemented;
    8.43 +				break;
    8.44 +		}
    8.45 +	}
    8.46  	/* Tell the driver domain that we're done. */ 
    8.47  	wmb();
    8.48  	clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
     9.1 --- a/drivers/xen/pcifront/pci_op.c	Tue Apr 22 18:56:27 2008 +0100
     9.2 +++ b/drivers/xen/pcifront/pci_op.c	Thu May 01 10:35:30 2008 +0100
     9.3 @@ -277,6 +277,122 @@ struct pci_ops pcifront_bus_ops = {
     9.4  	.write = pcifront_bus_write,
     9.5  };
     9.6  
     9.7 +#ifdef CONFIG_PCI_MSI
     9.8 +int pci_frontend_enable_msix(struct pci_dev *dev,
     9.9 +		struct msix_entry *entries,
    9.10 +		int nvec)
    9.11 +{
    9.12 +	int err;
    9.13 +	int i;
    9.14 +	struct xen_pci_op op = {
    9.15 +		.cmd    = XEN_PCI_OP_enable_msix,
    9.16 +		.domain = pci_domain_nr(dev->bus),
    9.17 +		.bus = dev->bus->number,
    9.18 +		.devfn = dev->devfn,
    9.19 +		.value = nvec,
    9.20 +	};
    9.21 +	struct pcifront_sd *sd = dev->bus->sysdata;
    9.22 +	struct pcifront_device *pdev = pcifront_get_pdev(sd);
    9.23 +
    9.24 +	if (nvec > SH_INFO_MAX_VEC) {
    9.25 +		printk("too much vector for pci frontend%x\n", nvec);
    9.26 +		return -EINVAL;
    9.27 +	}
    9.28 +
    9.29 +	for (i = 0; i < nvec; i++) {
    9.30 +		op.msix_entries[i].entry = entries[i].entry;
    9.31 +		op.msix_entries[i].vector = entries[i].vector;
    9.32 +	}
    9.33 +
    9.34 +	err = do_pci_op(pdev, &op);
    9.35 +
    9.36 +	if (!err) {
    9.37 +		if (!op.value) {
    9.38 +			/* we get the result */
    9.39 +			for ( i = 0; i < nvec; i++)
    9.40 +				entries[i].vector = op.msix_entries[i].vector;
    9.41 +			return 0;
    9.42 +		}
    9.43 +		else {
    9.44 +            printk("enable msix get value %x\n", op.value);
    9.45 +			return op.value;
    9.46 +		}
    9.47 +	}
    9.48 +	else {
    9.49 +        printk("enable msix get err %x\n", err);
    9.50 +		return err;
    9.51 +	}
    9.52 +}
    9.53 +
    9.54 +void pci_frontend_disable_msix(struct pci_dev* dev)
    9.55 +{
    9.56 +	int err;
    9.57 +	struct xen_pci_op op = {
    9.58 +		.cmd    = XEN_PCI_OP_disable_msix,
    9.59 +		.domain = pci_domain_nr(dev->bus),
    9.60 +		.bus = dev->bus->number,
    9.61 +		.devfn = dev->devfn,
    9.62 +	};
    9.63 +	struct pcifront_sd *sd = dev->bus->sysdata;
    9.64 +	struct pcifront_device *pdev = pcifront_get_pdev(sd);
    9.65 +
    9.66 +	err = do_pci_op(pdev, &op);
    9.67 +
    9.68 +	/* What should do for error ? */
    9.69 +	if (err)
    9.70 +		printk("pci_disable_msix get err %x\n", err);
    9.71 +}
    9.72 +
    9.73 +int pci_frontend_enable_msi(struct pci_dev *dev)
    9.74 +{
    9.75 +	int err;
    9.76 +	struct xen_pci_op op = {
    9.77 +		.cmd    = XEN_PCI_OP_enable_msi,
    9.78 +		.domain = pci_domain_nr(dev->bus),
    9.79 +		.bus = dev->bus->number,
    9.80 +		.devfn = dev->devfn,
    9.81 +	};
    9.82 +	struct pcifront_sd *sd = dev->bus->sysdata;
    9.83 +	struct pcifront_device *pdev = pcifront_get_pdev(sd);
    9.84 +
    9.85 +	err = do_pci_op(pdev, &op);
    9.86 +	if (likely(!err)) {
    9.87 +		dev->irq = op.value;
    9.88 +	}
    9.89 +	else {
    9.90 +		printk("pci frontend enable msi failed for dev %x:%x \n",
    9.91 +				op.bus, op.devfn);
    9.92 +		err = -EINVAL;
    9.93 +	}
    9.94 +	return err;
    9.95 +}
    9.96 +
    9.97 +void pci_frontend_disable_msi(struct pci_dev* dev)
    9.98 +{
    9.99 +	int err;
   9.100 +	struct xen_pci_op op = {
   9.101 +		.cmd    = XEN_PCI_OP_disable_msi,
   9.102 +		.domain = pci_domain_nr(dev->bus),
   9.103 +		.bus = dev->bus->number,
   9.104 +		.devfn = dev->devfn,
   9.105 +	};
   9.106 +	struct pcifront_sd *sd = dev->bus->sysdata;
   9.107 +	struct pcifront_device *pdev = pcifront_get_pdev(sd);
   9.108 +
   9.109 +	err = do_pci_op(pdev, &op);
   9.110 +	if (err == XEN_PCI_ERR_dev_not_found) {
   9.111 +		/* XXX No response from backend, what shall we do? */
   9.112 +		printk("get no response from backend for disable MSI\n");
   9.113 +		return;
   9.114 +	}
   9.115 +	if (likely(!err))
   9.116 +		dev->irq = op.value;
   9.117 +	else
   9.118 +		/* how can pciback notify us fail? */
   9.119 +		printk("get fake response frombackend \n");
   9.120 +}
   9.121 +#endif /* CONFIG_PCI_MSI */
   9.122 +
   9.123  /* Claim resources for the PCI frontend as-is, backend won't allow changes */
   9.124  static void pcifront_claim_resource(struct pci_dev *dev, void *data)
   9.125  {
    10.1 --- a/include/asm-i386/io_apic.h	Tue Apr 22 18:56:27 2008 +0100
    10.2 +++ b/include/asm-i386/io_apic.h	Thu May 01 10:35:30 2008 +0100
    10.3 @@ -12,7 +12,7 @@
    10.4  
    10.5  #ifdef CONFIG_X86_IO_APIC
    10.6  
    10.7 -#ifdef CONFIG_PCI_MSI
    10.8 +#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
    10.9  static inline int use_pci_vector(void)	{return 1;}
   10.10  static inline void disable_edge_ioapic_vector(unsigned int vector) { }
   10.11  static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
    11.1 --- a/include/asm-x86_64/io_apic.h	Tue Apr 22 18:56:27 2008 +0100
    11.2 +++ b/include/asm-x86_64/io_apic.h	Thu May 01 10:35:30 2008 +0100
    11.3 @@ -12,7 +12,7 @@
    11.4  
    11.5  #ifdef CONFIG_X86_IO_APIC
    11.6  
    11.7 -#ifdef CONFIG_PCI_MSI
    11.8 +#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
    11.9  static inline int use_pci_vector(void)	{return 1;}
   11.10  static inline void disable_edge_ioapic_vector(unsigned int vector) { }
   11.11  static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
    12.1 --- a/include/asm-x86_64/msi.h	Tue Apr 22 18:56:27 2008 +0100
    12.2 +++ b/include/asm-x86_64/msi.h	Thu May 01 10:35:30 2008 +0100
    12.3 @@ -7,14 +7,21 @@
    12.4  #define ASM_MSI_H
    12.5  
    12.6  #include <asm/desc.h>
    12.7 +#ifndef CONFIG_XEN
    12.8  #include <asm/mach_apic.h>
    12.9 +#endif
   12.10  #include <asm/smp.h>
   12.11  
   12.12 +#ifndef CONFIG_XEN
   12.13  #define LAST_DEVICE_VECTOR	(FIRST_SYSTEM_VECTOR - 1)
   12.14 +#else
   12.15 +#define LAST_DYNAMIC_VECTOR 0xdf
   12.16 +#define LAST_DEVICE_VECTOR	(LAST_DYNAMIC_VECTOR)
   12.17 +#endif
   12.18 +
   12.19  #define MSI_TARGET_CPU_SHIFT	12
   12.20  
   12.21  extern struct msi_ops msi_apic_ops;
   12.22 -
   12.23  static inline int msi_arch_init(void)
   12.24  {
   12.25  	msi_register(&msi_apic_ops);
    13.1 --- a/include/linux/pci.h	Tue Apr 22 18:56:27 2008 +0100
    13.2 +++ b/include/linux/pci.h	Thu May 01 10:35:30 2008 +0100
    13.3 @@ -152,6 +152,9 @@ struct pci_dev {
    13.4  	 * directly, use the values stored here. They might be different!
    13.5  	 */
    13.6  	unsigned int	irq;
    13.7 +#ifdef CONFIG_XEN
    13.8 +	unsigned int    irq_old;
    13.9 +#endif
   13.10  	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
   13.11  
   13.12  	/* These fields are used by common fixups */
    14.1 --- a/include/xen/evtchn.h	Tue Apr 22 18:56:27 2008 +0100
    14.2 +++ b/include/xen/evtchn.h	Thu May 01 10:35:30 2008 +0100
    14.3 @@ -136,4 +136,18 @@ static inline void notify_remote_via_evt
    14.4  void notify_remote_via_irq(int irq);
    14.5  int irq_to_evtchn_port(int irq);
    14.6  
    14.7 +#define PIRQ_SET_MAPPING 0x0
    14.8 +#define PIRQ_CLEAR_MAPPING 0x1
    14.9 +#define PIRQ_GET_MAPPING 0x3
   14.10 +int pirq_mapstatus(int pirq, int action);
   14.11 +int set_pirq_hw_action(int pirq, int (*action)(int pirq, int action));
   14.12 +int clear_pirq_hw_action(int pirq);
   14.13 +
   14.14 +#define PIRQ_STARTUP 1
   14.15 +#define PIRQ_SHUTDOWN 2
   14.16 +#define PIRQ_ENABLE 3
   14.17 +#define PIRQ_DISABLE 4
   14.18 +#define PIRQ_END 5
   14.19 +#define PIRQ_ACK 6
   14.20 +
   14.21  #endif /* __ASM_EVTCHN_H__ */
    15.1 --- a/include/xen/interface/io/pciif.h	Tue Apr 22 18:56:27 2008 +0100
    15.2 +++ b/include/xen/interface/io/pciif.h	Thu May 01 10:35:30 2008 +0100
    15.3 @@ -34,6 +34,10 @@
    15.4  /* xen_pci_op commands */
    15.5  #define XEN_PCI_OP_conf_read    (0)
    15.6  #define XEN_PCI_OP_conf_write   (1)
    15.7 +#define XEN_PCI_OP_enable_msi   (2)
    15.8 +#define XEN_PCI_OP_enable_msix  (3)
    15.9 +#define XEN_PCI_OP_disable_msi  (4)
   15.10 +#define XEN_PCI_OP_disable_msix (5)
   15.11  
   15.12  /* xen_pci_op error numbers */
   15.13  #define XEN_PCI_ERR_success          (0)
   15.14 @@ -44,6 +48,12 @@
   15.15  /* XEN_PCI_ERR_op_failed - backend failed to complete the operation */
   15.16  #define XEN_PCI_ERR_op_failed       (-5)
   15.17  
   15.18 +/*
   15.19 + * it should be PAGE_SIZE-sizeof(struct xen_pci_op))/sizeof(struct msix_entry))
   15.20 + * Should not exceed 128
   15.21 + */
   15.22 +#define SH_INFO_MAX_VEC     128
   15.23 +
   15.24  struct xen_pci_op {
   15.25      /* IN: what action to perform: XEN_PCI_OP_* */
   15.26      uint32_t cmd;
   15.27 @@ -62,6 +72,11 @@ struct xen_pci_op {
   15.28  
   15.29      /* IN/OUT: Contains the result after a READ or the value to WRITE */
   15.30      uint32_t value;
   15.31 +    /* IN: Contains extra infor for this operation */
   15.32 +    uint32_t info;
   15.33 +    /*IN:  param for msi-x */
   15.34 +    struct msix_entry msix_entries[SH_INFO_MAX_VEC];
   15.35 +
   15.36  };
   15.37  
   15.38  struct xen_pci_sharedinfo {
    16.1 --- a/include/xen/interface/physdev.h	Tue Apr 22 18:56:27 2008 +0100
    16.2 +++ b/include/xen/interface/physdev.h	Thu May 01 10:35:30 2008 +0100
    16.3 @@ -122,6 +122,38 @@ struct physdev_irq {
    16.4  typedef struct physdev_irq physdev_irq_t;
    16.5  DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
    16.6  
    16.7 +#define MAP_PIRQ_TYPE_MSI               0x0
    16.8 +#define MAP_PIRQ_TYPE_GSI               0x1
    16.9 +#define MAP_PIRQ_TYPE_UNKNOWN           0x2
   16.10 +
   16.11 +#define PHYSDEVOP_map_pirq               13
   16.12 +struct physdev_map_pirq {
   16.13 +    domid_t domid;
   16.14 +    /* IN */
   16.15 +    int type;
   16.16 +    /* IN */
   16.17 +    int index;
   16.18 +    /* IN or OUT */
   16.19 +    int pirq;
   16.20 +    /* msi info passed to VMM */
   16.21 +    struct {
   16.22 +        int bus, devfn, entry_nr;
   16.23 +		int msi;  /* 0 - MSIX  1 - MSI */
   16.24 +    } msi_info;
   16.25 +};
   16.26 +typedef struct physdev_map_pirq physdev_map_pirq_t;
   16.27 +DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
   16.28 +
   16.29 +#define PHYSDEVOP_unmap_pirq             14
   16.30 +struct physdev_unmap_pirq {
   16.31 +    domid_t domid;
   16.32 +    /* IN */
   16.33 +    int pirq;
   16.34 +};
   16.35 +
   16.36 +typedef struct physdev_unmap_pirq physdev_unmap_pirq_t;
   16.37 +DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t);
   16.38 +
   16.39  /*
   16.40   * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
   16.41   * hypercall since 0x00030202.