ia64/linux-2.6.18-xen.hg

changeset 680:583086d5cd26

pci-msi: Dynamically map into Linux irq space.

Signed-off-by: Shan Haitao <haitao.shan@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Sep 25 16:40:13 2008 +0100 (2008-09-25)
parents 2afa279661de
children cc6fc966c613
files drivers/pci/msi-xen.c
line diff
     1.1 --- a/drivers/pci/msi-xen.c	Thu Sep 25 13:10:57 2008 +0100
     1.2 +++ b/drivers/pci/msi-xen.c	Thu Sep 25 16:40:13 2008 +0100
     1.3 @@ -158,7 +158,11 @@ static int msi_unmap_pirq(struct pci_dev
     1.4  	int rc;
     1.5  
     1.6  	unmap.domid = msi_get_dev_owner(dev);
     1.7 -	unmap.pirq = evtchn_get_xen_pirq(pirq);
     1.8 +	/* See comments in msi_map_pirq_to_vector, input parameter pirq
     1.9 +	 * mean irq number only if the device belongs to dom0 itself.
    1.10 +	 */
    1.11 +	unmap.pirq = (unmap.domid != DOMID_SELF)
    1.12 +		? pirq : evtchn_get_xen_pirq(pirq);
    1.13  
    1.14  	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
    1.15  		printk(KERN_WARNING "unmap irq %x failed\n", pirq);
    1.16 @@ -166,7 +170,9 @@ static int msi_unmap_pirq(struct pci_dev
    1.17  	if (rc < 0)
    1.18  		return rc;
    1.19  
    1.20 -	evtchn_map_pirq(pirq, 0);
    1.21 +	if (unmap.domid == DOMID_SELF)
    1.22 +		evtchn_map_pirq(pirq, 0);
    1.23 +
    1.24  	return 0;
    1.25  }
    1.26  
    1.27 @@ -217,7 +223,14 @@ static int msi_map_pirq_to_vector(struct
    1.28  		return -ENOSYS;
    1.29  
    1.30  	BUG_ON(map_irq.pirq <= 0);
    1.31 -	return evtchn_map_pirq(pirq, map_irq.pirq);
    1.32 +
    1.33 +	/* If mapping of this particular MSI is on behalf of another domain,
    1.34 +	 * we do not need to get an irq in dom0. This also implies:
    1.35 +	 * dev->irq in dom0 will be 'Xen pirq' if this device belongs to
    1.36 +	 * to another domain, and will be 'Linux irq' if it belongs to dom0.
    1.37 +	 */
    1.38 +	return ((domid != DOMID_SELF) ?
    1.39 +		map_irq.pirq : evtchn_map_pirq(pirq, map_irq.pirq));
    1.40  }
    1.41  
    1.42  static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
    1.43 @@ -520,6 +533,7 @@ int pci_enable_msi(struct pci_dev* dev)
    1.44  		if (ret)
    1.45  			return ret;
    1.46  
    1.47 +		dev->irq = evtchn_map_pirq(-1, dev->irq);
    1.48  		dev->irq_old = temp;
    1.49  
    1.50  		return ret;
    1.51 @@ -563,6 +577,7 @@ void pci_disable_msi(struct pci_dev* dev
    1.52  
    1.53  #ifdef CONFIG_XEN_PCIDEV_FRONTEND
    1.54  	if (!is_initial_xendomain()) {
    1.55 +		evtchn_map_pirq(dev->irq, 0);
    1.56  		pci_frontend_disable_msi(dev);
    1.57  		dev->irq = dev->irq_old;
    1.58  		return;
    1.59 @@ -618,7 +633,9 @@ int pci_enable_msix(struct pci_dev* dev,
    1.60  
    1.61  #ifdef CONFIG_XEN_PCIDEV_FRONTEND
    1.62  	if (!is_initial_xendomain()) {
    1.63 -		int ret;
    1.64 +		struct msi_dev_list *msi_dev_entry;
    1.65 +		struct msi_pirq_entry *pirq_entry;
    1.66 +		int ret, irq;
    1.67  
    1.68  		ret = pci_frontend_enable_msix(dev, entries, nvec);
    1.69  		if (ret) {
    1.70 @@ -626,6 +643,25 @@ int pci_enable_msix(struct pci_dev* dev,
    1.71  			return ret;
    1.72  		}
    1.73  
    1.74 +		msi_dev_entry = get_msi_dev_pirq_list(dev);
    1.75 +		for (i = 0; i < nvec; i++) {
    1.76 +			int mapped = 0;
    1.77 +
    1.78 +			list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
    1.79 +				if (pirq_entry->entry_nr == entries[i].entry) {
    1.80 +					irq = pirq_entry->pirq;
    1.81 +					BUG_ON(entries[i].vector != evtchn_get_xen_pirq(irq));
    1.82 +					entries[i].vector = irq;
    1.83 +					mapped = 1;
    1.84 +					break;
    1.85 +				}
    1.86 +			}
    1.87 +			if (mapped)
    1.88 +				continue;
    1.89 +			irq = evtchn_map_pirq(-1, entries[i].vector);
    1.90 +			attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
    1.91 +			entries[i].vector = irq;
    1.92 +		}
    1.93          return 0;
    1.94  	}
    1.95  #endif
    1.96 @@ -687,7 +723,19 @@ void pci_disable_msix(struct pci_dev* de
    1.97  
    1.98  #ifdef CONFIG_XEN_PCIDEV_FRONTEND
    1.99  	if (!is_initial_xendomain()) {
   1.100 +		struct msi_dev_list *msi_dev_entry;
   1.101 +		struct msi_pirq_entry *pirq_entry, *tmp;
   1.102 +
   1.103  		pci_frontend_disable_msix(dev);
   1.104 +
   1.105 +		msi_dev_entry = get_msi_dev_pirq_list(dev);
   1.106 +		list_for_each_entry_safe(pirq_entry, tmp,
   1.107 +		                         &msi_dev_entry->pirq_list_head, list) {
   1.108 +			evtchn_map_pirq(pirq_entry->pirq, 0);
   1.109 +			list_del(&pirq_entry->list);
   1.110 +			kfree(pirq_entry);
   1.111 +		}
   1.112 +
   1.113  		dev->irq = dev->irq_old;
   1.114  		return;
   1.115  	}