[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] AMD IOMMU: enable for multi-vector MSI
commit c610867bf4b3a1e92a7f2a1a95e4e625160be956 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Jul 16 11:55:33 2013 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Jul 16 11:55:33 2013 +0200 AMD IOMMU: enable for multi-vector MSI The main change being to make alloc_intremap_entry() capable of allocating a block of entries. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> --- xen/drivers/passthrough/amd/iommu_intr.c | 63 ++++++++++++++++++++++++------ 1 files changed, 51 insertions(+), 12 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c index a46064e..62bdc7b 100644 --- a/xen/drivers/passthrough/amd/iommu_intr.c +++ b/xen/drivers/passthrough/amd/iommu_intr.c @@ -47,13 +47,33 @@ static int get_intremap_requestor_id(int seg, int bdf) return get_ivrs_mappings(seg)[bdf].dte_requestor_id; } -static unsigned int alloc_intremap_entry(int seg, int bdf) +static unsigned int alloc_intremap_entry(int seg, int bdf, unsigned int nr) { unsigned long *inuse = get_ivrs_mappings(seg)[bdf].intremap_inuse; unsigned int slot = find_first_zero_bit(inuse, INTREMAP_ENTRIES); - if ( slot < INTREMAP_ENTRIES ) - __set_bit(slot, inuse); + for ( ; ; ) + { + unsigned int end; + + if ( slot >= INTREMAP_ENTRIES ) + break; + end = find_next_bit(inuse, INTREMAP_ENTRIES, slot + 1); + if ( end > INTREMAP_ENTRIES ) + end = INTREMAP_ENTRIES; + slot = (slot + nr - 1) & ~(nr - 1); + if ( slot + nr <= end ) + { + while ( nr-- ) + __set_bit(slot + nr, inuse); + break; + } + slot = (end + nr) & ~(nr - 1); + if ( slot >= INTREMAP_ENTRIES ) + break; + slot = find_next_zero_bit(inuse, INTREMAP_ENTRIES, slot); + } + return slot; } @@ -138,7 +158,7 @@ static int update_intremap_entry_from_ioapic( offset = *index; if ( offset >= INTREMAP_ENTRIES ) { - offset = alloc_intremap_entry(iommu->seg, req_id); + offset = alloc_intremap_entry(iommu->seg, req_id, 1); if ( offset >= INTREMAP_ENTRIES ) { spin_unlock_irqrestore(lock, flags); @@ -221,7 +241,7 @@ int __init amd_iommu_setup_ioapic_remapping(void) dest = rte.dest.logical.logical_dest; spin_lock_irqsave(lock, flags); - offset = alloc_intremap_entry(seg, req_id); + offset = alloc_intremap_entry(seg, req_id, 1); BUG_ON(offset >= INTREMAP_ENTRIES); entry = get_intremap_entry(iommu->seg, req_id, offset); update_intremap_entry(entry, vector, @@ -355,7 +375,7 @@ unsigned int amd_iommu_read_ioapic_from_ire( } static int update_intremap_entry_from_msi_msg( - struct amd_iommu *iommu, u16 bdf, + struct amd_iommu *iommu, u16 bdf, unsigned int nr, int *remap_index, const struct msi_msg *msg, u32 *data) { unsigned long flags; @@ -363,7 +383,7 @@ static int update_intremap_entry_from_msi_msg( u16 req_id, alias_id; u8 delivery_mode, dest, vector, dest_mode; spinlock_t *lock; - unsigned int offset; + unsigned int offset, i; req_id = get_dma_requestor_id(iommu->seg, bdf); alias_id = get_intremap_requestor_id(iommu->seg, bdf); @@ -372,7 +392,8 @@ static int update_intremap_entry_from_msi_msg( { lock = get_intremap_lock(iommu->seg, req_id); spin_lock_irqsave(lock, flags); - free_intremap_entry(iommu->seg, req_id, *remap_index); + for ( i = 0; i < nr; ++i ) + free_intremap_entry(iommu->seg, req_id, *remap_index + i); spin_unlock_irqrestore(lock, flags); goto done; } @@ -387,7 +408,8 @@ static int update_intremap_entry_from_msi_msg( offset = *remap_index; if ( offset >= INTREMAP_ENTRIES ) { - offset = alloc_intremap_entry(iommu->seg, bdf); + ASSERT(nr); + offset = alloc_intremap_entry(iommu->seg, bdf, nr); if ( offset >= INTREMAP_ENTRIES ) { spin_unlock_irqrestore(lock, flags); @@ -453,6 +475,7 @@ int amd_iommu_msi_msg_update_ire( struct pci_dev *pdev = msi_desc->dev; int bdf, seg, rc; struct amd_iommu *iommu; + unsigned int i, nr = 1; u32 data; bdf = pdev ? PCI_BDF2(pdev->bus, pdev->devfn) : hpet_sbdf.bdf; @@ -462,10 +485,13 @@ int amd_iommu_msi_msg_update_ire( if ( IS_ERR_OR_NULL(iommu) ) return PTR_ERR(iommu); + if ( msi_desc->msi_attrib.type == PCI_CAP_ID_MSI ) + nr = msi_desc->msi.nvec; + if ( msi_desc->remap_index >= 0 && !msg ) { do { - update_intremap_entry_from_msi_msg(iommu, bdf, + update_intremap_entry_from_msi_msg(iommu, bdf, nr, &msi_desc->remap_index, NULL, NULL); if ( !pdev || !pdev->phantom_stride ) @@ -473,7 +499,8 @@ int amd_iommu_msi_msg_update_ire( bdf += pdev->phantom_stride; } while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) ); - msi_desc->remap_index = -1; + for ( i = 0; i < nr; ++i ) + msi_desc[i].remap_index = -1; if ( pdev ) bdf = PCI_BDF2(pdev->bus, pdev->devfn); } @@ -482,7 +509,7 @@ int amd_iommu_msi_msg_update_ire( return 0; do { - rc = update_intremap_entry_from_msi_msg(iommu, bdf, + rc = update_intremap_entry_from_msi_msg(iommu, bdf, nr, &msi_desc->remap_index, msg, &data); if ( rc || !pdev || !pdev->phantom_stride ) @@ -490,6 +517,10 @@ int amd_iommu_msi_msg_update_ire( bdf += pdev->phantom_stride; } while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) ); + if ( !rc ) + for ( i = 1; i < nr; ++i ) + msi_desc[i].remap_index = msi_desc->remap_index + i; + msg->data = data; return rc; } @@ -508,6 +539,14 @@ void amd_iommu_read_msi_from_ire( entry = get_intremap_entry(seg, get_dma_requestor_id(seg, bdf), offset); + if ( msi_desc->msi_attrib.type == PCI_CAP_ID_MSI ) + { + int nr = msi_desc->msi_attrib.entry_nr; + + ASSERT(!(offset & (msi_desc[-nr].msi.nvec - 1))); + offset |= nr; + } + msg->data &= ~(INTREMAP_ENTRIES - 1); msg->data |= get_field_from_reg_u32(*entry, INT_REMAP_ENTRY_INTTYPE_MASK, -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |