Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1c853b5 authored by Michael Ellerman's avatar Michael Ellerman Committed by Benjamin Herrenschmidt
Browse files

powerpc/powernv: Disable interrupts while taking phb->lock



We need to disable interrupts when taking the phb->lock. Otherwise
we could deadlock with pci_lock taken from an interrupt.

Signed-off-by: default avatarMichael Ellerman <michael@ellerman.id.au>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 6fe5f5f3
Loading
Loading
Loading
Loading
+14 −8
Original line number Original line Diff line number Diff line
@@ -52,32 +52,38 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)


static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
{
{
	unsigned int id;
	unsigned long flags;
	unsigned int id, rc;

	spin_lock_irqsave(&phb->lock, flags);


	spin_lock(&phb->lock);
	id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
	id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
	if (id >= phb->msi_count && phb->msi_next)
	if (id >= phb->msi_count && phb->msi_next)
		id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
		id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
	if (id >= phb->msi_count) {
	if (id >= phb->msi_count) {
		spin_unlock(&phb->lock);
		rc = 0;
		return 0;
		goto out;
	}
	}
	__set_bit(id, phb->msi_map);
	__set_bit(id, phb->msi_map);
	spin_unlock(&phb->lock);
	rc = id + phb->msi_base;
	return id + phb->msi_base;
out:
	spin_unlock_irqrestore(&phb->lock, flags);
	return rc;
}
}


static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
{
{
	unsigned long flags;
	unsigned int id;
	unsigned int id;


	if (WARN_ON(hwirq < phb->msi_base ||
	if (WARN_ON(hwirq < phb->msi_base ||
		    hwirq >= (phb->msi_base + phb->msi_count)))
		    hwirq >= (phb->msi_base + phb->msi_count)))
		return;
		return;
	id = hwirq - phb->msi_base;
	id = hwirq - phb->msi_base;
	spin_lock(&phb->lock);

	spin_lock_irqsave(&phb->lock, flags);
	__clear_bit(id, phb->msi_map);
	__clear_bit(id, phb->msi_map);
	spin_unlock(&phb->lock);
	spin_unlock_irqrestore(&phb->lock, flags);
}
}


static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)