ia64/xen-unstable

changeset 18324:0638a5c2cc9f

MSI-X: enhancement

Signed-off-by: Yu Zhao <yu.zhao@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Aug 13 13:45:39 2008 +0100 (2008-08-13)
parents 644a9d219973
children c6402709acc8
files tools/ioemu/hw/pass-through.h tools/ioemu/hw/pt-msi.c tools/libxc/xc_physdev.c tools/libxc/xenctrl.h xen/arch/x86/msi.c xen/arch/x86/physdev.c xen/drivers/passthrough/io.c xen/include/asm-x86/msi.h xen/include/public/physdev.h
line diff
     1.1 --- a/tools/ioemu/hw/pass-through.h	Wed Aug 13 13:42:30 2008 +0100
     1.2 +++ b/tools/ioemu/hw/pass-through.h	Wed Aug 13 13:45:39 2008 +0100
     1.3 @@ -120,6 +120,7 @@ struct pt_msix_info {
     1.4      int enabled;
     1.5      int total_entries;
     1.6      int bar_index;
     1.7 +    uint64_t table_base;
     1.8      uint32_t table_off;
     1.9      uint64_t mmio_base_addr;
    1.10      int mmio_index;
     2.1 --- a/tools/ioemu/hw/pt-msi.c	Wed Aug 13 13:42:30 2008 +0100
     2.2 +++ b/tools/ioemu/hw/pt-msi.c	Wed Aug 13 13:45:39 2008 +0100
     2.3 @@ -38,8 +38,8 @@ int pt_msi_setup(struct pt_dev *dev)
     2.4      }
     2.5  
     2.6      if ( xc_physdev_map_pirq_msi(xc_handle, domid, AUTO_ASSIGN, &pirq,
     2.7 -							dev->pci_dev->dev << 3 | dev->pci_dev->func,
     2.8 -							dev->pci_dev->bus, 0, 1) )
     2.9 +                                 dev->pci_dev->dev << 3 | dev->pci_dev->func,
    2.10 +                                 dev->pci_dev->bus, 0, 0) )
    2.11      {
    2.12          PT_LOG("error map msi\n");
    2.13          return -1;
    2.14 @@ -121,7 +121,8 @@ static int pt_msix_update_one(struct pt_
    2.15      {
    2.16          ret = xc_physdev_map_pirq_msi(xc_handle, domid, AUTO_ASSIGN, &pirq,
    2.17                                  dev->pci_dev->dev << 3 | dev->pci_dev->func,
    2.18 -                                dev->pci_dev->bus, entry_nr, 0);
    2.19 +                                dev->pci_dev->bus, entry_nr,
    2.20 +                                dev->msix->table_base);
    2.21          if ( ret )
    2.22          {
    2.23              PT_LOG("error map msix entry %x\n", entry_nr);
    2.24 @@ -183,7 +184,7 @@ static void pci_msix_writel(void *opaque
    2.25      entry = &msix->msix_entry[entry_nr];
    2.26      offset = ((addr - msix->mmio_base_addr) % 16) / 4;
    2.27  
    2.28 -    if ( offset != 3 && msix->enabled && entry->io_mem[3] & 0x1 )
    2.29 +    if ( offset != 3 && msix->enabled && !(entry->io_mem[3] & 0x1) )
    2.30      {
    2.31          PT_LOG("can not update msix entry %d since MSI-X is already \
    2.32                  function now.\n", entry_nr);
    2.33 @@ -196,7 +197,7 @@ static void pci_msix_writel(void *opaque
    2.34  
    2.35      if ( offset == 3 )
    2.36      {
    2.37 -        if ( !(val & 0x1) )
    2.38 +        if ( msix->enabled && !(val & 0x1) )
    2.39              pt_msix_update_one(dev, entry_nr);
    2.40          mask_physical_msix_entry(dev, entry_nr, entry->io_mem[3] & 0x1);
    2.41      }
    2.42 @@ -280,7 +281,6 @@ int pt_msix_init(struct pt_dev *dev, int
    2.43      uint8_t id;
    2.44      uint16_t control;
    2.45      int i, total_entries, table_off, bar_index;
    2.46 -    uint64_t bar_base;
    2.47      struct pci_dev *pd = dev->pci_dev;
    2.48  
    2.49      id = pci_read_byte(pd, pos + PCI_CAP_LIST_ID);
    2.50 @@ -314,18 +314,14 @@ int pt_msix_init(struct pt_dev *dev, int
    2.51      table_off = pci_read_long(pd, pos + PCI_MSIX_TABLE);
    2.52      bar_index = dev->msix->bar_index = table_off & PCI_MSIX_BIR;
    2.53      table_off &= table_off & ~PCI_MSIX_BIR;
    2.54 -    bar_base = pci_read_long(pd, 0x10 + 4 * bar_index);
    2.55 -    if ( (bar_base & 0x6) == 0x4 )
    2.56 -    {
    2.57 -        bar_base &= ~0xf;
    2.58 -        bar_base += (uint64_t)pci_read_long(pd, 0x10 + 4 * (bar_index + 1)) << 32;
    2.59 -    }
    2.60 -    PT_LOG("get MSI-X table bar base %lx\n", bar_base);
    2.61 +    dev->msix->table_base = dev->pci_dev->base_addr[bar_index];
    2.62 +    PT_LOG("get MSI-X table bar base %llx\n",
    2.63 +           (unsigned long long)dev->msix->table_base);
    2.64  
    2.65      dev->msix->fd = open("/dev/mem", O_RDWR);
    2.66      dev->msix->phys_iomem_base = mmap(0, total_entries * 16,
    2.67                            PROT_WRITE | PROT_READ, MAP_SHARED | MAP_LOCKED,
    2.68 -                          dev->msix->fd, bar_base + table_off);
    2.69 +                          dev->msix->fd, dev->msix->table_base + table_off);
    2.70      PT_LOG("mapping physical MSI-X table to %lx\n",
    2.71             (unsigned long)dev->msix->phys_iomem_base);
    2.72      return 0;
     3.1 --- a/tools/libxc/xc_physdev.c	Wed Aug 13 13:42:30 2008 +0100
     3.2 +++ b/tools/libxc/xc_physdev.c	Wed Aug 13 13:45:39 2008 +0100
     3.3 @@ -51,7 +51,7 @@ int xc_physdev_map_pirq_msi(int xc_handl
     3.4                              int devfn,
     3.5                              int bus,
     3.6                              int entry_nr,
     3.7 -                            int msi_type)
     3.8 +                            uint64_t table_base)
     3.9  {
    3.10      int rc;
    3.11      struct physdev_map_pirq map;
    3.12 @@ -63,10 +63,10 @@ int xc_physdev_map_pirq_msi(int xc_handl
    3.13      map.type = MAP_PIRQ_TYPE_MSI;
    3.14      map.index = index;
    3.15      map.pirq = *pirq;
    3.16 -    map.msi_info.devfn = devfn;
    3.17 -    map.msi_info.bus = bus;
    3.18 -    map.msi_info.entry_nr = entry_nr;
    3.19 -    map.msi_info.msi = msi_type;
    3.20 +    map.bus = bus;
    3.21 +    map.devfn = devfn;
    3.22 +    map.entry_nr = entry_nr;
    3.23 +    map.table_base = table_base;
    3.24  
    3.25      rc = do_physdev_op(xc_handle, PHYSDEVOP_map_pirq, &map);
    3.26  
     4.1 --- a/tools/libxc/xenctrl.h	Wed Aug 13 13:42:30 2008 +0100
     4.2 +++ b/tools/libxc/xenctrl.h	Wed Aug 13 13:45:39 2008 +0100
     4.3 @@ -917,7 +917,7 @@ int xc_physdev_map_pirq_msi(int xc_handl
     4.4                              int devfn,
     4.5                              int bus,
     4.6                              int entry_nr,
     4.7 -                            int msi_type);
     4.8 +                            uint64_t table_base);
     4.9  
    4.10  int xc_physdev_unmap_pirq(int xc_handle,
    4.11                            int domid,
     5.1 --- a/xen/arch/x86/msi.c	Wed Aug 13 13:42:30 2008 +0100
     5.2 +++ b/xen/arch/x86/msi.c	Wed Aug 13 13:45:39 2008 +0100
     5.3 @@ -490,28 +490,6 @@ static int msi_capability_init(struct pc
     5.4      return 0;
     5.5  }
     5.6  
     5.7 -static u64 pci_resource_start(struct pci_dev *dev, u8 bar_index)
     5.8 -{
     5.9 -    u64 bar_base;
    5.10 -    u32 reg_val;
    5.11 -    u8 bus = dev->bus;
    5.12 -    u8 slot = PCI_SLOT(dev->devfn);
    5.13 -    u8 func = PCI_FUNC(dev->devfn);
    5.14 -
    5.15 -    reg_val = pci_conf_read32(bus, slot, func,
    5.16 -                              PCI_BASE_ADDRESS_0 + 4 * bar_index);
    5.17 -    bar_base = reg_val & PCI_BASE_ADDRESS_MEM_MASK;
    5.18 -    if ( ( reg_val & PCI_BASE_ADDRESS_MEM_TYPE_MASK ) ==
    5.19 -         PCI_BASE_ADDRESS_MEM_TYPE_64 )
    5.20 -    {
    5.21 -        reg_val = pci_conf_read32(bus, slot, func,
    5.22 -                                  PCI_BASE_ADDRESS_0 + 4 * (bar_index + 1));
    5.23 -        bar_base |= ((u64)reg_val) << 32;
    5.24 -    }
    5.25 -
    5.26 -    return bar_base;
    5.27 -}
    5.28 -
    5.29  /**
    5.30   * msix_capability_init - configure device's MSI-X capability
    5.31   * @dev: pointer to the pci_dev data structure of MSI-X device function
    5.32 @@ -522,7 +500,7 @@ static u64 pci_resource_start(struct pci
    5.33   * single MSI-X irq. A return of zero indicates the successful setup of
    5.34   * requested MSI-X entries with allocated irqs or non-zero for otherwise.
    5.35   **/
    5.36 -static int msix_capability_init(struct pci_dev *dev, int vector, int entry_nr)
    5.37 +static int msix_capability_init(struct pci_dev *dev, struct msi_info *msi)
    5.38  {
    5.39      struct msi_desc *entry;
    5.40      int pos;
    5.41 @@ -549,7 +527,7 @@ static int msix_capability_init(struct p
    5.42      table_offset = pci_conf_read32(bus, slot, func, msix_table_offset_reg(pos));
    5.43      bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
    5.44      table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
    5.45 -    phys_addr = pci_resource_start(dev, bir) + table_offset;
    5.46 +    phys_addr = msi->table_base + table_offset;
    5.47      idx = msix_fixmap_alloc();
    5.48      if ( idx < 0 )
    5.49      {
    5.50 @@ -561,11 +539,11 @@ static int msix_capability_init(struct p
    5.51  
    5.52      entry->msi_attrib.type = PCI_CAP_ID_MSIX;
    5.53      entry->msi_attrib.is_64 = 1;
    5.54 -    entry->msi_attrib.entry_nr = entry_nr;
    5.55 +    entry->msi_attrib.entry_nr = msi->entry_nr;
    5.56      entry->msi_attrib.maskbit = 1;
    5.57      entry->msi_attrib.masked = 1;
    5.58      entry->msi_attrib.pos = pos;
    5.59 -    entry->vector = vector;
    5.60 +    entry->vector = msi->vector;
    5.61      entry->dev = dev;
    5.62      entry->mask_base = base;
    5.63  
    5.64 @@ -589,24 +567,25 @@ static int msix_capability_init(struct p
    5.65   * indicates the successful setup of an entry zero with the new MSI
    5.66   * irq or non-zero for otherwise.
    5.67   **/
    5.68 -static int __pci_enable_msi(u8 bus, u8 devfn, int vector)
    5.69 +static int __pci_enable_msi(struct msi_info *msi)
    5.70  {
    5.71      int status;
    5.72      struct pci_dev *pdev;
    5.73  
    5.74 -    pdev = pci_lock_pdev(bus, devfn);
    5.75 +    pdev = pci_lock_pdev(msi->bus, msi->devfn);
    5.76      if ( !pdev )
    5.77  	return -ENODEV;
    5.78  
    5.79 -    if ( find_msi_entry(pdev, vector, PCI_CAP_ID_MSI) )
    5.80 +    if ( find_msi_entry(pdev, msi->vector, PCI_CAP_ID_MSI) )
    5.81      {
    5.82  	spin_unlock(&pdev->lock);
    5.83 -        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSI on device \
    5.84 -            %02x:%02x.%01x.\n", vector, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
    5.85 +        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSI on "
    5.86 +            "device %02x:%02x.%01x.\n", msi->vector, msi->bus,
    5.87 +            PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
    5.88          return 0;
    5.89      }
    5.90  
    5.91 -    status = msi_capability_init(pdev, vector);
    5.92 +    status = msi_capability_init(pdev, msi->vector);
    5.93      spin_unlock(&pdev->lock);
    5.94      return status;
    5.95  }
    5.96 @@ -659,37 +638,37 @@ static void __pci_disable_msi(int vector
    5.97   * of irqs available. Driver should use the returned value to re-send
    5.98   * its request.
    5.99   **/
   5.100 -static int __pci_enable_msix(u8 bus, u8 devfn, int vector, int entry_nr)
   5.101 +static int __pci_enable_msix(struct msi_info *msi)
   5.102  {
   5.103      int status, pos, nr_entries;
   5.104      struct pci_dev *pdev;
   5.105      u16 control;
   5.106 -    u8 slot = PCI_SLOT(devfn);
   5.107 -    u8 func = PCI_FUNC(devfn);
   5.108 +    u8 slot = PCI_SLOT(msi->devfn);
   5.109 +    u8 func = PCI_FUNC(msi->devfn);
   5.110  
   5.111 -    pdev = pci_lock_pdev(bus, devfn);
   5.112 +    pdev = pci_lock_pdev(msi->bus, msi->devfn);
   5.113      if ( !pdev )
   5.114  	return -ENODEV;
   5.115  
   5.116 -    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
   5.117 -    control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
   5.118 +    pos = pci_find_cap_offset(msi->bus, slot, func, PCI_CAP_ID_MSIX);
   5.119 +    control = pci_conf_read16(msi->bus, slot, func, msi_control_reg(pos));
   5.120      nr_entries = multi_msix_capable(control);
   5.121 -    if (entry_nr > nr_entries)
   5.122 +    if (msi->entry_nr > nr_entries)
   5.123      {
   5.124  	spin_unlock(&pdev->lock);
   5.125          return -EINVAL;
   5.126      }
   5.127  
   5.128 -    if ( find_msi_entry(pdev, vector, PCI_CAP_ID_MSIX) )
   5.129 +    if ( find_msi_entry(pdev, msi->vector, PCI_CAP_ID_MSIX) )
   5.130      {
   5.131  	spin_unlock(&pdev->lock);
   5.132 -        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSIX on \
   5.133 -                device %02x:%02x.%01x.\n", vector, bus,
   5.134 -                PCI_SLOT(devfn), PCI_FUNC(devfn));
   5.135 +        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSIX on "
   5.136 +                "device %02x:%02x.%01x.\n", msi->vector, msi->bus,
   5.137 +                PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
   5.138          return 0;
   5.139      }
   5.140  
   5.141 -    status = msix_capability_init(pdev, vector, entry_nr);
   5.142 +    status = msix_capability_init(pdev, msi);
   5.143      spin_unlock(&pdev->lock);
   5.144      return status;
   5.145  }
   5.146 @@ -727,13 +706,12 @@ static void __pci_disable_msix(int vecto
   5.147      spin_unlock(&dev->lock);
   5.148  }
   5.149  
   5.150 -int pci_enable_msi(u8 bus, u8 devfn, int vector, int entry_nr, int msi)
   5.151 +int pci_enable_msi(struct msi_info *msi)
   5.152  {
   5.153 -    ASSERT(spin_is_locked(&irq_desc[vector].lock));
   5.154 -    if ( msi )
   5.155 -        return __pci_enable_msi(bus, devfn, vector);
   5.156 -    else
   5.157 -        return __pci_enable_msix(bus, devfn, vector, entry_nr);
   5.158 +    ASSERT(spin_is_locked(&irq_desc[msi->vector].lock));
   5.159 +
   5.160 +    return  msi->table_base ? __pci_enable_msix(msi) :
   5.161 +                              __pci_enable_msi(msi);
   5.162  }
   5.163  
   5.164  void pci_disable_msi(int vector)
     6.1 --- a/xen/arch/x86/physdev.c	Wed Aug 13 13:42:30 2008 +0100
     6.2 +++ b/xen/arch/x86/physdev.c	Wed Aug 13 13:45:39 2008 +0100
     6.3 @@ -66,6 +66,7 @@ static int map_domain_pirq(struct domain
     6.4  {
     6.5      int ret = 0;
     6.6      int old_vector, old_pirq;
     6.7 +    struct msi_info msi;
     6.8  
     6.9      if ( d == NULL )
    6.10          return -EINVAL;
    6.11 @@ -115,10 +116,14 @@ static int map_domain_pirq(struct domain
    6.12                       vector);
    6.13          desc->handler = &pci_msi_type;
    6.14  
    6.15 -        ret = pci_enable_msi(map->msi_info.bus,
    6.16 -		                     map->msi_info.devfn, vector,
    6.17 -							 map->msi_info.entry_nr,
    6.18 -							 map->msi_info.msi);
    6.19 +        msi.bus = map->bus;
    6.20 +        msi.devfn = map->devfn;
    6.21 +        msi.entry_nr = map->entry_nr;
    6.22 +        msi.table_base = map->table_base;
    6.23 +        msi.vector = vector;
    6.24 +
    6.25 +        ret = pci_enable_msi(&msi);
    6.26 +
    6.27          spin_unlock_irqrestore(&desc->lock, flags);
    6.28          if ( ret )
    6.29              goto done;
    6.30 @@ -139,7 +144,7 @@ static int unmap_domain_pirq(struct doma
    6.31      int ret = 0;
    6.32      int vector;
    6.33  
    6.34 -    if ( d == NULL || pirq < 0 || pirq > NR_PIRQS )
    6.35 +    if ( d == NULL || pirq < 0 || pirq >= NR_PIRQS )
    6.36          return -EINVAL;
    6.37  
    6.38      if ( !IS_PRIV(current->domain) )
     7.1 --- a/xen/drivers/passthrough/io.c	Wed Aug 13 13:42:30 2008 +0100
     7.2 +++ b/xen/drivers/passthrough/io.c	Wed Aug 13 13:45:39 2008 +0100
     7.3 @@ -75,6 +75,9 @@ int pt_irq_create_bind_vtd(
     7.4      {
     7.5          int pirq = pt_irq_bind->machine_irq;
     7.6  
     7.7 +        if ( pirq < 0 || pirq >= NR_IRQS )
     7.8 +            return -EINVAL;
     7.9 +
    7.10          if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID ) )
    7.11          {
    7.12              hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID |
     8.1 --- a/xen/include/asm-x86/msi.h	Wed Aug 13 13:42:30 2008 +0100
     8.2 +++ b/xen/include/asm-x86/msi.h	Wed Aug 13 13:45:39 2008 +0100
     8.3 @@ -54,6 +54,14 @@
     8.4  #define MAX_MSIX_PAGES              32
     8.5  #endif
     8.6  
     8.7 +struct msi_info {
     8.8 +    int bus;
     8.9 +    int devfn;
    8.10 +    int vector;
    8.11 +    int entry_nr;
    8.12 +    uint64_t table_base;
    8.13 +};
    8.14 +
    8.15  struct msi_msg {
    8.16  	u32	address_lo;	/* low 32 bits of msi message address */
    8.17  	u32	address_hi;	/* high 32 bits of msi message address */
    8.18 @@ -64,7 +72,7 @@ struct msi_msg {
    8.19  extern void mask_msi_irq(unsigned int irq);
    8.20  extern void unmask_msi_irq(unsigned int irq);
    8.21  extern void set_msi_irq_affinity(unsigned int irq, cpumask_t mask);
    8.22 -extern int pci_enable_msi(u8 bus, u8 devfn, int vector, int entry_nr, int msi);
    8.23 +extern int pci_enable_msi(struct msi_info *msi);
    8.24  extern void pci_disable_msi(int vector);
    8.25  extern void pci_cleanup_msi(struct pci_dev *pdev);
    8.26  
     9.1 --- a/xen/include/public/physdev.h	Wed Aug 13 13:42:30 2008 +0100
     9.2 +++ b/xen/include/public/physdev.h	Wed Aug 13 13:45:39 2008 +0100
     9.3 @@ -136,10 +136,13 @@ struct physdev_map_pirq {
     9.4      /* IN or OUT */
     9.5      int pirq;
     9.6      /* IN */
     9.7 -    struct {
     9.8 -        int bus, devfn, entry_nr;
     9.9 -		int msi;  /* 0 - MSIX    1 - MSI */
    9.10 -    } msi_info;
    9.11 +    int bus;
    9.12 +    /* IN */
    9.13 +    int devfn;
    9.14 +    /* IN */
    9.15 +    int entry_nr;
    9.16 +    /* IN */
    9.17 +    uint64_t table_base;
    9.18  };
    9.19  typedef struct physdev_map_pirq physdev_map_pirq_t;
    9.20  DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);