ia64/linux-2.6.18-xen.hg

changeset 645:359b1e70d9eb

MSI-X: enhancement

Signed-off-by: Yu Zhao <yu.zhao@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Aug 13 13:46:14 2008 +0100 (2008-08-13)
parents c110692c140f
children 9c94f6de5e30
files drivers/pci/msi-xen.c include/xen/interface/physdev.h
line diff
     1.1 --- a/drivers/pci/msi-xen.c	Wed Aug 13 10:00:09 2008 +0100
     1.2 +++ b/drivers/pci/msi-xen.c	Wed Aug 13 13:46:14 2008 +0100
     1.3 @@ -166,11 +166,27 @@ static int msi_unmap_pirq(struct pci_dev
     1.4  	return 0;
     1.5  }
     1.6  
     1.7 +static u64 find_table_base(struct pci_dev *dev, int pos)
     1.8 +{
     1.9 +	u8 bar;
    1.10 +	u32 reg;
    1.11 +	unsigned long flags;
    1.12 +
    1.13 + 	pci_read_config_dword(dev, msix_table_offset_reg(pos), &reg);
    1.14 +	bar = reg & PCI_MSIX_FLAGS_BIRMASK;
    1.15 +
    1.16 +	flags = pci_resource_flags(dev, bar);
    1.17 +	if (flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET | IORESOURCE_BUSY))
    1.18 +		return 0;
    1.19 +
    1.20 +	return pci_resource_start(dev, bar);
    1.21 +}
    1.22 +
    1.23  /*
    1.24   * Protected by msi_lock
    1.25   */
    1.26  static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq,
    1.27 -                                  int entry_nr, int msi)
    1.28 +				  int entry_nr, u64 table_base)
    1.29  {
    1.30  	struct physdev_map_pirq map_irq;
    1.31  	int rc;
    1.32 @@ -182,10 +198,10 @@ static int msi_map_pirq_to_vector(struct
    1.33  	map_irq.type = MAP_PIRQ_TYPE_MSI;
    1.34  	map_irq.index = -1;
    1.35  	map_irq.pirq = pirq;
    1.36 -    map_irq.msi_info.bus = dev->bus->number;
    1.37 -    map_irq.msi_info.devfn = dev->devfn;
    1.38 -	map_irq.msi_info.entry_nr = entry_nr;
    1.39 -    map_irq.msi_info.msi = msi;
    1.40 +	map_irq.bus = dev->bus->number;
    1.41 +	map_irq.devfn = dev->devfn;
    1.42 +	map_irq.entry_nr = entry_nr;
    1.43 +	map_irq.table_base = table_base;
    1.44  
    1.45  	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq)))
    1.46  		printk(KERN_WARNING "map irq failed\n");
    1.47 @@ -196,9 +212,9 @@ static int msi_map_pirq_to_vector(struct
    1.48  	return map_irq.pirq;
    1.49  }
    1.50  
    1.51 -static int msi_map_vector(struct pci_dev *dev, int entry_nr, int msi)
    1.52 +static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
    1.53  {
    1.54 -	return msi_map_pirq_to_vector(dev, -1, entry_nr, msi);
    1.55 +	return msi_map_pirq_to_vector(dev, -1, entry_nr, table_base);
    1.56  }
    1.57  
    1.58  static int msi_init(void)
    1.59 @@ -290,7 +306,7 @@ void pci_restore_msi_state(struct pci_de
    1.60  	if (!dev->msi_enabled)
    1.61  		return;
    1.62  
    1.63 -	pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 1);
    1.64 +	pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 0);
    1.65  	if (pirq < 0)
    1.66  		return;
    1.67  	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
    1.68 @@ -330,6 +346,7 @@ void pci_restore_msix_state(struct pci_d
    1.69  {
    1.70  	int pos;
    1.71  	unsigned long flags;
    1.72 +	u64 table_base;
    1.73  	struct msi_dev_list *msi_dev_entry;
    1.74  	struct msi_pirq_entry *pirq_entry, *tmp;
    1.75  
    1.76 @@ -341,11 +358,15 @@ void pci_restore_msix_state(struct pci_d
    1.77  		return;
    1.78  
    1.79  	msi_dev_entry = get_msi_dev_pirq_list(dev);
    1.80 +	table_base = find_table_base(dev, pos);
    1.81 +	if (!table_base)
    1.82 +		return;
    1.83  
    1.84  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
    1.85  	list_for_each_entry_safe(pirq_entry, tmp,
    1.86 -							 &msi_dev_entry->pirq_list_head, list)
    1.87 -		msi_map_pirq_to_vector(dev, pirq_entry->pirq, pirq_entry->entry_nr, 0);
    1.88 +				 &msi_dev_entry->pirq_list_head, list)
    1.89 +		msi_map_pirq_to_vector(dev, pirq_entry->pirq,
    1.90 +				       pirq_entry->entry_nr, table_base);
    1.91  	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
    1.92  
    1.93  	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
    1.94 @@ -366,10 +387,10 @@ static int msi_capability_init(struct pc
    1.95  	int pos, pirq;
    1.96  	u16 control;
    1.97  
    1.98 -   	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    1.99 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
   1.100  	pci_read_config_word(dev, msi_control_reg(pos), &control);
   1.101  
   1.102 -	pirq = msi_map_vector(dev, 0, 1);
   1.103 +	pirq = msi_map_vector(dev, 0, 0);
   1.104  	if (pirq < 0)
   1.105  		return -EBUSY;
   1.106  
   1.107 @@ -394,6 +415,7 @@ static int msi_capability_init(struct pc
   1.108  static int msix_capability_init(struct pci_dev *dev,
   1.109  				struct msix_entry *entries, int nvec)
   1.110  {
   1.111 +	u64 table_base;
   1.112  	int pirq, i, j, mapped, pos;
   1.113  	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
   1.114  	struct msi_pirq_entry *pirq_entry;
   1.115 @@ -401,6 +423,11 @@ static int msix_capability_init(struct p
   1.116  	if (!msi_dev_entry)
   1.117  		return -ENOMEM;
   1.118  
   1.119 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   1.120 +	table_base = find_table_base(dev, pos);
   1.121 +	if (!table_base)
   1.122 +		return -ENODEV;
   1.123 +
   1.124  	/* MSI-X Table Initialization */
   1.125  	for (i = 0; i < nvec; i++) {
   1.126  		mapped = 0;
   1.127 @@ -417,7 +444,7 @@ static int msix_capability_init(struct p
   1.128  		}
   1.129  		if (mapped)
   1.130  			continue;
   1.131 -		pirq = msi_map_vector(dev, entries[i].entry, 0);
   1.132 +		pirq = msi_map_vector(dev, entries[i].entry, table_base);
   1.133  		if (pirq < 0)
   1.134  			break;
   1.135  		attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
   1.136 @@ -433,7 +460,6 @@ static int msix_capability_init(struct p
   1.137  		return -EBUSY;
   1.138  	}
   1.139  
   1.140 -	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   1.141  	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   1.142  	dev->msix_enabled = 1;
   1.143  
     2.1 --- a/include/xen/interface/physdev.h	Wed Aug 13 10:00:09 2008 +0100
     2.2 +++ b/include/xen/interface/physdev.h	Wed Aug 13 13:46:14 2008 +0100
     2.3 @@ -121,7 +121,7 @@ struct physdev_irq {
     2.4  };
     2.5  typedef struct physdev_irq physdev_irq_t;
     2.6  DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
     2.7 - 
     2.8 +
     2.9  #define MAP_PIRQ_TYPE_MSI               0x0
    2.10  #define MAP_PIRQ_TYPE_GSI               0x1
    2.11  #define MAP_PIRQ_TYPE_UNKNOWN           0x2
    2.12 @@ -136,10 +136,13 @@ struct physdev_map_pirq {
    2.13      /* IN or OUT */
    2.14      int pirq;
    2.15      /* IN */
    2.16 -    struct {
    2.17 -        int bus, devfn, entry_nr;
    2.18 -		int msi;  /* 0 - MSIX    1 - MSI */
    2.19 -    } msi_info;
    2.20 +    int bus;
    2.21 +    /* IN */
    2.22 +    int devfn;
    2.23 +    /* IN */
    2.24 +    int entry_nr;
    2.25 +    /* IN */
    2.26 +    uint64_t table_base;
    2.27  };
    2.28  typedef struct physdev_map_pirq physdev_map_pirq_t;
    2.29  DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);