aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/msi.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-08-23 09:22:08 +0200
committerJan Beulich <jbeulich@suse.com>2013-08-23 09:22:08 +0200
commit1035bb64fd7fd9f05c510466d98566fd82e37ad9 (patch)
tree633b821d1480107aaa767fa1382d7510421380d6 /xen/arch/x86/msi.c
parentb5692f2ef9b6fd67c3e7b4d4f2a4bdb1d58100e5 (diff)
downloadxen-1035bb64fd7fd9f05c510466d98566fd82e37ad9.tar.gz
xen-1035bb64fd7fd9f05c510466d98566fd82e37ad9.tar.bz2
xen-1035bb64fd7fd9f05c510466d98566fd82e37ad9.zip
PCI: break MSI-X data out of struct pci_dev_info
Considering that a significant share of PCI devices out there (not the least the myriad of CPU-exposed ones) don't support MSI-X at all, and that the amount of data is well beyond a handful of bytes, break this out of the common structure, at once allowing the actual data to be tracked to become architecture specific. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/msi.c')
-rw-r--r--xen/arch/x86/msi.c101
1 files changed, 51 insertions, 50 deletions
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 3a8956aa3e..e17e5b2817 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -66,7 +66,7 @@ static void msix_fixmap_free(int idx)
spin_unlock(&msix_fixmap_lock);
}
-static int msix_get_fixmap(struct pci_dev *dev, u64 table_paddr,
+static int msix_get_fixmap(struct arch_msix *msix, u64 table_paddr,
u64 entry_paddr)
{
long nr_page;
@@ -77,48 +77,48 @@ static int msix_get_fixmap(struct pci_dev *dev, u64 table_paddr,
if ( nr_page < 0 || nr_page >= MAX_MSIX_TABLE_PAGES )
return -EINVAL;
- spin_lock(&dev->msix_table_lock);
- if ( dev->msix_table_refcnt[nr_page]++ == 0 )
+ spin_lock(&msix->table_lock);
+ if ( msix->table_refcnt[nr_page]++ == 0 )
{
idx = msix_fixmap_alloc();
if ( idx < 0 )
{
- dev->msix_table_refcnt[nr_page]--;
+ msix->table_refcnt[nr_page]--;
goto out;
}
set_fixmap_nocache(idx, entry_paddr);
- dev->msix_table_idx[nr_page] = idx;
+ msix->table_idx[nr_page] = idx;
}
else
- idx = dev->msix_table_idx[nr_page];
+ idx = msix->table_idx[nr_page];
out:
- spin_unlock(&dev->msix_table_lock);
+ spin_unlock(&msix->table_lock);
return idx;
}
-static void msix_put_fixmap(struct pci_dev *dev, int idx)
+static void msix_put_fixmap(struct arch_msix *msix, int idx)
{
int i;
- spin_lock(&dev->msix_table_lock);
+ spin_lock(&msix->table_lock);
for ( i = 0; i < MAX_MSIX_TABLE_PAGES; i++ )
{
- if ( dev->msix_table_idx[i] == idx )
+ if ( msix->table_idx[i] == idx )
break;
}
if ( i == MAX_MSIX_TABLE_PAGES )
goto out;
- if ( --dev->msix_table_refcnt[i] == 0 )
+ if ( --msix->table_refcnt[i] == 0 )
{
__set_fixmap(idx, 0, 0);
msix_fixmap_free(idx);
- dev->msix_table_idx[i] = 0;
+ msix->table_idx[i] = 0;
}
out:
- spin_unlock(&dev->msix_table_lock);
+ spin_unlock(&msix->table_lock);
}
/*
@@ -503,7 +503,7 @@ int msi_free_irq(struct msi_desc *entry)
{
unsigned long start;
start = (unsigned long)entry->mask_base & ~(PAGE_SIZE - 1);
- msix_put_fixmap(entry->dev, virt_to_fix(start));
+ msix_put_fixmap(entry->dev->msix, virt_to_fix(start));
nr = 1;
}
@@ -698,6 +698,7 @@ static int msix_capability_init(struct pci_dev *dev,
struct msi_desc **desc,
unsigned int nr_entries)
{
+ struct arch_msix *msix = dev->msix;
struct msi_desc *entry = NULL;
int pos, vf;
u16 control;
@@ -757,17 +758,17 @@ static int msix_capability_init(struct pci_dev *dev,
}
table_paddr += table_offset;
- if ( !dev->msix_used_entries )
+ if ( !msix->used_entries )
{
u64 pba_paddr;
u32 pba_offset;
- dev->msix_nr_entries = nr_entries;
- dev->msix_table.first = PFN_DOWN(table_paddr);
- dev->msix_table.last = PFN_DOWN(table_paddr +
- nr_entries * PCI_MSIX_ENTRY_SIZE - 1);
- WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, dev->msix_table.first,
- dev->msix_table.last));
+ msix->nr_entries = nr_entries;
+ msix->table.first = PFN_DOWN(table_paddr);
+ msix->table.last = PFN_DOWN(table_paddr +
+ nr_entries * PCI_MSIX_ENTRY_SIZE - 1);
+ WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, msix->table.first,
+ msix->table.last));
pba_offset = pci_conf_read32(seg, bus, slot, func,
msix_pba_offset_reg(pos));
@@ -776,18 +777,18 @@ static int msix_capability_init(struct pci_dev *dev,
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));
+ msix->pba.first = PFN_DOWN(pba_paddr);
+ msix->pba.last = PFN_DOWN(pba_paddr +
+ BITS_TO_LONGS(nr_entries) - 1);
+ WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, msix->pba.first,
+ msix->pba.last));
}
if ( entry )
{
/* Map MSI-X table region */
u64 entry_paddr = table_paddr + msi->entry_nr * PCI_MSIX_ENTRY_SIZE;
- int idx = msix_get_fixmap(dev, table_paddr, entry_paddr);
+ int idx = msix_get_fixmap(msix, table_paddr, entry_paddr);
void __iomem *base;
if ( idx < 0 )
@@ -815,13 +816,13 @@ static int msix_capability_init(struct pci_dev *dev,
*desc = entry;
}
- if ( !dev->msix_used_entries )
+ if ( !msix->used_entries )
{
- if ( rangeset_add_range(mmio_ro_ranges, dev->msix_table.first,
- dev->msix_table.last) )
+ if ( rangeset_add_range(mmio_ro_ranges, msix->table.first,
+ msix->table.last) )
WARN();
- if ( rangeset_add_range(mmio_ro_ranges, dev->msix_pba.first,
- dev->msix_pba.last) )
+ if ( rangeset_add_range(mmio_ro_ranges, msix->pba.first,
+ msix->pba.last) )
WARN();
if ( dev->domain )
@@ -834,16 +835,16 @@ static int msix_capability_init(struct pci_dev *dev,
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)) )
+ (iomem_access_permitted(d, msix->table.first,
+ msix->table.last) ||
+ iomem_access_permitted(d, msix->pba.first,
+ msix->pba.last)) )
break;
if ( d )
{
- if ( !is_hardware_domain(d) && dev->msix_warned != d->domain_id )
+ if ( !is_hardware_domain(d) && msix->warned != d->domain_id )
{
- dev->msix_warned = d->domain_id;
+ msix->warned = d->domain_id;
printk(XENLOG_ERR
"Potentially insecure use of MSI-X on %04x:%02x:%02x.%u by Dom%d\n",
seg, bus, slot, func, d->domain_id);
@@ -852,9 +853,9 @@ static int msix_capability_init(struct pci_dev *dev,
}
}
}
- WARN_ON(dev->msix_nr_entries != nr_entries);
- WARN_ON(dev->msix_table.first != (table_paddr >> PAGE_SHIFT));
- ++dev->msix_used_entries;
+ WARN_ON(msix->nr_entries != nr_entries);
+ WARN_ON(msix->table.first != (table_paddr >> PAGE_SHIFT));
+ ++msix->used_entries;
/* Restore MSI-X enabled bits */
pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), control);
@@ -978,15 +979,15 @@ static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc)
return status;
}
-static void _pci_cleanup_msix(struct pci_dev *dev)
+static void _pci_cleanup_msix(struct arch_msix *msix)
{
- if ( !--dev->msix_used_entries )
+ if ( !--msix->used_entries )
{
- if ( rangeset_remove_range(mmio_ro_ranges, dev->msix_table.first,
- dev->msix_table.last) )
+ if ( rangeset_remove_range(mmio_ro_ranges, msix->table.first,
+ msix->table.last) )
WARN();
- if ( rangeset_remove_range(mmio_ro_ranges, dev->msix_pba.first,
- dev->msix_pba.last) )
+ if ( rangeset_remove_range(mmio_ro_ranges, msix->pba.first,
+ msix->pba.last) )
WARN();
}
}
@@ -1014,7 +1015,7 @@ static void __pci_disable_msix(struct msi_desc *entry)
pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), control);
- _pci_cleanup_msix(dev);
+ _pci_cleanup_msix(dev->msix);
}
int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool_t off)
@@ -1035,11 +1036,11 @@ int pci_prepare_msix(u16 seg, u8 bus, u8 devfn, bool_t off)
pdev = pci_get_pdev(seg, bus, devfn);
if ( !pdev )
rc = -ENODEV;
- else if ( pdev->msix_used_entries != !!off )
+ else if ( pdev->msix->used_entries != !!off )
rc = -EBUSY;
else if ( off )
{
- _pci_cleanup_msix(pdev);
+ _pci_cleanup_msix(pdev->msix);
rc = 0;
}
else