[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 07/10] xen: pci: add per-device locking
Spinlock in struct pci_device will be used to protect access to device itself. Right now it is used mostly by MSI code. Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx> --- xen/arch/x86/hvm/vmsi.c | 6 +++++- xen/arch/x86/msi.c | 16 ++++++++++++++++ xen/drivers/passthrough/msi.c | 8 +++++++- xen/drivers/passthrough/pci.c | 2 ++ xen/include/xen/pci.h | 12 ++++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index 7fb1075673..c9e5f279c5 100644 --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -203,10 +203,14 @@ static struct msi_desc *msixtbl_addr_to_desc( nr_entry = (addr - entry->gtable) / PCI_MSIX_ENTRY_SIZE; + pcidev_lock(entry->pdev); list_for_each_entry( desc, &entry->pdev->msi_list, list ) if ( desc->msi_attrib.type == PCI_CAP_ID_MSIX && - desc->msi_attrib.entry_nr == nr_entry ) + desc->msi_attrib.entry_nr == nr_entry ) { + pcidev_unlock(entry->pdev); return desc; + } + pcidev_unlock(entry->pdev); return NULL; } diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index bccaccb98b..6b62c4f452 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -389,6 +389,7 @@ static bool msi_set_mask_bit(struct irq_desc *desc, bool host, bool guest) default: return 0; } + entry->msi_attrib.host_masked = host; entry->msi_attrib.guest_masked = guest; @@ -585,12 +586,17 @@ static struct msi_desc *find_msi_entry(struct pci_dev *dev, { struct msi_desc *entry; + pcidev_lock(dev); list_for_each_entry( entry, &dev->msi_list, list ) { if ( entry->msi_attrib.type == cap_id && (irq == -1 || entry->irq == irq) ) + { + pcidev_unlock(dev); return entry; + } } + pcidev_unlock(dev); return NULL; } @@ -661,7 +667,9 @@ static int msi_capability_init(struct pci_dev *dev, maskbits |= ~(uint32_t)0 >> (32 - dev->msi_maxvec); pci_conf_write32(dev->sbdf, mpos, maskbits); } + pcidev_lock(dev); list_add_tail(&entry->list, &dev->msi_list); + pcidev_unlock(dev); *desc = entry; /* Restore the original MSI enabled bits */ @@ -946,7 +954,9 @@ static int msix_capability_init(struct pci_dev *dev, pcidev_get(dev); + pcidev_lock(dev); list_add_tail(&entry->list, &dev->msi_list); + pcidev_unlock(dev); *desc = entry; } @@ -1231,11 +1241,13 @@ static void msi_free_irqs(struct pci_dev* dev) { struct msi_desc *entry, *tmp; + pcidev_lock(dev); list_for_each_entry_safe( entry, tmp, &dev->msi_list, list ) { pci_disable_msi(entry); msi_free_irq(entry); } + pcidev_unlock(dev); } void pci_cleanup_msi(struct pci_dev *pdev) @@ -1354,6 +1366,7 @@ int pci_restore_msi_state(struct pci_dev *pdev) if ( ret ) return ret; + pcidev_lock(pdev); list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list ) { unsigned int i = 0, nr = 1; @@ -1371,6 +1384,7 @@ int pci_restore_msi_state(struct pci_dev *pdev) dprintk(XENLOG_ERR, "Restore MSI for %pp entry %u not set?\n", &pdev->sbdf, i); spin_unlock_irqrestore(&desc->lock, flags); + pcidev_unlock(pdev); if ( type == PCI_CAP_ID_MSIX ) pci_conf_write16(pdev->sbdf, msix_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE); @@ -1393,6 +1407,7 @@ int pci_restore_msi_state(struct pci_dev *pdev) if ( unlikely(!memory_decoded(pdev)) ) { spin_unlock_irqrestore(&desc->lock, flags); + pcidev_unlock(pdev); pci_conf_write16(pdev->sbdf, msix_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE); return -ENXIO; @@ -1438,6 +1453,7 @@ int pci_restore_msi_state(struct pci_dev *pdev) pci_conf_write16(pdev->sbdf, msix_control_reg(pos), control | PCI_MSIX_FLAGS_ENABLE); + pcidev_unlock(pdev); return 0; } diff --git a/xen/drivers/passthrough/msi.c b/xen/drivers/passthrough/msi.c index ce1a450f6f..98f4d2721a 100644 --- a/xen/drivers/passthrough/msi.c +++ b/xen/drivers/passthrough/msi.c @@ -22,6 +22,7 @@ int pdev_msi_init(struct pci_dev *pdev) { unsigned int pos; + pcidev_lock(pdev); INIT_LIST_HEAD(&pdev->msi_list); pos = pci_find_cap_offset(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), @@ -41,7 +42,10 @@ int pdev_msi_init(struct pci_dev *pdev) uint16_t ctrl; if ( !msix ) - return -ENOMEM; + { + pcidev_unlock(pdev); + return -ENOMEM; + } spin_lock_init(&msix->table_lock); @@ -51,6 +55,8 @@ int pdev_msi_init(struct pci_dev *pdev) pdev->msix = msix; } + pcidev_unlock(pdev); + return 0; } diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index c8da80b981..c83397211b 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -1383,7 +1383,9 @@ static int cf_check _dump_pci_devices(struct pci_seg *pseg, void *arg) printk("%pd", pdev->domain); printk(" - node %-3d refcnt %d", (pdev->node != NUMA_NO_NODE) ? pdev->node : -1, atomic_read(&pdev->refcnt)); + pcidev_lock(pdev); pdev_dump_msi(pdev); + pcidev_unlock(pdev); printk("\n"); } spin_unlock(&pseg->alldevs_lock); diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index e71a180ef3..d0a7339d84 100644 --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -106,6 +106,8 @@ struct pci_dev { uint8_t msi_maxvec; uint8_t phantom_stride; + /* Device lock */ + spinlock_t lock; nodeid_t node; /* NUMA node */ /* Device to be quarantined, don't automatically re-assign to dom0 */ @@ -235,6 +237,16 @@ int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable); void msixtbl_pt_unregister(struct domain *, struct pirq *); void msixtbl_pt_cleanup(struct domain *d); +static inline void pcidev_lock(struct pci_dev *pdev) +{ + spin_lock(&pdev->lock); +} + +static inline void pcidev_unlock(struct pci_dev *pdev) +{ + spin_unlock(&pdev->lock); +} + #ifdef CONFIG_HVM int arch_pci_clean_pirqs(struct domain *d); #else -- 2.36.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |