xen msi: Handle devices with a pba of 0 (such as SRIOV) Signed-off-by: George Dunlap diff -r 33717472f37e xen/arch/x86/msi.c --- a/xen/arch/x86/msi.c Tue Jun 28 18:15:44 2011 +0100 +++ b/xen/arch/x86/msi.c Thu Jun 30 13:00:08 2011 +0100 @@ -633,7 +633,6 @@ static int msix_capability_init(struct p u32 pba_offset; ASSERT(!dev->msix_used_entries); - WARN_ON(msi->table_base != read_pci_mem_bar(bus, slot, func, bir)); dev->msix_nr_entries = nr_entries; dev->msix_table.first = PFN_DOWN(table_paddr); @@ -646,20 +645,29 @@ static int msix_capability_init(struct p msix_pba_offset_reg(pos)); bir = (u8)(pba_offset & PCI_MSIX_BIRMASK); pba_paddr = read_pci_mem_bar(bus, slot, func, bir); - WARN_ON(!pba_paddr); - pba_paddr += pba_offset & ~PCI_MSIX_BIRMASK; - dev->msix_pba.first = PFN_DOWN(pba_paddr); - dev->msix_pba.last = PFN_DOWN(pba_paddr + - BITS_TO_LONGS(nr_entries) - 1); - WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, dev->msix_pba.first, - dev->msix_pba.last)); + if ( pba_paddr ) + { + WARN_ON(msi->table_base != pba_paddr); + + pba_paddr += pba_offset & ~PCI_MSIX_BIRMASK; + + dev->msix_pba.first = PFN_DOWN(pba_paddr); + dev->msix_pba.last = PFN_DOWN(pba_paddr + + BITS_TO_LONGS(nr_entries) - 1); + WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, dev->msix_pba.first, + dev->msix_pba.last)); + } + else + dev->msix_pba.first = dev->msix_pba.last = 0; if ( rangeset_add_range(mmio_ro_ranges, dev->msix_table.first, dev->msix_table.last) ) WARN(); - if ( rangeset_add_range(mmio_ro_ranges, dev->msix_pba.first, - dev->msix_pba.last) ) + + if ( dev->msix_pba.first + && rangeset_add_range(mmio_ro_ranges, dev->msix_pba.first, + dev->msix_pba.last) ) WARN(); if ( dev->domain ) @@ -669,17 +677,20 @@ static int msix_capability_init(struct p { struct domain *d = dev->domain; + /* See if any existing domains already have access to this space */ if ( !d ) for_each_domain(d) if ( !paging_mode_translate(d) && (iomem_access_permitted(d, dev->msix_table.first, dev->msix_table.last) || - iomem_access_permitted(d, dev->msix_pba.first, - dev->msix_pba.last)) ) + (dev->msix_pba.first && + iomem_access_permitted(d, dev->msix_pba.first, + dev->msix_pba.last))) ) break; if ( d ) { /* XXX How to deal with existing mappings? */ + WARN(); } } } @@ -839,8 +850,9 @@ static void __pci_disable_msix(struct ms if ( rangeset_remove_range(mmio_ro_ranges, dev->msix_table.first, dev->msix_table.last) ) WARN(); - if ( rangeset_remove_range(mmio_ro_ranges, dev->msix_pba.first, - dev->msix_pba.last) ) + if ( dev->msix_pba.first + && rangeset_remove_range(mmio_ro_ranges, dev->msix_pba.first, + dev->msix_pba.last) ) WARN(); } }