diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_irq_kms.c | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 127 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware.h | 7 | ||||
| -rw-r--r-- | drivers/pci/msi/msi.c | 14 | ||||
| -rw-r--r-- | drivers/pci/msi/pcidev_msi.c | 2 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 7 |
8 files changed, 79 insertions, 91 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 60afaa8e56b4..5faae0361361 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1374,6 +1374,7 @@ int radeon_device_init(struct radeon_device *rdev, pr_warn("radeon: No suitable DMA available\n"); return r; } + rdev->pdev->msi_addr_mask = DMA_BIT_MASK(dma_bits); rdev->need_swiotlb = drm_need_swiotlb(dma_bits); /* Registers mapping */ diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 9961251b44ba..839d619e5602 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -245,16 +245,6 @@ static bool radeon_msi_ok(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_AGP) return false; - /* - * Older chips have a HW limitation, they can only generate 40 bits - * of address for "64-bit" MSIs which breaks on some platforms, notably - * IBM POWER servers, so we limit them - */ - if (rdev->family < CHIP_BONAIRE) { - dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n"); - rdev->pdev->no_64bit_msi = 1; - } - /* force MSI on */ if (radeon_msi == 1) return true; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index 70d86c5f52fb..0671deae9a28 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -331,7 +331,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_PPC64 /* Ensure MSI/MSI-X interrupts lie within addressable physical memory */ - pdev->no_64bit_msi = 1; + pdev->msi_addr_mask = DMA_BIT_MASK(32); #endif err = ionic_setup_one(ionic); diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 372207c33a85..f116591975ff 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -26,9 +26,27 @@ static struct pci_ops dw_pcie_ops; static struct pci_ops dw_pcie_ecam_ops; static struct pci_ops dw_child_pcie_ops; +#ifdef CONFIG_SMP +static void dw_irq_noop(struct irq_data *d) { } +#endif + +static bool dw_pcie_init_dev_msi_info(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, struct msi_domain_info *info) +{ + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) + return false; + +#ifdef CONFIG_SMP + info->chip->irq_ack = dw_irq_noop; + info->chip->irq_pre_redirect = irq_chip_pre_redirect_parent; +#else + info->chip->irq_ack = irq_chip_ack_parent; +#endif + return true; +} + #define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ MSI_FLAG_USE_DEF_CHIP_OPS | \ - MSI_FLAG_NO_AFFINITY | \ MSI_FLAG_PCI_MSI_MASK_PARENT) #define DW_PCIE_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \ MSI_FLAG_PCI_MSIX | \ @@ -40,41 +58,30 @@ static const struct msi_parent_ops dw_pcie_msi_parent_ops = { .required_flags = DW_PCIE_MSI_FLAGS_REQUIRED, .supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED, .bus_select_token = DOMAIN_BUS_PCI_MSI, - .chip_flags = MSI_CHIP_FLAG_SET_ACK, .prefix = "DW-", - .init_dev_msi_info = msi_lib_init_dev_msi_info, + .init_dev_msi_info = dw_pcie_init_dev_msi_info, }; /* MSI int handler */ -irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp) +void dw_handle_msi_irq(struct dw_pcie_rp *pp) { - int i, pos; - unsigned long val; - u32 status, num_ctrls; - irqreturn_t ret = IRQ_NONE; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + unsigned int i, num_ctrls; num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; for (i = 0; i < num_ctrls; i++) { - status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS + - (i * MSI_REG_CTRL_BLOCK_SIZE)); + unsigned int reg_off = i * MSI_REG_CTRL_BLOCK_SIZE; + unsigned int irq_off = i * MAX_MSI_IRQS_PER_CTRL; + unsigned long status, pos; + + status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS + reg_off); if (!status) continue; - ret = IRQ_HANDLED; - val = status; - pos = 0; - while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL, - pos)) != MAX_MSI_IRQS_PER_CTRL) { - generic_handle_domain_irq(pp->irq_domain, - (i * MAX_MSI_IRQS_PER_CTRL) + - pos); - pos++; - } + for_each_set_bit(pos, &status, MAX_MSI_IRQS_PER_CTRL) + generic_handle_demux_domain_irq(pp->irq_domain, irq_off + pos); } - - return ret; } /* Chained MSI interrupt service routine */ @@ -95,13 +102,10 @@ static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg) { struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d); struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - u64 msi_target; - - msi_target = (u64)pp->msi_data; + u64 msi_target = (u64)pp->msi_data; msg->address_lo = lower_32_bits(msi_target); msg->address_hi = upper_32_bits(msi_target); - msg->data = d->hwirq; dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n", @@ -113,18 +117,14 @@ static void dw_pci_bottom_mask(struct irq_data *d) struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d); struct dw_pcie *pci = to_dw_pcie_from_pp(pp); unsigned int res, bit, ctrl; - unsigned long flags; - - raw_spin_lock_irqsave(&pp->lock, flags); + guard(raw_spinlock)(&pp->lock); ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; pp->irq_mask[ctrl] |= BIT(bit); dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]); - - raw_spin_unlock_irqrestore(&pp->lock, flags); } static void dw_pci_bottom_unmask(struct irq_data *d) @@ -132,18 +132,14 @@ static void dw_pci_bottom_unmask(struct irq_data *d) struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d); struct dw_pcie *pci = to_dw_pcie_from_pp(pp); unsigned int res, bit, ctrl; - unsigned long flags; - - raw_spin_lock_irqsave(&pp->lock, flags); + guard(raw_spinlock)(&pp->lock); ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; pp->irq_mask[ctrl] &= ~BIT(bit); dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]); - - raw_spin_unlock_irqrestore(&pp->lock, flags); } static void dw_pci_bottom_ack(struct irq_data *d) @@ -160,54 +156,48 @@ static void dw_pci_bottom_ack(struct irq_data *d) } static struct irq_chip dw_pci_msi_bottom_irq_chip = { - .name = "DWPCI-MSI", - .irq_ack = dw_pci_bottom_ack, - .irq_compose_msi_msg = dw_pci_setup_msi_msg, - .irq_mask = dw_pci_bottom_mask, - .irq_unmask = dw_pci_bottom_unmask, + .name = "DWPCI-MSI", + .irq_compose_msi_msg = dw_pci_setup_msi_msg, + .irq_mask = dw_pci_bottom_mask, + .irq_unmask = dw_pci_bottom_unmask, +#ifdef CONFIG_SMP + .irq_ack = dw_irq_noop, + .irq_pre_redirect = dw_pci_bottom_ack, + .irq_set_affinity = irq_chip_redirect_set_affinity, +#else + .irq_ack = dw_pci_bottom_ack, +#endif }; -static int dw_pcie_irq_domain_alloc(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs, - void *args) +static int dw_pcie_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs, void *args) { struct dw_pcie_rp *pp = domain->host_data; - unsigned long flags; - u32 i; int bit; - raw_spin_lock_irqsave(&pp->lock, flags); - - bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors, - order_base_2(nr_irqs)); - - raw_spin_unlock_irqrestore(&pp->lock, flags); + scoped_guard (raw_spinlock_irq, &pp->lock) { + bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors, + order_base_2(nr_irqs)); + } if (bit < 0) return -ENOSPC; - for (i = 0; i < nr_irqs; i++) - irq_domain_set_info(domain, virq + i, bit + i, - pp->msi_irq_chip, - pp, handle_edge_irq, - NULL, NULL); - + for (unsigned int i = 0; i < nr_irqs; i++) { + irq_domain_set_info(domain, virq + i, bit + i, pp->msi_irq_chip, + pp, handle_edge_irq, NULL, NULL); + } return 0; } -static void dw_pcie_irq_domain_free(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs) +static void dw_pcie_irq_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) { struct irq_data *d = irq_domain_get_irq_data(domain, virq); struct dw_pcie_rp *pp = domain->host_data; - unsigned long flags; - raw_spin_lock_irqsave(&pp->lock, flags); - - bitmap_release_region(pp->msi_irq_in_use, d->hwirq, - order_base_2(nr_irqs)); - - raw_spin_unlock_irqrestore(&pp->lock, flags); + guard(raw_spinlock_irq)(&pp->lock); + bitmap_release_region(pp->msi_irq_in_use, d->hwirq, order_base_2(nr_irqs)); } static const struct irq_domain_ops dw_pcie_msi_domain_ops = { @@ -241,8 +231,7 @@ void dw_pcie_free_msi(struct dw_pcie_rp *pp) for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++) { if (pp->msi_irq[ctrl] > 0) - irq_set_chained_handler_and_data(pp->msi_irq[ctrl], - NULL, NULL); + irq_set_chained_handler_and_data(pp->msi_irq[ctrl], NULL, NULL); } irq_domain_remove(pp->irq_domain); diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 31685951a080..403f6cfe8191 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -821,7 +821,7 @@ static inline enum dw_pcie_ltssm dw_pcie_get_ltssm(struct dw_pcie *pci) #ifdef CONFIG_PCIE_DW_HOST int dw_pcie_suspend_noirq(struct dw_pcie *pci); int dw_pcie_resume_noirq(struct dw_pcie *pci); -irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp); +void dw_handle_msi_irq(struct dw_pcie_rp *pp); void dw_pcie_msi_init(struct dw_pcie_rp *pp); int dw_pcie_msi_host_init(struct dw_pcie_rp *pp); void dw_pcie_free_msi(struct dw_pcie_rp *pp); @@ -842,10 +842,7 @@ static inline int dw_pcie_resume_noirq(struct dw_pcie *pci) return 0; } -static inline irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp) -{ - return IRQ_NONE; -} +static inline void dw_handle_msi_irq(struct dw_pcie_rp *pp) { } static inline void dw_pcie_msi_init(struct dw_pcie_rp *pp) { } diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index 34d664139f48..e2412175d7af 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -321,14 +321,16 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, static int msi_verify_entries(struct pci_dev *dev) { struct msi_desc *entry; + u64 address; - if (!dev->no_64bit_msi) + if (dev->msi_addr_mask == DMA_BIT_MASK(64)) return 0; msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { - if (entry->msg.address_hi) { - pci_err(dev, "arch assigned 64-bit MSI address %#x%08x but device only supports 32 bits\n", - entry->msg.address_hi, entry->msg.address_lo); + address = (u64)entry->msg.address_hi << 32 | entry->msg.address_lo; + if (address & ~dev->msi_addr_mask) { + pci_err(dev, "arch assigned 64-bit MSI address %#llx above device MSI address mask %#llx\n", + address, dev->msi_addr_mask); break; } } @@ -737,7 +739,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, ret = msix_setup_interrupts(dev, entries, nvec, affd); if (ret) - goto out_disable; + goto out_unmap; /* Disable INTX */ pci_intx_for_msi(dev, 0); @@ -758,6 +760,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, pcibios_free_irq(dev); return 0; +out_unmap: + iounmap(dev->msix_base); out_disable: dev->msix_enabled = 0; pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); diff --git a/drivers/pci/msi/pcidev_msi.c b/drivers/pci/msi/pcidev_msi.c index 5520aff53b56..0b0346813092 100644 --- a/drivers/pci/msi/pcidev_msi.c +++ b/drivers/pci/msi/pcidev_msi.c @@ -24,7 +24,7 @@ void pci_msi_init(struct pci_dev *dev) } if (!(ctrl & PCI_MSI_FLAGS_64BIT)) - dev->no_64bit_msi = 1; + dev->msi_addr_mask = DMA_BIT_MASK(32); } void pci_msix_init(struct pci_dev *dev) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 41183aed8f5d..a2bff57176a3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2047,6 +2047,13 @@ int pci_setup_device(struct pci_dev *dev) */ dev->dma_mask = 0xffffffff; + /* + * Assume 64-bit addresses for MSI initially. Will be changed to 32-bit + * if MSI (rather than MSI-X) capability does not have + * PCI_MSI_FLAGS_64BIT. Can also be overridden by driver. + */ + dev->msi_addr_mask = DMA_BIT_MASK(64); + dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); |
