Re: [PATCH] PCI: dwc: fall back to legacy IRQs when multiple devices are attached

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Mittwoch, den 26.04.2017, 14:11 -0700 schrieb Tim Harvey:
> On Wed, Apr 26, 2017 at 11:15 AM, Lucas Stach <l.stach@xxxxxxxxxxxxxx> wrote:
> > The DWC host does not support legacy PCI IRQs and MSIs at the same time,
> > so we need to fall back to using only legacy IRQs if there is a chance
> > that multiple devices with differing MSI capabilities are connected to
> > the host. The only configuration where MSIs can be safely used is when
> > the device below the host bridge is not a bridge, i.e. the only device
> > connected to this host.
> >
> > By disallowing MSI allocation when multiple devices might be attached
> > we get those configurations in a working state. The only configurations
> > that depend on MSIs being available, that I am aware of, are some
> > embedded devices with a PCIe attached FPGA, that is incapable of
> > generating PCI legacy IRQs. Those are kept working by allowing MSIs
> > when only a single device is attached to the host.
> >
> > Signed-off-by: Lucas Stach <l.stach@xxxxxxxxxxxxxx>
> > ---
> >  drivers/pci/dwc/pcie-designware-host.c | 24 ++++++++++++++++++++++--
> >  drivers/pci/dwc/pcie-designware.h      |  1 +
> >  2 files changed, 23 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/dwc/pcie-designware-host.c
> > index 5ba334938b52..be2b2762c944 100644
> > --- a/drivers/pci/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/dwc/pcie-designware-host.c
> > @@ -92,6 +92,8 @@ void dw_pcie_msi_init(struct pcie_port *pp)
> >                             (u32)(msi_target & 0xffffffff));
> >         dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4,
> >                             (u32)(msi_target >> 32 & 0xffffffff));
> > +
> > +       pp->msi_disabled = false;
> >  }
> >
> >  static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
> > @@ -136,9 +138,11 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
> >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> >  {
> >         int irq, pos0, i;
> > -       struct pcie_port *pp;
> > +       struct pcie_port *pp = (struct pcie_port *)msi_desc_to_pci_sysdata(desc);
> > +
> > +       if (pp->msi_disabled)
> > +               return -EINVAL;
> >
> > -       pp = (struct pcie_port *)msi_desc_to_pci_sysdata(desc);
> >         pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> >                                        order_base_2(no_irqs));
> >         if (pos0 < 0)
> > @@ -410,6 +414,22 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >                 goto error;
> >         }
> >
> > +       /*
> > +        * The DWC host does not support legacy PCI IRQs and MSIs at the same
> > +        * time, so we need to fall back to using only legacy IRQs if there is
> > +        * a chance that multiple devices with differing MSI capabilities are
> > +        * connected to the host. The only configuration where MSIs can be
> > +        * safely used is when the device below the host bridge is not a bridge,
> > +        * i.e. the only device connected to this host.
> > +        */
> > +       child = list_first_entry(&bus->children, struct pci_bus, node);
> > +       if (!list_empty(&child->devices)) {
> > +               struct pci_dev *dev = list_first_entry(&child->devices,
> > +                                                      struct pci_dev, bus_list);
> > +               if (pci_is_bridge(dev))
> > +                       pp->msi_disabled = true;
> > +       }
> > +
> >         if (pp->ops->scan_bus)
> >                 pp->ops->scan_bus(pp);
> >
> > diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h
> > index cd3b8713fe50..741bc31f8947 100644
> > --- a/drivers/pci/dwc/pcie-designware.h
> > +++ b/drivers/pci/dwc/pcie-designware.h
> > @@ -140,6 +140,7 @@ struct pcie_port {
> >         struct irq_domain       *irq_domain;
> >         unsigned long           msi_data;
> >         DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
> > +       bool                    msi_disabled;
> >  };
> >
> >  struct dw_pcie_ops {
> > --
> > 2.11.0
> >
> 
> Lucas,
> 
> Legacy interrupts are still not firing with this.

Can you provide me the output of "cat /proc/interrupts" and "lspci -t"
on your system? I've tested this change on the GW54xx and legacy IRQs
seemed to work there.

Regards,
Lucas





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux