Skip to content

Commit 91f8ae8

Browse files
lynxeye-devbjorn-helgaas
authored andcommitted
PCI: designware: Setup and clear exactly one MSI at a time
The setup_irq function is supposed to set up exactly one MSI IRQ. Multiple IRQ setup is handled differently, to respect the choices made by the upper layers. Also only clear one MSI IRQ at a time; the PCI core will call into this function multiple times if it has to tear down more than one MSI IRQ. Signed-off-by: Lucas Stach <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Pratyush Anand <[email protected]> Acked-by: Jingoo Han <[email protected]>
1 parent 24832b4 commit 91f8ae8

File tree

1 file changed

+7
-40
lines changed

1 file changed

+7
-40
lines changed

drivers/pci/host/pcie-designware.c

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -313,54 +313,17 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
313313
return -ENOSPC;
314314
}
315315

316-
static void clear_irq(unsigned int irq)
317-
{
318-
unsigned int pos, nvec;
319-
struct msi_desc *msi;
320-
struct pcie_port *pp;
321-
struct irq_data *data = irq_get_irq_data(irq);
322-
323-
/* get the port structure */
324-
msi = irq_data_get_msi(data);
325-
pp = sys_to_pcie(msi->dev->bus->sysdata);
326-
327-
/* undo what was done in assign_irq */
328-
pos = data->hwirq;
329-
nvec = 1 << msi->msi_attrib.multiple;
330-
331-
clear_irq_range(pp, irq, nvec, pos);
332-
333-
/* all irqs cleared; reset attributes */
334-
msi->irq = 0;
335-
msi->msi_attrib.multiple = 0;
336-
}
337-
338316
static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
339317
struct msi_desc *desc)
340318
{
341-
int irq, pos, msgvec;
342-
u16 msg_ctr;
319+
int irq, pos;
343320
struct msi_msg msg;
344321
struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
345322

346-
pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS,
347-
&msg_ctr);
348-
msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4;
349-
if (msgvec == 0)
350-
msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1;
351-
if (msgvec > 5)
352-
msgvec = 0;
353-
354-
irq = assign_irq((1 << msgvec), desc, &pos);
323+
irq = assign_irq(1, desc, &pos);
355324
if (irq < 0)
356325
return irq;
357326

358-
/*
359-
* write_msi_msg() will update PCI_MSI_FLAGS so there is
360-
* no need to explicitly call pci_write_config_word().
361-
*/
362-
desc->msi_attrib.multiple = msgvec;
363-
364327
if (pp->ops->get_msi_addr)
365328
msg.address_lo = pp->ops->get_msi_addr(pp);
366329
else
@@ -379,7 +342,11 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
379342

380343
static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
381344
{
382-
clear_irq(irq);
345+
struct irq_data *data = irq_get_irq_data(irq);
346+
struct msi_desc *msi = irq_data_get_msi(data);
347+
struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
348+
349+
clear_irq_range(pp, irq, 1, data->hwirq);
383350
}
384351

385352
static struct msi_chip dw_pcie_msi_chip = {

0 commit comments

Comments
 (0)