diff mbox

PCI: dwc: fall back to legacy IRQs when multiple devices are attached

Message ID 20170426181502.770-1-l.stach@pengutronix.de
State Not Applicable
Headers show

Commit Message

Lucas Stach April 26, 2017, 6:15 p.m. UTC
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@pengutronix.de>
---
 drivers/pci/dwc/pcie-designware-host.c | 24 ++++++++++++++++++++++--
 drivers/pci/dwc/pcie-designware.h      |  1 +
 2 files changed, 23 insertions(+), 2 deletions(-)

Comments

Tim Harvey April 26, 2017, 9:11 p.m. UTC | #1
On Wed, Apr 26, 2017 at 11:15 AM, Lucas Stach <l.stach@pengutronix.de> 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@pengutronix.de>
> ---
>  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.

Tim
Lucas Stach April 27, 2017, 8:43 a.m. UTC | #2
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@pengutronix.de> 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@pengutronix.de>
> > ---
> >  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
Tim Harvey April 27, 2017, 3:32 p.m. UTC | #3
On Thu, Apr 27, 2017 at 1:43 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> 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@pengutronix.de> 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@pengutronix.de>
>> > ---
>> >  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.
>

Lucas,

Right, I should have given you more detail. The legacy interrupts are
firing for endpoints through a bridge, but not for boards without a
bridge:

GW54xx + ath9k:
root@ventana:~# echo $(cat /proc/device-tree/model)
Gateworks Ventana i.MX6 Dual/Quad GW54XX
root@ventana:~# cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
 16:       4343       1141       2358       1998     GIC-0  29 Edge      twd
 17:         91         79         76         65       GPC  55 Level
  i.MX Timer Tick
 18:      93375          0          0          0       GPC  13 Level     mxs-dma
 19:      21611          0          0          0       GPC  15 Level     bch
 20:          0          0          0          0       GPC 115 Level
  120000.hdmi
 21:          0          0          0          0       GPC   9 Level
  130000.gpu
 22:          0          0          0          0       GPC  10 Level
  134000.gpu
 24:          3          0          0          0       GPC 120 Level
  mx6-pcie-msi, ath9k
^^^^ correct legacy irq and its firing (3 interrupts)
 26:          0          0          0          0       GPC  32 Level
  200c000.ecspi
 27:          0          0          0          0       GPC  26 Level
  2020000.serial
 28:          0          0          0          0       GPC  46 Level
  2028000.ssi
 29:          0          0          0          0       GPC  47 Level
  202c000.ssi
 30:          0          0          0          0       GPC  50 Level
  2034000.asrc
 31:          0          0          0          0       GPC  12 Level
  2040000.vpu
 49:          0          0          0          0       GPC  81 Level
  20c0000.wdog
 50:          0          0          0          0       GPC  49 Level
  imx_thermal
 55:          0          0          0          0       GPC  19 Level
  rtc alarm
 61:          2          0          0          0       GPC   2 Level     sdma
 62:          0          0          0          0       GPC  43 Level
  2184000.usb
 63:         30          0          0          0       GPC  40 Level
  2184200.usb
 64:       1699          0          0          0     GIC-0 150 Level
  2188000.ethernet
 65:          0          0          0          0     GIC-0 151 Level
  2188000.ethernet
 66:          0          0          0          0       GPC  24 Level     mmc0
 67:         30          0          0          0       GPC  36 Level
  21a0000.i2c
 68:         92          0          0          0       GPC  37 Level
  21a4000.i2c
 69:        298          0          0          0       GPC  38 Level
  21a8000.i2c
 70:          0          0          0          0       GPC  18 Level     vdoa
 71:        500          0          0          0       GPC  27 Level
  21e8000.serial
 72:          0          0          0          0       GPC  30 Level
  21f4000.serial
 75:          0          0          0          0       GPC  39 Level
  ahci-imx[2200000.sata]
 76:          0          0          0          0       GPC  11 Level
  2204000.gpu
271:          0          0          0          0  gpio-mxc   0 Edge
  2198000.usdhc cd
335:          0          0          0          0       GPC 123 Level
  PCIe PME, aerdrv
338:          0          0          0          0       IPU 457 Edge
  2400000.ipu
339:          0          0          0          0       IPU 451 Edge
  2400000.ipu
340:          0          0          0          0       IPU 457 Edge
  2800000.ipu
341:          0          0          0          0       IPU 451 Edge
  2800000.ipu
342:       1029          1          1          0       IPU  23 Edge      imx_drm
343:          0          0          0          0       IPU  28 Edge      imx_drm
344:          0          0          0          0       IPU  23 Edge      imx_drm
345:          0          0          0          0       IPU  28 Edge      imx_drm
346:          2          0          0          0       GPC 105 Level
  2101000.jr0
347:          0          0          0          0       GPC 106 Level
  2102000.jr1
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:         25         36         15         22  Timer broadcast interrupts
IPI2:        862       8482       4490       4783  Rescheduling interrupts
IPI3:         36         29         41         44  Function call interrupts
IPI4:          0          0          0          0  CPU stop interrupts
IPI5:        229        174        430        250  IRQ work interrupts
IPI6:          0          0          0          0  completion interrupts
Err:          0
root@ventana:~# lspci -t
-[0000:00]---00.0-[01]--+-00.0-[02-09]--+-01.0-[03]--
                        |               +-04.0-[04]--
                        |               +-05.0-[05]--
                        |               +-06.0-[06]--
                        |               +-07.0-[07]----00.0
                        |               +-08.0-[08]----00.0
                        |               \-09.0-[09]--
                        \-00.1

GW51xx + ath9k (no bridge):
root@ventana:~# echo $(cat /proc/device-tree/model)
Gateworks Ventana i.MX6 Dual/Quad GW51XX
root@ventana:~# cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
 16:       3818        991       1747       2665     GIC-0  29 Edge      twd
 17:         65         90         57         60       GPC  55 Level
  i.MX Timer Tick
 18:      39451          0          0          0       GPC  13 Level     mxs-dma
 19:      10397          0          0          0       GPC  15 Level     bch
 20:          0          0          0          0       GPC 115 Level
  120000.hdmi
 21:          0          0          0          0       GPC   9 Level
  130000.gpu
 22:          0          0          0          0       GPC  10 Level
  134000.gpu
 24:          0          0          0          0       GPC 120 Level
  mx6-pcie-msi
 26:          0          0          0          0       GPC  26 Level
  2020000.serial
 27:          0          0          0          0       GPC  50 Level
  2034000.asrc
 28:          0          0          0          0       GPC  12 Level
  2040000.vpu
 44:          0          0          0          0       GPC  49 Level
  imx_thermal
 49:          0          0          0          0       GPC  19 Level
  rtc alarm
 55:          0          0          0          0       GPC   2 Level     sdma
 56:          0          0          0          0       GPC  43 Level
  2184000.usb
 57:          0          0          0          0       GPC  40 Level
  2184200.usb
 58:       2186          0          0          0     GIC-0 150 Level
  2188000.ethernet
 59:          0          0          0          0     GIC-0 151 Level
  2188000.ethernet
 60:         30          0          0          0       GPC  36 Level
  21a0000.i2c
 61:         61          0          0          0       GPC  37 Level
  21a4000.i2c
 62:          0          0          0          0       GPC  38 Level
  21a8000.i2c
 63:          0          0          0          0       GPC  18 Level     vdoa
 64:        328          0          0          0       GPC  27 Level
  21e8000.serial
 65:          0          0          0          0       GPC  28 Level
  21ec000.serial
 66:          0          0          0          0       GPC  30 Level
  21f4000.serial
 69:          0          0          0          0       GPC  11 Level
  2204000.gpu
 80:          0          0          0          0  gpio-mxc   8 Level     ltc3676
296:          0          0          0          0   PCI-MSI   0 Edge
  PCIe PME, aerdrv
328:          0          0          0          0       GPC 123 Level     ath9k
^^^^ correct legacy interrupt, but not firing (0 interrupts)
329:          0          0          0          0       IPU 457 Edge
  2400000.ipu
330:          0          0          0          0       IPU 451 Edge
  2400000.ipu
331:          0          0          0          0       IPU 457 Edge
  2800000.ipu
332:          0          0          0          0       IPU 451 Edge
  2800000.ipu
333:          0          0          0          0       IPU  23 Edge      imx_drm
334:          0          0          0          0       IPU  28 Edge      imx_drm
335:          0          0          0          0       IPU  23 Edge      imx_drm
336:          0          0          0          0       IPU  28 Edge      imx_drm
337:          2          0          0          0       GPC 105 Level
  2101000.jr0
338:          0          0          0          0       GPC 106 Level
  2102000.jr1
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:         22         18         23         18  Timer broadcast interrupts
IPI2:       1016       5415      18358       6131  Rescheduling interrupts
IPI3:         40         44         34         50  Function call interrupts
IPI4:          0          0          0          0  CPU stop interrupts
IPI5:        455        152        326        609  IRQ work interrupts
IPI6:          0          0          0          0  completion interrupts
Err:          0
root@ventana:~# lspci -t
-[0000:00]---00.0-[01]----00.0

A GW51xx + ath10k (no bridge, device requesting MSI interrupts) looks
appropriate with the patch (uses MSI):
root@ventana:~# echo $(cat /proc/device-tree/model)
Gateworks Ventana i.MX6 Dual/Quad GW51XX
root@ventana:~# cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
 16:       1759       1224        771       2368     GIC-0  29 Edge      twd
 17:         38         88         71         62       GPC  55 Level
  i.MX Timer Tick
 18:      39627          0          0          0       GPC  13 Level     mxs-dma
 19:      10451          0          0          0       GPC  15 Level     bch
 20:          0          0          0          0       GPC 115 Level
  120000.hdmi
 21:          0          0          0          0       GPC   9 Level
  130000.gpu
 22:          0          0          0          0       GPC  10 Level
  134000.gpu
 24:         78          0          0          0       GPC 120 Level
  mx6-pcie-msi
 26:          0          0          0          0       GPC  26 Level
  2020000.serial
 27:          0          0          0          0       GPC  50 Level
  2034000.asrc
 28:          0          0          0          0       GPC  12 Level
  2040000.vpu
 44:          0          0          0          0       GPC  49 Level
  imx_thermal
 49:          0          0          0          0       GPC  19 Level
  rtc alarm
 55:          0          0          0          0       GPC   2 Level     sdma
 56:          0          0          0          0       GPC  43 Level
  2184000.usb
 57:          0          0          0          0       GPC  40 Level
  2184200.usb
 58:        806          0          0          0     GIC-0 150 Level
  2188000.ethernet
 59:          0          0          0          0     GIC-0 151 Level
  2188000.ethernet
 60:         30          0          0          0       GPC  36 Level
  21a0000.i2c
 61:         61          0          0          0       GPC  37 Level
  21a4000.i2c
 62:          0          0          0          0       GPC  38 Level
  21a8000.i2c
 63:          0          0          0          0       GPC  18 Level     vdoa
 64:        201          0          0          0       GPC  27 Level
  21e8000.serial
 65:          0          0          0          0       GPC  28 Level
  21ec000.serial
 66:          0          0          0          0       GPC  30 Level
  21f4000.serial
 69:          0          0          0          0       GPC  11 Level
  2204000.gpu
 80:          0          0          0          0  gpio-mxc   8 Level     ltc3676
296:          0          0          0          0   PCI-MSI   0 Edge
  PCIe PME, aerdrv
297:         78          0          0          0   PCI-MSI   1 Edge
  ath10k_pci
^^^^ MSI interrupt and its firing (78 interrupts)
329:          0          0          0          0       IPU 457 Edge
  2400000.ipu
330:          0          0          0          0       IPU 451 Edge
  2400000.ipu
331:          0          0          0          0       IPU 457 Edge
  2800000.ipu
332:          0          0          0          0       IPU 451 Edge
  2800000.ipu
333:          0          0          0          0       IPU  23 Edge      imx_drm
334:          0          0          0          0       IPU  28 Edge      imx_drm
335:          0          0          0          0       IPU  23 Edge      imx_drm
336:          0          0          0          0       IPU  28 Edge      imx_drm
337:          2          0          0          0       GPC 105 Level
  2101000.jr0
338:          0          0          0          0       GPC 106 Level
  2102000.jr1
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:         12         24         13         20  Timer broadcast interrupts
IPI2:        905       7340      17490       6554  Rescheduling interrupts
IPI3:         50         49         34         48  Function call interrupts
IPI4:          0          0          0          0  CPU stop interrupts
IPI5:        192        160         60         29  IRQ work interrupts
IPI6:          0          0          0          0  completion interrupts
Err:          0
root@ventana:~# lspci -t
-[0000:00]---00.0-[01]----00.0
root@ventana:~# grep ath /proc/interrupts
297:         78          0          0          0   PCI-MSI   1 Edge
  ath10k_pci

Regards,

Tim
Tim Harvey May 10, 2017, 9:44 p.m. UTC | #4
On Thu, Apr 27, 2017 at 8:32 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> On Thu, Apr 27, 2017 at 1:43 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
>> 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@pengutronix.de> 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@pengutronix.de>
>>> > ---
>>> >  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.
>>
>
> Lucas,
>
> Right, I should have given you more detail. The legacy interrupts are
> firing for endpoints through a bridge, but not for boards without a
> bridge:
>
> GW54xx + ath9k:
> root@ventana:~# echo $(cat /proc/device-tree/model)
> Gateworks Ventana i.MX6 Dual/Quad GW54XX
> root@ventana:~# cat /proc/interrupts
>            CPU0       CPU1       CPU2       CPU3
>  16:       4343       1141       2358       1998     GIC-0  29 Edge      twd
>  17:         91         79         76         65       GPC  55 Level
>   i.MX Timer Tick
>  18:      93375          0          0          0       GPC  13 Level     mxs-dma
>  19:      21611          0          0          0       GPC  15 Level     bch
>  20:          0          0          0          0       GPC 115 Level
>   120000.hdmi
>  21:          0          0          0          0       GPC   9 Level
>   130000.gpu
>  22:          0          0          0          0       GPC  10 Level
>   134000.gpu
>  24:          3          0          0          0       GPC 120 Level
>   mx6-pcie-msi, ath9k
> ^^^^ correct legacy irq and its firing (3 interrupts)
>  26:          0          0          0          0       GPC  32 Level
>   200c000.ecspi
>  27:          0          0          0          0       GPC  26 Level
>   2020000.serial
>  28:          0          0          0          0       GPC  46 Level
>   2028000.ssi
>  29:          0          0          0          0       GPC  47 Level
>   202c000.ssi
>  30:          0          0          0          0       GPC  50 Level
>   2034000.asrc
>  31:          0          0          0          0       GPC  12 Level
>   2040000.vpu
>  49:          0          0          0          0       GPC  81 Level
>   20c0000.wdog
>  50:          0          0          0          0       GPC  49 Level
>   imx_thermal
>  55:          0          0          0          0       GPC  19 Level
>   rtc alarm
>  61:          2          0          0          0       GPC   2 Level     sdma
>  62:          0          0          0          0       GPC  43 Level
>   2184000.usb
>  63:         30          0          0          0       GPC  40 Level
>   2184200.usb
>  64:       1699          0          0          0     GIC-0 150 Level
>   2188000.ethernet
>  65:          0          0          0          0     GIC-0 151 Level
>   2188000.ethernet
>  66:          0          0          0          0       GPC  24 Level     mmc0
>  67:         30          0          0          0       GPC  36 Level
>   21a0000.i2c
>  68:         92          0          0          0       GPC  37 Level
>   21a4000.i2c
>  69:        298          0          0          0       GPC  38 Level
>   21a8000.i2c
>  70:          0          0          0          0       GPC  18 Level     vdoa
>  71:        500          0          0          0       GPC  27 Level
>   21e8000.serial
>  72:          0          0          0          0       GPC  30 Level
>   21f4000.serial
>  75:          0          0          0          0       GPC  39 Level
>   ahci-imx[2200000.sata]
>  76:          0          0          0          0       GPC  11 Level
>   2204000.gpu
> 271:          0          0          0          0  gpio-mxc   0 Edge
>   2198000.usdhc cd
> 335:          0          0          0          0       GPC 123 Level
>   PCIe PME, aerdrv
> 338:          0          0          0          0       IPU 457 Edge
>   2400000.ipu
> 339:          0          0          0          0       IPU 451 Edge
>   2400000.ipu
> 340:          0          0          0          0       IPU 457 Edge
>   2800000.ipu
> 341:          0          0          0          0       IPU 451 Edge
>   2800000.ipu
> 342:       1029          1          1          0       IPU  23 Edge      imx_drm
> 343:          0          0          0          0       IPU  28 Edge      imx_drm
> 344:          0          0          0          0       IPU  23 Edge      imx_drm
> 345:          0          0          0          0       IPU  28 Edge      imx_drm
> 346:          2          0          0          0       GPC 105 Level
>   2101000.jr0
> 347:          0          0          0          0       GPC 106 Level
>   2102000.jr1
> IPI0:          0          0          0          0  CPU wakeup interrupts
> IPI1:         25         36         15         22  Timer broadcast interrupts
> IPI2:        862       8482       4490       4783  Rescheduling interrupts
> IPI3:         36         29         41         44  Function call interrupts
> IPI4:          0          0          0          0  CPU stop interrupts
> IPI5:        229        174        430        250  IRQ work interrupts
> IPI6:          0          0          0          0  completion interrupts
> Err:          0
> root@ventana:~# lspci -t
> -[0000:00]---00.0-[01]--+-00.0-[02-09]--+-01.0-[03]--
>                         |               +-04.0-[04]--
>                         |               +-05.0-[05]--
>                         |               +-06.0-[06]--
>                         |               +-07.0-[07]----00.0
>                         |               +-08.0-[08]----00.0
>                         |               \-09.0-[09]--
>                         \-00.1
>
> GW51xx + ath9k (no bridge):
> root@ventana:~# echo $(cat /proc/device-tree/model)
> Gateworks Ventana i.MX6 Dual/Quad GW51XX
> root@ventana:~# cat /proc/interrupts
>            CPU0       CPU1       CPU2       CPU3
>  16:       3818        991       1747       2665     GIC-0  29 Edge      twd
>  17:         65         90         57         60       GPC  55 Level
>   i.MX Timer Tick
>  18:      39451          0          0          0       GPC  13 Level     mxs-dma
>  19:      10397          0          0          0       GPC  15 Level     bch
>  20:          0          0          0          0       GPC 115 Level
>   120000.hdmi
>  21:          0          0          0          0       GPC   9 Level
>   130000.gpu
>  22:          0          0          0          0       GPC  10 Level
>   134000.gpu
>  24:          0          0          0          0       GPC 120 Level
>   mx6-pcie-msi
>  26:          0          0          0          0       GPC  26 Level
>   2020000.serial
>  27:          0          0          0          0       GPC  50 Level
>   2034000.asrc
>  28:          0          0          0          0       GPC  12 Level
>   2040000.vpu
>  44:          0          0          0          0       GPC  49 Level
>   imx_thermal
>  49:          0          0          0          0       GPC  19 Level
>   rtc alarm
>  55:          0          0          0          0       GPC   2 Level     sdma
>  56:          0          0          0          0       GPC  43 Level
>   2184000.usb
>  57:          0          0          0          0       GPC  40 Level
>   2184200.usb
>  58:       2186          0          0          0     GIC-0 150 Level
>   2188000.ethernet
>  59:          0          0          0          0     GIC-0 151 Level
>   2188000.ethernet
>  60:         30          0          0          0       GPC  36 Level
>   21a0000.i2c
>  61:         61          0          0          0       GPC  37 Level
>   21a4000.i2c
>  62:          0          0          0          0       GPC  38 Level
>   21a8000.i2c
>  63:          0          0          0          0       GPC  18 Level     vdoa
>  64:        328          0          0          0       GPC  27 Level
>   21e8000.serial
>  65:          0          0          0          0       GPC  28 Level
>   21ec000.serial
>  66:          0          0          0          0       GPC  30 Level
>   21f4000.serial
>  69:          0          0          0          0       GPC  11 Level
>   2204000.gpu
>  80:          0          0          0          0  gpio-mxc   8 Level     ltc3676
> 296:          0          0          0          0   PCI-MSI   0 Edge
>   PCIe PME, aerdrv
> 328:          0          0          0          0       GPC 123 Level     ath9k
> ^^^^ correct legacy interrupt, but not firing (0 interrupts)
> 329:          0          0          0          0       IPU 457 Edge
>   2400000.ipu
> 330:          0          0          0          0       IPU 451 Edge
>   2400000.ipu
> 331:          0          0          0          0       IPU 457 Edge
>   2800000.ipu
> 332:          0          0          0          0       IPU 451 Edge
>   2800000.ipu
> 333:          0          0          0          0       IPU  23 Edge      imx_drm
> 334:          0          0          0          0       IPU  28 Edge      imx_drm
> 335:          0          0          0          0       IPU  23 Edge      imx_drm
> 336:          0          0          0          0       IPU  28 Edge      imx_drm
> 337:          2          0          0          0       GPC 105 Level
>   2101000.jr0
> 338:          0          0          0          0       GPC 106 Level
>   2102000.jr1
> IPI0:          0          0          0          0  CPU wakeup interrupts
> IPI1:         22         18         23         18  Timer broadcast interrupts
> IPI2:       1016       5415      18358       6131  Rescheduling interrupts
> IPI3:         40         44         34         50  Function call interrupts
> IPI4:          0          0          0          0  CPU stop interrupts
> IPI5:        455        152        326        609  IRQ work interrupts
> IPI6:          0          0          0          0  completion interrupts
> Err:          0
> root@ventana:~# lspci -t
> -[0000:00]---00.0-[01]----00.0
>
> A GW51xx + ath10k (no bridge, device requesting MSI interrupts) looks
> appropriate with the patch (uses MSI):
> root@ventana:~# echo $(cat /proc/device-tree/model)
> Gateworks Ventana i.MX6 Dual/Quad GW51XX
> root@ventana:~# cat /proc/interrupts
>            CPU0       CPU1       CPU2       CPU3
>  16:       1759       1224        771       2368     GIC-0  29 Edge      twd
>  17:         38         88         71         62       GPC  55 Level
>   i.MX Timer Tick
>  18:      39627          0          0          0       GPC  13 Level     mxs-dma
>  19:      10451          0          0          0       GPC  15 Level     bch
>  20:          0          0          0          0       GPC 115 Level
>   120000.hdmi
>  21:          0          0          0          0       GPC   9 Level
>   130000.gpu
>  22:          0          0          0          0       GPC  10 Level
>   134000.gpu
>  24:         78          0          0          0       GPC 120 Level
>   mx6-pcie-msi
>  26:          0          0          0          0       GPC  26 Level
>   2020000.serial
>  27:          0          0          0          0       GPC  50 Level
>   2034000.asrc
>  28:          0          0          0          0       GPC  12 Level
>   2040000.vpu
>  44:          0          0          0          0       GPC  49 Level
>   imx_thermal
>  49:          0          0          0          0       GPC  19 Level
>   rtc alarm
>  55:          0          0          0          0       GPC   2 Level     sdma
>  56:          0          0          0          0       GPC  43 Level
>   2184000.usb
>  57:          0          0          0          0       GPC  40 Level
>   2184200.usb
>  58:        806          0          0          0     GIC-0 150 Level
>   2188000.ethernet
>  59:          0          0          0          0     GIC-0 151 Level
>   2188000.ethernet
>  60:         30          0          0          0       GPC  36 Level
>   21a0000.i2c
>  61:         61          0          0          0       GPC  37 Level
>   21a4000.i2c
>  62:          0          0          0          0       GPC  38 Level
>   21a8000.i2c
>  63:          0          0          0          0       GPC  18 Level     vdoa
>  64:        201          0          0          0       GPC  27 Level
>   21e8000.serial
>  65:          0          0          0          0       GPC  28 Level
>   21ec000.serial
>  66:          0          0          0          0       GPC  30 Level
>   21f4000.serial
>  69:          0          0          0          0       GPC  11 Level
>   2204000.gpu
>  80:          0          0          0          0  gpio-mxc   8 Level     ltc3676
> 296:          0          0          0          0   PCI-MSI   0 Edge
>   PCIe PME, aerdrv
> 297:         78          0          0          0   PCI-MSI   1 Edge
>   ath10k_pci
> ^^^^ MSI interrupt and its firing (78 interrupts)
> 329:          0          0          0          0       IPU 457 Edge
>   2400000.ipu
> 330:          0          0          0          0       IPU 451 Edge
>   2400000.ipu
> 331:          0          0          0          0       IPU 457 Edge
>   2800000.ipu
> 332:          0          0          0          0       IPU 451 Edge
>   2800000.ipu
> 333:          0          0          0          0       IPU  23 Edge      imx_drm
> 334:          0          0          0          0       IPU  28 Edge      imx_drm
> 335:          0          0          0          0       IPU  23 Edge      imx_drm
> 336:          0          0          0          0       IPU  28 Edge      imx_drm
> 337:          2          0          0          0       GPC 105 Level
>   2101000.jr0
> 338:          0          0          0          0       GPC 106 Level
>   2102000.jr1
> IPI0:          0          0          0          0  CPU wakeup interrupts
> IPI1:         12         24         13         20  Timer broadcast interrupts
> IPI2:        905       7340      17490       6554  Rescheduling interrupts
> IPI3:         50         49         34         48  Function call interrupts
> IPI4:          0          0          0          0  CPU stop interrupts
> IPI5:        192        160         60         29  IRQ work interrupts
> IPI6:          0          0          0          0  completion interrupts
> Err:          0
> root@ventana:~# lspci -t
> -[0000:00]---00.0-[01]----00.0
> root@ventana:~# grep ath /proc/interrupts
> 297:         78          0          0          0   PCI-MSI   1 Edge
>   ath10k_pci
>
> Regards,
>
> Tim

Lucas,

Are you not able to repeat my findings?

Since Linux 4.8 IMX PCIe is completely broken for PCIe devices that do
not support MSI interrupts (and there are a whole lot of 802.11n
radios that fall into this category) as you can no longer disable MSI
because the IMX PCIe driver depends on it.

It seems like your patch is the right approach but something must
still be getting set that causes the legacy interrupts to not fire.

Regards,

Tim
Lucas Stach May 11, 2017, 8:16 a.m. UTC | #5
Hi Tim,

Am Mittwoch, den 10.05.2017, 14:44 -0700 schrieb Tim Harvey:
> On Thu, Apr 27, 2017 at 8:32 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> > On Thu, Apr 27, 2017 at 1:43 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> >> 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@pengutronix.de> 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@pengutronix.de>
> >>> > ---
[...]
> Lucas,
> 
> Are you not able to repeat my findings?

Yes, I see what's going on.

> Since Linux 4.8 IMX PCIe is completely broken for PCIe devices that do
> not support MSI interrupts (and there are a whole lot of 802.11n
> radios that fall into this category) as you can no longer disable MSI
> because the IMX PCIe driver depends on it.
> 
> It seems like your patch is the right approach but something must
> still be getting set that causes the legacy interrupts to not fire.

The issue here are the port-services, which are using MSI when
available, which might conflict with the device requirements, even if
only a single device is attached.

Probably we need to disable MSI on all systems, unless we know that we
absolutely need them (EP devices, which don't support legacy IRQs). I'll
send a patch to do this, but other issues have been higher priority
again.

Regards,
Lucas
Tim Harvey May 11, 2017, 2:08 p.m. UTC | #6
On Thu, May 11, 2017 at 1:16 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> Hi Tim,
>
> Am Mittwoch, den 10.05.2017, 14:44 -0700 schrieb Tim Harvey:
>> On Thu, Apr 27, 2017 at 8:32 AM, Tim Harvey <tharvey@gateworks.com> wrote:
>> > On Thu, Apr 27, 2017 at 1:43 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
>> >> 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@pengutronix.de> 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@pengutronix.de>
>> >>> > ---
> [...]
>> Lucas,
>>
>> Are you not able to repeat my findings?
>
> Yes, I see what's going on.
>
>> Since Linux 4.8 IMX PCIe is completely broken for PCIe devices that do
>> not support MSI interrupts (and there are a whole lot of 802.11n
>> radios that fall into this category) as you can no longer disable MSI
>> because the IMX PCIe driver depends on it.
>>
>> It seems like your patch is the right approach but something must
>> still be getting set that causes the legacy interrupts to not fire.
>
> The issue here are the port-services, which are using MSI when
> available, which might conflict with the device requirements, even if
> only a single device is attached.
>
> Probably we need to disable MSI on all systems, unless we know that we
> absolutely need them (EP devices, which don't support legacy IRQs). I'll
> send a patch to do this, but other issues have been higher priority
> again.
>
> Regards,
> Lucas
>

Lucas,

Thanks, this fix is something that's beyond my experience or I would
be glad to do it. The PCIe driver has been changing very rapidly in
recent kernel versions and there is no single patch that can be
reverted to 'fix' this long-standing issue. I'm really surprised
others haven't chimed in with reports of it being broken as its been
an issue since 4.8.

Is it worth removing the 'depends on PCI_MSI_IRQ_DOMAIN' from
PCIE_DW_HOST and PCI_IMX6 and defaulting MSI off until your proposed
fix is ready and working? That is precisely what I have to do on 4.8+
kernels to get them working for our IMX6 users using ath9k radios
(making distro's like Ubuntu a problem as they run a fairly standard
4.8 kernel).

Tim
Tim Harvey June 8, 2017, 3:48 p.m. UTC | #7
On Thu, May 11, 2017 at 7:08 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> On Thu, May 11, 2017 at 1:16 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
>> Hi Tim,
>>
>> Am Mittwoch, den 10.05.2017, 14:44 -0700 schrieb Tim Harvey:
>>> On Thu, Apr 27, 2017 at 8:32 AM, Tim Harvey <tharvey@gateworks.com> wrote:
>>> > On Thu, Apr 27, 2017 at 1:43 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
>>> >> 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@pengutronix.de> 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@pengutronix.de>
>>> >>> > ---
>> [...]
>>> Lucas,
>>>
>>> Are you not able to repeat my findings?
>>
>> Yes, I see what's going on.
>>
>>> Since Linux 4.8 IMX PCIe is completely broken for PCIe devices that do
>>> not support MSI interrupts (and there are a whole lot of 802.11n
>>> radios that fall into this category) as you can no longer disable MSI
>>> because the IMX PCIe driver depends on it.
>>>
>>> It seems like your patch is the right approach but something must
>>> still be getting set that causes the legacy interrupts to not fire.
>>
>> The issue here are the port-services, which are using MSI when
>> available, which might conflict with the device requirements, even if
>> only a single device is attached.
>>
>> Probably we need to disable MSI on all systems, unless we know that we
>> absolutely need them (EP devices, which don't support legacy IRQs). I'll
>> send a patch to do this, but other issues have been higher priority
>> again.
>>
>> Regards,
>> Lucas
>>
>
> Lucas,
>
> Thanks, this fix is something that's beyond my experience or I would
> be glad to do it. The PCIe driver has been changing very rapidly in
> recent kernel versions and there is no single patch that can be
> reverted to 'fix' this long-standing issue. I'm really surprised
> others haven't chimed in with reports of it being broken as its been
> an issue since 4.8.
>
> Is it worth removing the 'depends on PCI_MSI_IRQ_DOMAIN' from
> PCIE_DW_HOST and PCI_IMX6 and defaulting MSI off until your proposed
> fix is ready and working? That is precisely what I have to do on 4.8+
> kernels to get them working for our IMX6 users using ath9k radios
> (making distro's like Ubuntu a problem as they run a fairly standard
> 4.8 kernel).
>
> Tim

Lucas,

Any cycles to put together another attempt to allow legacy IRQ's on IMX6?

Thanks,

Tim
Tim Harvey Aug. 24, 2017, 3:51 p.m. UTC | #8
On Thu, Jun 8, 2017 at 8:48 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> On Thu, May 11, 2017 at 7:08 AM, Tim Harvey <tharvey@gateworks.com> wrote:
>> On Thu, May 11, 2017 at 1:16 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
>>> Hi Tim,
>>>
>>> Am Mittwoch, den 10.05.2017, 14:44 -0700 schrieb Tim Harvey:
>>>> On Thu, Apr 27, 2017 at 8:32 AM, Tim Harvey <tharvey@gateworks.com> wrote:
>>>> > On Thu, Apr 27, 2017 at 1:43 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
>>>> >> 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@pengutronix.de> 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@pengutronix.de>
>>>> >>> > ---
>>> [...]
>>>> Lucas,
>>>>
>>>> Are you not able to repeat my findings?
>>>
>>> Yes, I see what's going on.
>>>
>>>> Since Linux 4.8 IMX PCIe is completely broken for PCIe devices that do
>>>> not support MSI interrupts (and there are a whole lot of 802.11n
>>>> radios that fall into this category) as you can no longer disable MSI
>>>> because the IMX PCIe driver depends on it.
>>>>
>>>> It seems like your patch is the right approach but something must
>>>> still be getting set that causes the legacy interrupts to not fire.
>>>
>>> The issue here are the port-services, which are using MSI when
>>> available, which might conflict with the device requirements, even if
>>> only a single device is attached.
>>>
>>> Probably we need to disable MSI on all systems, unless we know that we
>>> absolutely need them (EP devices, which don't support legacy IRQs). I'll
>>> send a patch to do this, but other issues have been higher priority
>>> again.
>>>
>>> Regards,
>>> Lucas
>>>
>>
>> Lucas,
>>
>> Thanks, this fix is something that's beyond my experience or I would
>> be glad to do it. The PCIe driver has been changing very rapidly in
>> recent kernel versions and there is no single patch that can be
>> reverted to 'fix' this long-standing issue. I'm really surprised
>> others haven't chimed in with reports of it being broken as its been
>> an issue since 4.8.
>>
>> Is it worth removing the 'depends on PCI_MSI_IRQ_DOMAIN' from
>> PCIE_DW_HOST and PCI_IMX6 and defaulting MSI off until your proposed
>> fix is ready and working? That is precisely what I have to do on 4.8+
>> kernels to get them working for our IMX6 users using ath9k radios
>> (making distro's like Ubuntu a problem as they run a fairly standard
>> 4.8 kernel).
>>
>> Tim
>
> Lucas,
>
> Any cycles to put together another attempt to allow legacy IRQ's on IMX6?
>

Lucas,

Any update on this? We still have broken legacy PCI interrupts on IMX6
on mainline.

Regards,

Tim
diff mbox

Patch

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 {