* [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge
@ 2024-09-30 19:42 Frank Li
2024-09-30 19:42 ` [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges Frank Li
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Frank Li @ 2024-09-30 19:42 UTC (permalink / raw)
To: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
Cc: linux-pci, linux-kernel, linux-arm-kernel, imx, Frank.li, alyssa,
bpf, broonie, jgg, joro, l.stach, lgirdwood, maz, p.zabel,
robin.murphy, will, Frank Li
Some system's IOMMU stream(master) ID bits(such as 6bits) less than
pci_device_id (16bit). It needs add hardware configuration to enable
pci_device_id to stream ID convert.
https://lore.kernel.org/imx/20240622173849.GA1432357@bhelgaas/
This ways use pcie bus notifier (like apple pci controller), when new PCIe
device added, bus notifier will call register specific callback to handle
look up table (LUT) configuration.
https://lore.kernel.org/imx/20240429150842.GC1709920-robh@kernel.org/
which parse dt's 'msi-map' and 'iommu-map' property to static config LUT
table (qcom use this way). This way is rejected by DT maintainer Rob.
Above ways can resolve LUT take or stream id out of usage the problem. If
there are not enough stream id resource, not error return, EP hardware
still issue DMA to do transfer, which may transfer to wrong possition.
Add enable(disable)_device() hook for bridge can return error when not
enough resource, and PCI device can't enabled.
Basicallly this version can match Bjorn's requirement:
1: simple, because it is rare that there are no LUT resource.
2: EP driver probe failure when no LUT, but lspci can see such device.
[ 2.164415] nvme nvme0: pci function 0000:01:00.0
[ 2.169142] pci 0000:00:00.0: Error enabling bridge (-1), continuing
[ 2.175654] nvme 0000:01:00.0: probe with driver nvme failed with error -12
> lspci
0000:00:00.0 PCI bridge: Philips Semiconductors Device 0000
0000:01:00.0 Non-Volatile memory controller: Micron Technology Inc 2100AI NVMe SSD [Nitro] (rev 03)
To: Bjorn Helgaas <bhelgaas@google.com>
To: Richard Zhu <hongxing.zhu@nxp.com>
To: Lucas Stach <l.stach@pengutronix.de>
To: Lorenzo Pieralisi <lpieralisi@kernel.org>
To: Krzysztof Wilczyński <kw@linux.com>
To: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
To: Rob Herring <robh@kernel.org>
To: Shawn Guo <shawnguo@kernel.org>
To: Sascha Hauer <s.hauer@pengutronix.de>
To: Pengutronix Kernel Team <kernel@pengutronix.de>
To: Fabio Estevam <festevam@gmail.com>
Cc: linux-pci@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: imx@lists.linux.dev
Cc: Frank.li@nxp.com \
Cc: alyssa@rosenzweig.io \
Cc: bpf@vger.kernel.org \
Cc: broonie@kernel.org \
Cc: jgg@ziepe.ca \
Cc: joro@8bytes.org \
Cc: l.stach@pengutronix.de \
Cc: lgirdwood@gmail.com \
Cc: maz@kernel.org \
Cc: p.zabel@pengutronix.de \
Cc: robin.murphy@arm.com \
Cc: will@kernel.org \
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v2:
- see each patch
- Link to v1: https://lore.kernel.org/r/20240926-imx95_lut-v1-0-d0c62087dbab@nxp.com
---
Frank Li (2):
PCI: Add enable_device() and disable_device() callbacks for bridges
PCI: imx6: Add IOMMU and ITS MSI support for i.MX95
drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++-
drivers/pci/pci.c | 14 ++++
include/linux/pci.h | 2 +
3 files changed, 148 insertions(+), 1 deletion(-)
---
base-commit: 2849622e7b01d5aea1b060ba3955054798c1e0bb
change-id: 20240926-imx95_lut-1c68222e0944
Best regards,
---
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges 2024-09-30 19:42 [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Frank Li @ 2024-09-30 19:42 ` Frank Li 2024-10-02 22:46 ` Bjorn Helgaas 2024-10-03 10:30 ` Robin Murphy 2024-09-30 19:42 ` [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 Frank Li ` (2 subsequent siblings) 3 siblings, 2 replies; 12+ messages in thread From: Frank Li @ 2024-09-30 19:42 UTC (permalink / raw) To: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam Cc: linux-pci, linux-kernel, linux-arm-kernel, imx, Frank.li, alyssa, bpf, broonie, jgg, joro, l.stach, lgirdwood, maz, p.zabel, robin.murphy, will, Frank Li Some PCIe bridges require special handling when enabling or disabling PCIe devices. For example, on the i.MX95 platform, a lookup table must be configured to inform the hardware how to convert pci_device_id to stream (bus master) ID, which is used by the IOMMU and MSI controller to identify bus master device. Enablement will be failure when there is not enough lookup table resource. Avoid DMA write to wrong position. That is the reason why pci_fixup_enable can't work since not return value for fixup function. Signed-off-by: Frank Li <Frank.Li@nxp.com> --- Change from v1 to v2 - move enable(disable)device ops to pci_host_bridge --- drivers/pci/pci.c | 14 ++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7d85c04fbba2a..fcdeb12622568 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2056,6 +2056,7 @@ int __weak pcibios_enable_device(struct pci_dev *dev, int bars) static int do_pci_enable_device(struct pci_dev *dev, int bars) { int err; + struct pci_host_bridge *host_bridge; struct pci_dev *bridge; u16 cmd; u8 pin; @@ -2068,6 +2069,13 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) if (bridge) pcie_aspm_powersave_config_link(bridge); + host_bridge = pci_find_host_bridge(dev->bus); + if (host_bridge && host_bridge->enable_device) { + err = host_bridge->enable_device(host_bridge, dev); + if (err) + return err; + } + err = pcibios_enable_device(dev, bars); if (err < 0) return err; @@ -2262,12 +2270,18 @@ void pci_disable_enabled_device(struct pci_dev *dev) */ void pci_disable_device(struct pci_dev *dev) { + struct pci_host_bridge *host_bridge; + dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0, "disabling already-disabled device"); if (atomic_dec_return(&dev->enable_cnt) != 0) return; + host_bridge = pci_find_host_bridge(dev->bus); + if (host_bridge && host_bridge->disable_device) + host_bridge->disable_device(host_bridge, dev); + do_pci_disable_device(dev); dev->is_busmaster = 0; diff --git a/include/linux/pci.h b/include/linux/pci.h index 573b4c4c2be61..ac15b02e14ddd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -578,6 +578,8 @@ struct pci_host_bridge { u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ int (*map_irq)(const struct pci_dev *, u8, u8); void (*release_fn)(struct pci_host_bridge *); + int (*enable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); + void (*disable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); void *release_data; unsigned int ignore_reset_delay:1; /* For entire hierarchy */ unsigned int no_ext_tags:1; /* No Extended Tags */ -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges 2024-09-30 19:42 ` [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges Frank Li @ 2024-10-02 22:46 ` Bjorn Helgaas 2024-10-03 10:30 ` Robin Murphy 1 sibling, 0 replies; 12+ messages in thread From: Bjorn Helgaas @ 2024-10-02 22:46 UTC (permalink / raw) To: Frank Li Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, robin.murphy, will On Mon, Sep 30, 2024 at 03:42:21PM -0400, Frank Li wrote: > Some PCIe bridges require special handling when enabling or disabling > PCIe devices. For example, on the i.MX95 platform, a lookup table must be > configured to inform the hardware how to convert pci_device_id to stream > (bus master) ID, which is used by the IOMMU and MSI controller to identify > bus master device. It's important that this say "PCI *host bridge*" specifically to avoid confusion with PCI-to-PCI bridges. On the PCIe side, it would be better to use "Requester ID" than "pci_device_id" because I think that's the actual key for the lookup table. Possible commit log text, fix my misconceptions as needed: Some PCIe host bridges require special handling when enabling or disabling PCIe Endpoints. For example, the i.MX95 platform has a lookup table to map Requester IDs to StreamIDs, which are used by the SMMU and MSI controller to identify the source of DMA accesses. Without this mapping, DMA accesses may target unintended memory, which would corrupt memory or read the wrong data. Add a host bridge .enable_device() hook the imx6 driver can use to configure the Requester ID to StreamID mapping. The hardware table isn't big enough to map all possible Requester IDs, so this hook may fail if no table space is available. In that case, return failure from pci_enable_device(). It might make more sense to make pci_set_master() decline to enable bus mastering and return failure, but it currently doesn't have a way to return failure. > Enablement will be failure when there is not enough lookup table resource. > Avoid DMA write to wrong position. That is the reason why pci_fixup_enable > can't work since not return value for fixup function. > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > Change from v1 to v2 > - move enable(disable)device ops to pci_host_bridge > --- > drivers/pci/pci.c | 14 ++++++++++++++ > include/linux/pci.h | 2 ++ > 2 files changed, 16 insertions(+) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 7d85c04fbba2a..fcdeb12622568 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -2056,6 +2056,7 @@ int __weak pcibios_enable_device(struct pci_dev *dev, int bars) > static int do_pci_enable_device(struct pci_dev *dev, int bars) > { > int err; > + struct pci_host_bridge *host_bridge; > struct pci_dev *bridge; > u16 cmd; > u8 pin; > @@ -2068,6 +2069,13 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) > if (bridge) > pcie_aspm_powersave_config_link(bridge); > > + host_bridge = pci_find_host_bridge(dev->bus); > + if (host_bridge && host_bridge->enable_device) { > + err = host_bridge->enable_device(host_bridge, dev); > + if (err) > + return err; > + } > + > err = pcibios_enable_device(dev, bars); > if (err < 0) > return err; > @@ -2262,12 +2270,18 @@ void pci_disable_enabled_device(struct pci_dev *dev) > */ > void pci_disable_device(struct pci_dev *dev) > { > + struct pci_host_bridge *host_bridge; > + > dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0, > "disabling already-disabled device"); > > if (atomic_dec_return(&dev->enable_cnt) != 0) > return; > > + host_bridge = pci_find_host_bridge(dev->bus); > + if (host_bridge && host_bridge->disable_device) > + host_bridge->disable_device(host_bridge, dev); > + > do_pci_disable_device(dev); > > dev->is_busmaster = 0; > diff --git a/include/linux/pci.h b/include/linux/pci.h > index 573b4c4c2be61..ac15b02e14ddd 100644 > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -578,6 +578,8 @@ struct pci_host_bridge { > u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ > int (*map_irq)(const struct pci_dev *, u8, u8); > void (*release_fn)(struct pci_host_bridge *); > + int (*enable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); > + void (*disable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); > void *release_data; > unsigned int ignore_reset_delay:1; /* For entire hierarchy */ > unsigned int no_ext_tags:1; /* No Extended Tags */ > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges 2024-09-30 19:42 ` [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges Frank Li 2024-10-02 22:46 ` Bjorn Helgaas @ 2024-10-03 10:30 ` Robin Murphy 1 sibling, 0 replies; 12+ messages in thread From: Robin Murphy @ 2024-10-03 10:30 UTC (permalink / raw) To: Frank Li, Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam Cc: linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, will On 2024-09-30 8:42 pm, Frank Li wrote: > Some PCIe bridges require special handling when enabling or disabling > PCIe devices. For example, on the i.MX95 platform, a lookup table must be > configured to inform the hardware how to convert pci_device_id to stream > (bus master) ID, which is used by the IOMMU and MSI controller to identify > bus master device. > > Enablement will be failure when there is not enough lookup table resource. > Avoid DMA write to wrong position. That is the reason why pci_fixup_enable > can't work since not return value for fixup function. > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > Change from v1 to v2 > - move enable(disable)device ops to pci_host_bridge > --- > drivers/pci/pci.c | 14 ++++++++++++++ > include/linux/pci.h | 2 ++ > 2 files changed, 16 insertions(+) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 7d85c04fbba2a..fcdeb12622568 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -2056,6 +2056,7 @@ int __weak pcibios_enable_device(struct pci_dev *dev, int bars) > static int do_pci_enable_device(struct pci_dev *dev, int bars) > { > int err; > + struct pci_host_bridge *host_bridge; > struct pci_dev *bridge; > u16 cmd; > u8 pin; > @@ -2068,6 +2069,13 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) > if (bridge) > pcie_aspm_powersave_config_link(bridge); > > + host_bridge = pci_find_host_bridge(dev->bus); > + if (host_bridge && host_bridge->enable_device) { > + err = host_bridge->enable_device(host_bridge, dev); If the intent is that this call may allocate host bridge resources, what about the existing error returns below? Should those now have a cleanup path to avoid a potential resource leak from here? Thanks, Robin. > + if (err) > + return err; > + } > + > err = pcibios_enable_device(dev, bars); > if (err < 0) > return err; > @@ -2262,12 +2270,18 @@ void pci_disable_enabled_device(struct pci_dev *dev) > */ > void pci_disable_device(struct pci_dev *dev) > { > + struct pci_host_bridge *host_bridge; > + > dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0, > "disabling already-disabled device"); > > if (atomic_dec_return(&dev->enable_cnt) != 0) > return; > > + host_bridge = pci_find_host_bridge(dev->bus); > + if (host_bridge && host_bridge->disable_device) > + host_bridge->disable_device(host_bridge, dev); > + > do_pci_disable_device(dev); > > dev->is_busmaster = 0; > diff --git a/include/linux/pci.h b/include/linux/pci.h > index 573b4c4c2be61..ac15b02e14ddd 100644 > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -578,6 +578,8 @@ struct pci_host_bridge { > u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ > int (*map_irq)(const struct pci_dev *, u8, u8); > void (*release_fn)(struct pci_host_bridge *); > + int (*enable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); > + void (*disable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); > void *release_data; > unsigned int ignore_reset_delay:1; /* For entire hierarchy */ > unsigned int no_ext_tags:1; /* No Extended Tags */ > ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 2024-09-30 19:42 [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Frank Li 2024-09-30 19:42 ` [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges Frank Li @ 2024-09-30 19:42 ` Frank Li 2024-10-03 11:16 ` Robin Murphy 2024-10-02 22:24 ` [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Bjorn Helgaas 2024-10-03 5:15 ` Manivannan Sadhasivam 3 siblings, 1 reply; 12+ messages in thread From: Frank Li @ 2024-09-30 19:42 UTC (permalink / raw) To: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam Cc: linux-pci, linux-kernel, linux-arm-kernel, imx, Frank.li, alyssa, bpf, broonie, jgg, joro, l.stach, lgirdwood, maz, p.zabel, robin.murphy, will, Frank Li For the i.MX95, configuration of a LUT is necessary to convert Bus Device Function (BDF) to stream IDs, which are utilized by both IOMMU and ITS. This involves examining the msi-map and smmu-map to ensure consistent mapping of PCI BDF to the same stream IDs. Subsequently, LUT-related registers are configured. In the absence of an msi-map, the built-in MSI controller is utilized as a fallback. Additionally, register a PCI bus callback function enable_device() and disable_device() to config LUT when enable a new PCI device. Signed-off-by: Frank Li <Frank.Li@nxp.com> --- change from v1 to v2 - set callback to pci_host_bridge instead pci->ops. --- drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 94f3411352bf0..29186058ba256 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -55,6 +55,22 @@ #define IMX95_PE0_GEN_CTRL_3 0x1058 #define IMX95_PCIE_LTSSM_EN BIT(0) +#define IMX95_PE0_LUT_ACSCTRL 0x1008 +#define IMX95_PEO_LUT_RWA BIT(16) +#define IMX95_PE0_LUT_ENLOC GENMASK(4, 0) + +#define IMX95_PE0_LUT_DATA1 0x100c +#define IMX95_PE0_LUT_VLD BIT(31) +#define IMX95_PE0_LUT_DAC_ID GENMASK(10, 8) +#define IMX95_PE0_LUT_STREAM_ID GENMASK(5, 0) + +#define IMX95_PE0_LUT_DATA2 0x1010 +#define IMX95_PE0_LUT_REQID GENMASK(31, 16) +#define IMX95_PE0_LUT_MASK GENMASK(15, 0) + +#define IMX95_SID_MASK GENMASK(5, 0) +#define IMX95_MAX_LUT 32 + #define to_imx_pcie(x) dev_get_drvdata((x)->dev) enum imx_pcie_variants { @@ -82,6 +98,7 @@ enum imx_pcie_variants { #define IMX_PCIE_FLAG_HAS_PHY_RESET BIT(5) #define IMX_PCIE_FLAG_HAS_SERDES BIT(6) #define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7) +#define IMX_PCIE_FLAG_HAS_LUT BIT(8) #define imx_check_flag(pci, val) (pci->drvdata->flags & val) @@ -134,6 +151,7 @@ struct imx_pcie { struct device *pd_pcie_phy; struct phy *phy; const struct imx_pcie_drvdata *drvdata; + struct mutex lock; }; /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ @@ -925,6 +943,111 @@ static void imx_pcie_stop_link(struct dw_pcie *pci) imx_pcie_ltssm_disable(dev); } +static int imx_pcie_add_lut(struct imx_pcie *imx_pcie, u16 reqid, u8 sid) +{ + struct dw_pcie *pci = imx_pcie->pci; + struct device *dev = pci->dev; + u32 data1, data2; + int i; + + if (sid >= 64) { + dev_err(dev, "Invalid SID for index %d\n", sid); + return -EINVAL; + } + + guard(mutex)(&imx_pcie->lock); + + for (i = 0; i < IMX95_MAX_LUT; i++) { + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, IMX95_PEO_LUT_RWA | i); + + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, &data1); + if (data1 & IMX95_PE0_LUT_VLD) + continue; + + data1 = FIELD_PREP(IMX95_PE0_LUT_DAC_ID, 0); + data1 |= FIELD_PREP(IMX95_PE0_LUT_STREAM_ID, sid); + data1 |= IMX95_PE0_LUT_VLD; + + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, data1); + + data2 = 0xffff; + data2 |= FIELD_PREP(IMX95_PE0_LUT_REQID, reqid); + + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, data2); + + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); + + return 0; + } + + dev_err(dev, "All lut already used\n"); + return -EINVAL; +} + +static void imx_pcie_remove_lut(struct imx_pcie *imx_pcie, u16 reqid) +{ + u32 data2 = 0; + int i; + + guard(mutex)(&imx_pcie->lock); + + for (i = 0; i < IMX95_MAX_LUT; i++) { + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, IMX95_PEO_LUT_RWA | i); + + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, &data2); + if (FIELD_GET(IMX95_PE0_LUT_REQID, data2) == reqid) { + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, 0); + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, 0); + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); + } + } +} + +static int imx_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) +{ + u32 sid_i = 0, sid_m = 0, rid = pci_dev_id(pdev); + struct imx_pcie *imx_pcie; + struct device *dev; + int err; + + imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); + dev = imx_pcie->pci->dev; + + err = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask", NULL, &sid_i); + if (err) + return err; + + err = of_map_id(dev->of_node, rid, "msi-map", "msi-map-mask", NULL, &sid_m); + if (err) + return err; + + if (sid_i != rid && sid_m != rid) + if ((sid_i & IMX95_SID_MASK) != (sid_m & IMX95_SID_MASK)) { + dev_err(dev, "its and iommu stream id miss match, please check dts file\n"); + return -EINVAL; + } + + /* if iommu-map is not existed then use msi-map's stream id*/ + if (sid_i == rid) + sid_i = sid_m; + + sid_i &= IMX95_SID_MASK; + + if (sid_i != rid) + return imx_pcie_add_lut(imx_pcie, rid, sid_i); + + /* Use dwc built-in MSI controller */ + return 0; +} + +static void imx_pcie_disable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) +{ + struct imx_pcie *imx_pcie; + + imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); + imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev)); +} + static int imx_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -941,6 +1064,11 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp) } } + if (pp->bridge && imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) { + pp->bridge->enable_device = imx_pcie_enable_device; + pp->bridge->disable_device = imx_pcie_disable_device; + } + imx_pcie_assert_core_reset(imx_pcie); if (imx_pcie->drvdata->init_phy) @@ -1292,6 +1420,8 @@ static int imx_pcie_probe(struct platform_device *pdev) imx_pcie->pci = pci; imx_pcie->drvdata = of_device_get_match_data(dev); + mutex_init(&imx_pcie->lock); + /* Find the PHY if one is defined, only imx7d uses it */ np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0); if (np) { @@ -1587,7 +1717,8 @@ static const struct imx_pcie_drvdata drvdata[] = { }, [IMX95] = { .variant = IMX95, - .flags = IMX_PCIE_FLAG_HAS_SERDES, + .flags = IMX_PCIE_FLAG_HAS_SERDES | + IMX_PCIE_FLAG_HAS_LUT, .clk_names = imx8mq_clks, .clks_cnt = ARRAY_SIZE(imx8mq_clks), .ltssm_off = IMX95_PE0_GEN_CTRL_3, -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 2024-09-30 19:42 ` [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 Frank Li @ 2024-10-03 11:16 ` Robin Murphy 2024-10-03 21:12 ` Frank Li 0 siblings, 1 reply; 12+ messages in thread From: Robin Murphy @ 2024-10-03 11:16 UTC (permalink / raw) To: Frank Li, Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam Cc: linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, will On 2024-09-30 8:42 pm, Frank Li wrote: > For the i.MX95, configuration of a LUT is necessary to convert Bus Device > Function (BDF) to stream IDs, which are utilized by both IOMMU and ITS. > This involves examining the msi-map and smmu-map to ensure consistent > mapping of PCI BDF to the same stream IDs. Subsequently, LUT-related > registers are configured. In the absence of an msi-map, the built-in MSI > controller is utilized as a fallback. > > Additionally, register a PCI bus callback function enable_device() and > disable_device() to config LUT when enable a new PCI device. > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > change from v1 to v2 > - set callback to pci_host_bridge instead pci->ops. > --- > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > 1 file changed, 132 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c > index 94f3411352bf0..29186058ba256 100644 > --- a/drivers/pci/controller/dwc/pci-imx6.c > +++ b/drivers/pci/controller/dwc/pci-imx6.c > @@ -55,6 +55,22 @@ > #define IMX95_PE0_GEN_CTRL_3 0x1058 > #define IMX95_PCIE_LTSSM_EN BIT(0) > > +#define IMX95_PE0_LUT_ACSCTRL 0x1008 > +#define IMX95_PEO_LUT_RWA BIT(16) > +#define IMX95_PE0_LUT_ENLOC GENMASK(4, 0) > + > +#define IMX95_PE0_LUT_DATA1 0x100c > +#define IMX95_PE0_LUT_VLD BIT(31) > +#define IMX95_PE0_LUT_DAC_ID GENMASK(10, 8) > +#define IMX95_PE0_LUT_STREAM_ID GENMASK(5, 0) > + > +#define IMX95_PE0_LUT_DATA2 0x1010 > +#define IMX95_PE0_LUT_REQID GENMASK(31, 16) > +#define IMX95_PE0_LUT_MASK GENMASK(15, 0) > + > +#define IMX95_SID_MASK GENMASK(5, 0) > +#define IMX95_MAX_LUT 32 > + > #define to_imx_pcie(x) dev_get_drvdata((x)->dev) > > enum imx_pcie_variants { > @@ -82,6 +98,7 @@ enum imx_pcie_variants { > #define IMX_PCIE_FLAG_HAS_PHY_RESET BIT(5) > #define IMX_PCIE_FLAG_HAS_SERDES BIT(6) > #define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7) > +#define IMX_PCIE_FLAG_HAS_LUT BIT(8) > > #define imx_check_flag(pci, val) (pci->drvdata->flags & val) > > @@ -134,6 +151,7 @@ struct imx_pcie { > struct device *pd_pcie_phy; > struct phy *phy; > const struct imx_pcie_drvdata *drvdata; > + struct mutex lock; > }; > > /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ > @@ -925,6 +943,111 @@ static void imx_pcie_stop_link(struct dw_pcie *pci) > imx_pcie_ltssm_disable(dev); > } > > +static int imx_pcie_add_lut(struct imx_pcie *imx_pcie, u16 reqid, u8 sid) > +{ > + struct dw_pcie *pci = imx_pcie->pci; > + struct device *dev = pci->dev; > + u32 data1, data2; > + int i; > + > + if (sid >= 64) { > + dev_err(dev, "Invalid SID for index %d\n", sid); > + return -EINVAL; > + } > + > + guard(mutex)(&imx_pcie->lock); > + > + for (i = 0; i < IMX95_MAX_LUT; i++) { > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, IMX95_PEO_LUT_RWA | i); > + > + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, &data1); > + if (data1 & IMX95_PE0_LUT_VLD) > + continue; Maybe check if an existing entry already exists for the given RID? > + data1 = FIELD_PREP(IMX95_PE0_LUT_DAC_ID, 0); > + data1 |= FIELD_PREP(IMX95_PE0_LUT_STREAM_ID, sid); > + data1 |= IMX95_PE0_LUT_VLD; > + > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, data1); > + > + data2 = 0xffff; > + data2 |= FIELD_PREP(IMX95_PE0_LUT_REQID, reqid); > + > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, data2); > + > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); > + > + return 0; > + } > + > + dev_err(dev, "All lut already used\n"); > + return -EINVAL; > +} > + > +static void imx_pcie_remove_lut(struct imx_pcie *imx_pcie, u16 reqid) > +{ > + u32 data2 = 0; > + int i; > + > + guard(mutex)(&imx_pcie->lock); > + > + for (i = 0; i < IMX95_MAX_LUT; i++) { > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, IMX95_PEO_LUT_RWA | i); > + > + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, &data2); > + if (FIELD_GET(IMX95_PE0_LUT_REQID, data2) == reqid) { > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, 0); > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, 0); > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); ...plus then you could safely return early here. > + } > + } > +} > + > +static int imx_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) > +{ > + u32 sid_i = 0, sid_m = 0, rid = pci_dev_id(pdev); > + struct imx_pcie *imx_pcie; > + struct device *dev; > + int err; > + > + imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); > + dev = imx_pcie->pci->dev; > + > + err = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask", NULL, &sid_i); > + if (err) > + return err; > + > + err = of_map_id(dev->of_node, rid, "msi-map", "msi-map-mask", NULL, &sid_m); > + if (err) > + return err; > + > + if (sid_i != rid && sid_m != rid) Perhaps it is reasonable to assume that i.MX95 will never have SMMU/ITS mappings for low-numbered devices on bus 0, but in general this isn't very robust, and either way it's certainly not all that clear at first glance what assmuption is actually being made here. If it's significant whether a mapping actually exists or not for the given ID then you should really use the "target" argument of of_map_id() to determine that. > + if ((sid_i & IMX95_SID_MASK) != (sid_m & IMX95_SID_MASK)) { > + dev_err(dev, "its and iommu stream id miss match, please check dts file\n"); > + return -EINVAL; > + } > + > + /* if iommu-map is not existed then use msi-map's stream id*/ > + if (sid_i == rid) > + sid_i = sid_m; > + > + sid_i &= IMX95_SID_MASK; AFAICS this means that: a) the check in imx_pcie_add_lut() is useless, since if a mapping had an output ID larger than 63, then we've now just silently truncated the LUT entry to not match what the SMMU/ITS will still expect. b) if no mapping existed, then we're going to needlessly allocate a LUT entry anyway since the truncated RID now won't match the original. > + > + if (sid_i != rid) > + return imx_pcie_add_lut(imx_pcie, rid, sid_i); > + > + /* Use dwc built-in MSI controller */ This comment seems out of place - how does returning 0 from here vs. returning 0 from imx_pcie_add_lut() achieve that? I don't see any obvious way for the LUT programming to influence the IRQ subsystem here :/ Thanks, Robin. > + return 0; > +} > + > +static void imx_pcie_disable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) > +{ > + struct imx_pcie *imx_pcie; > + > + imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); > + imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev)); > +} > + > static int imx_pcie_host_init(struct dw_pcie_rp *pp) > { > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > @@ -941,6 +1064,11 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp) > } > } > > + if (pp->bridge && imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) { > + pp->bridge->enable_device = imx_pcie_enable_device; > + pp->bridge->disable_device = imx_pcie_disable_device; > + } > + > imx_pcie_assert_core_reset(imx_pcie); > > if (imx_pcie->drvdata->init_phy) > @@ -1292,6 +1420,8 @@ static int imx_pcie_probe(struct platform_device *pdev) > imx_pcie->pci = pci; > imx_pcie->drvdata = of_device_get_match_data(dev); > > + mutex_init(&imx_pcie->lock); > + > /* Find the PHY if one is defined, only imx7d uses it */ > np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0); > if (np) { > @@ -1587,7 +1717,8 @@ static const struct imx_pcie_drvdata drvdata[] = { > }, > [IMX95] = { > .variant = IMX95, > - .flags = IMX_PCIE_FLAG_HAS_SERDES, > + .flags = IMX_PCIE_FLAG_HAS_SERDES | > + IMX_PCIE_FLAG_HAS_LUT, > .clk_names = imx8mq_clks, > .clks_cnt = ARRAY_SIZE(imx8mq_clks), > .ltssm_off = IMX95_PE0_GEN_CTRL_3, > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 2024-10-03 11:16 ` Robin Murphy @ 2024-10-03 21:12 ` Frank Li 0 siblings, 0 replies; 12+ messages in thread From: Frank Li @ 2024-10-03 21:12 UTC (permalink / raw) To: Robin Murphy Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, N Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, will On Thu, Oct 03, 2024 at 12:16:42PM +0100, Robin Murphy wrote: > On 2024-09-30 8:42 pm, Frank Li wrote: > > For the i.MX95, configuration of a LUT is necessary to convert Bus Device > > Function (BDF) to stream IDs, which are utilized by both IOMMU and ITS. > > This involves examining the msi-map and smmu-map to ensure consistent > > mapping of PCI BDF to the same stream IDs. Subsequently, LUT-related > > registers are configured. In the absence of an msi-map, the built-in MSI > > controller is utilized as a fallback. > > > > Additionally, register a PCI bus callback function enable_device() and > > disable_device() to config LUT when enable a new PCI device. > > > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > > --- > > change from v1 to v2 > > - set callback to pci_host_bridge instead pci->ops. > > --- > > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > > 1 file changed, 132 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c > > index 94f3411352bf0..29186058ba256 100644 > > --- a/drivers/pci/controller/dwc/pci-imx6.c > > +++ b/drivers/pci/controller/dwc/pci-imx6.c > > @@ -55,6 +55,22 @@ > > #define IMX95_PE0_GEN_CTRL_3 0x1058 > > #define IMX95_PCIE_LTSSM_EN BIT(0) > > +#define IMX95_PE0_LUT_ACSCTRL 0x1008 > > +#define IMX95_PEO_LUT_RWA BIT(16) > > +#define IMX95_PE0_LUT_ENLOC GENMASK(4, 0) > > + > > +#define IMX95_PE0_LUT_DATA1 0x100c > > +#define IMX95_PE0_LUT_VLD BIT(31) > > +#define IMX95_PE0_LUT_DAC_ID GENMASK(10, 8) > > +#define IMX95_PE0_LUT_STREAM_ID GENMASK(5, 0) > > + > > +#define IMX95_PE0_LUT_DATA2 0x1010 > > +#define IMX95_PE0_LUT_REQID GENMASK(31, 16) > > +#define IMX95_PE0_LUT_MASK GENMASK(15, 0) > > + > > +#define IMX95_SID_MASK GENMASK(5, 0) > > +#define IMX95_MAX_LUT 32 > > + > > #define to_imx_pcie(x) dev_get_drvdata((x)->dev) > > enum imx_pcie_variants { > > @@ -82,6 +98,7 @@ enum imx_pcie_variants { > > #define IMX_PCIE_FLAG_HAS_PHY_RESET BIT(5) > > #define IMX_PCIE_FLAG_HAS_SERDES BIT(6) > > #define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7) > > +#define IMX_PCIE_FLAG_HAS_LUT BIT(8) > > #define imx_check_flag(pci, val) (pci->drvdata->flags & val) > > @@ -134,6 +151,7 @@ struct imx_pcie { > > struct device *pd_pcie_phy; > > struct phy *phy; > > const struct imx_pcie_drvdata *drvdata; > > + struct mutex lock; > > }; > > /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ > > @@ -925,6 +943,111 @@ static void imx_pcie_stop_link(struct dw_pcie *pci) > > imx_pcie_ltssm_disable(dev); > > } > > +static int imx_pcie_add_lut(struct imx_pcie *imx_pcie, u16 reqid, u8 sid) > > +{ > > + struct dw_pcie *pci = imx_pcie->pci; > > + struct device *dev = pci->dev; > > + u32 data1, data2; > > + int i; > > + > > + if (sid >= 64) { > > + dev_err(dev, "Invalid SID for index %d\n", sid); > > + return -EINVAL; > > + } > > + > > + guard(mutex)(&imx_pcie->lock); > > + > > + for (i = 0; i < IMX95_MAX_LUT; i++) { > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, IMX95_PEO_LUT_RWA | i); > > + > > + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, &data1); > > + if (data1 & IMX95_PE0_LUT_VLD) > > + continue; > > Maybe check if an existing entry already exists for the given RID? > > > + data1 = FIELD_PREP(IMX95_PE0_LUT_DAC_ID, 0); > > + data1 |= FIELD_PREP(IMX95_PE0_LUT_STREAM_ID, sid); > > + data1 |= IMX95_PE0_LUT_VLD; > > + > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, data1); > > + > > + data2 = 0xffff; > > + data2 |= FIELD_PREP(IMX95_PE0_LUT_REQID, reqid); > > + > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, data2); > > + > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); > > + > > + return 0; > > + } > > + > > + dev_err(dev, "All lut already used\n"); > > + return -EINVAL; > > +} > > + > > +static void imx_pcie_remove_lut(struct imx_pcie *imx_pcie, u16 reqid) > > +{ > > + u32 data2 = 0; > > + int i; > > + > > + guard(mutex)(&imx_pcie->lock); > > + > > + for (i = 0; i < IMX95_MAX_LUT; i++) { > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, IMX95_PEO_LUT_RWA | i); > > + > > + regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, &data2); > > + if (FIELD_GET(IMX95_PE0_LUT_REQID, data2) == reqid) { > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, 0); > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, 0); > > + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); > > ...plus then you could safely return early here. > > > + } > > + } > > +} > > + > > +static int imx_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) > > +{ > > + u32 sid_i = 0, sid_m = 0, rid = pci_dev_id(pdev); > > + struct imx_pcie *imx_pcie; > > + struct device *dev; > > + int err; > > + > > + imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); > > + dev = imx_pcie->pci->dev; > > + > > + err = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask", NULL, &sid_i); > > + if (err) > > + return err; > > + > > + err = of_map_id(dev->of_node, rid, "msi-map", "msi-map-mask", NULL, &sid_m); > > + if (err) > > + return err; > > + > > + if (sid_i != rid && sid_m != rid) > > Perhaps it is reasonable to assume that i.MX95 will never have SMMU/ITS > mappings for low-numbered devices on bus 0, but in general this isn't very > robust, and either way it's certainly not all that clear at first glance > what assmuption is actually being made here. If it's significant whether a > mapping actually exists or not for the given ID then you should really use > the "target" argument of of_map_id() to determine that. let me do more research on this. The key part is patch 1. Frank > > > + if ((sid_i & IMX95_SID_MASK) != (sid_m & IMX95_SID_MASK)) { > > + dev_err(dev, "its and iommu stream id miss match, please check dts file\n"); > > + return -EINVAL; > > + } > > + > > + /* if iommu-map is not existed then use msi-map's stream id*/ > > + if (sid_i == rid) > > + sid_i = sid_m; > > + > > + sid_i &= IMX95_SID_MASK; > > AFAICS this means that: > a) the check in imx_pcie_add_lut() is useless, since if a mapping had an > output ID larger than 63, then we've now just silently truncated the LUT > entry to not match what the SMMU/ITS will still expect. > b) if no mapping existed, then we're going to needlessly allocate a LUT > entry anyway since the truncated RID now won't match the original. You are right. It is my mistake. > > > + > > + if (sid_i != rid) > > + return imx_pcie_add_lut(imx_pcie, rid, sid_i); > > + > > + /* Use dwc built-in MSI controller */ > > This comment seems out of place - how does returning 0 from here vs. > returning 0 from imx_pcie_add_lut() achieve that? I don't see any obvious > way for the LUT programming to influence the IRQ subsystem here :/ If msi-map is not existed. sid_i will equal to rid. imx_pcie_add_lut() will be skipped. PCI controller still fallback to the dwc built-in's MSI controller. msi-map iommu-map Y Y ITS + SMMU, require the same sid Y N ITS N Y DWC MSI Ctrl + SMMU N N DWC MSI Ctrl. (current upstream state) Return 0 here, it is N-N case. > > Thanks, > Robin. > > > + return 0; > > +} > > + > > +static void imx_pcie_disable_device(struct pci_host_bridge *bridge, struct pci_dev *pdev) > > +{ > > + struct imx_pcie *imx_pcie; > > + > > + imx_pcie = to_imx_pcie(to_dw_pcie_from_pp(bridge->sysdata)); > > + imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev)); > > +} > > + > > static int imx_pcie_host_init(struct dw_pcie_rp *pp) > > { > > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > > @@ -941,6 +1064,11 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp) > > } > > } > > + if (pp->bridge && imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) { > > + pp->bridge->enable_device = imx_pcie_enable_device; > > + pp->bridge->disable_device = imx_pcie_disable_device; > > + } > > + > > imx_pcie_assert_core_reset(imx_pcie); > > if (imx_pcie->drvdata->init_phy) > > @@ -1292,6 +1420,8 @@ static int imx_pcie_probe(struct platform_device *pdev) > > imx_pcie->pci = pci; > > imx_pcie->drvdata = of_device_get_match_data(dev); > > + mutex_init(&imx_pcie->lock); > > + > > /* Find the PHY if one is defined, only imx7d uses it */ > > np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0); > > if (np) { > > @@ -1587,7 +1717,8 @@ static const struct imx_pcie_drvdata drvdata[] = { > > }, > > [IMX95] = { > > .variant = IMX95, > > - .flags = IMX_PCIE_FLAG_HAS_SERDES, > > + .flags = IMX_PCIE_FLAG_HAS_SERDES | > > + IMX_PCIE_FLAG_HAS_LUT, > > .clk_names = imx8mq_clks, > > .clks_cnt = ARRAY_SIZE(imx8mq_clks), > > .ltssm_off = IMX95_PE0_GEN_CTRL_3, > > > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge 2024-09-30 19:42 [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Frank Li 2024-09-30 19:42 ` [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges Frank Li 2024-09-30 19:42 ` [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 Frank Li @ 2024-10-02 22:24 ` Bjorn Helgaas 2024-10-03 5:15 ` Manivannan Sadhasivam 3 siblings, 0 replies; 12+ messages in thread From: Bjorn Helgaas @ 2024-10-02 22:24 UTC (permalink / raw) To: Frank Li Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, robin.murphy, will On Mon, Sep 30, 2024 at 03:42:20PM -0400, Frank Li wrote: > Some system's IOMMU stream(master) ID bits(such as 6bits) less than > pci_device_id (16bit). It needs add hardware configuration to enable > pci_device_id to stream ID convert. > > https://lore.kernel.org/imx/20240622173849.GA1432357@bhelgaas/ > This ways use pcie bus notifier (like apple pci controller), when new PCIe > device added, bus notifier will call register specific callback to handle > look up table (LUT) configuration. > > https://lore.kernel.org/imx/20240429150842.GC1709920-robh@kernel.org/ > which parse dt's 'msi-map' and 'iommu-map' property to static config LUT > table (qcom use this way). This way is rejected by DT maintainer Rob. > > Above ways can resolve LUT take or stream id out of usage the problem. If > there are not enough stream id resource, not error return, EP hardware > still issue DMA to do transfer, which may transfer to wrong possition. > > Add enable(disable)_device() hook for bridge can return error when not > enough resource, and PCI device can't enabled. > > Basicallly this version can match Bjorn's requirement: > 1: simple, because it is rare that there are no LUT resource. > 2: EP driver probe failure when no LUT, but lspci can see such device. > > [ 2.164415] nvme nvme0: pci function 0000:01:00.0 > [ 2.169142] pci 0000:00:00.0: Error enabling bridge (-1), continuing > [ 2.175654] nvme 0000:01:00.0: probe with driver nvme failed with error -12 > > > lspci > 0000:00:00.0 PCI bridge: Philips Semiconductors Device 0000 > 0000:01:00.0 Non-Volatile memory controller: Micron Technology Inc 2100AI NVMe SSD [Nitro] (rev 03) > > To: Bjorn Helgaas <bhelgaas@google.com> > To: Richard Zhu <hongxing.zhu@nxp.com> > To: Lucas Stach <l.stach@pengutronix.de> > To: Lorenzo Pieralisi <lpieralisi@kernel.org> > To: Krzysztof Wilczyński <kw@linux.com> > To: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > To: Rob Herring <robh@kernel.org> > To: Shawn Guo <shawnguo@kernel.org> > To: Sascha Hauer <s.hauer@pengutronix.de> > To: Pengutronix Kernel Team <kernel@pengutronix.de> > To: Fabio Estevam <festevam@gmail.com> > Cc: linux-pci@vger.kernel.org > Cc: linux-kernel@vger.kernel.org > Cc: linux-arm-kernel@lists.infradead.org > Cc: imx@lists.linux.dev > Cc: Frank.li@nxp.com \ > Cc: alyssa@rosenzweig.io \ > Cc: bpf@vger.kernel.org \ > Cc: broonie@kernel.org \ > Cc: jgg@ziepe.ca \ > Cc: joro@8bytes.org \ > Cc: l.stach@pengutronix.de \ > Cc: lgirdwood@gmail.com \ > Cc: maz@kernel.org \ > Cc: p.zabel@pengutronix.de \ > Cc: robin.murphy@arm.com \ > Cc: will@kernel.org \ > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > Changes in v2: > - see each patch > - Link to v1: https://lore.kernel.org/r/20240926-imx95_lut-v1-0-d0c62087dbab@nxp.com > > --- > Frank Li (2): > PCI: Add enable_device() and disable_device() callbacks for bridges > PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 > > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > drivers/pci/pci.c | 14 ++++ > include/linux/pci.h | 2 + > 3 files changed, 148 insertions(+), 1 deletion(-) > --- > base-commit: 2849622e7b01d5aea1b060ba3955054798c1e0bb > change-id: 20240926-imx95_lut-1c68222e0944 Not sure what this applies to; it doesn't apply cleanly to v6.13-rc1 (the pci/main branch). ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge 2024-09-30 19:42 [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Frank Li ` (2 preceding siblings ...) 2024-10-02 22:24 ` [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Bjorn Helgaas @ 2024-10-03 5:15 ` Manivannan Sadhasivam 2024-10-03 19:18 ` Frank Li 3 siblings, 1 reply; 12+ messages in thread From: Manivannan Sadhasivam @ 2024-10-03 5:15 UTC (permalink / raw) To: Frank Li Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, robin.murphy, will On Mon, Sep 30, 2024 at 03:42:20PM -0400, Frank Li wrote: > Some system's IOMMU stream(master) ID bits(such as 6bits) less than > pci_device_id (16bit). It needs add hardware configuration to enable > pci_device_id to stream ID convert. > > https://lore.kernel.org/imx/20240622173849.GA1432357@bhelgaas/ > This ways use pcie bus notifier (like apple pci controller), when new PCIe > device added, bus notifier will call register specific callback to handle > look up table (LUT) configuration. > > https://lore.kernel.org/imx/20240429150842.GC1709920-robh@kernel.org/ > which parse dt's 'msi-map' and 'iommu-map' property to static config LUT > table (qcom use this way). This way is rejected by DT maintainer Rob. > What is the issue in doing this during the probe() stage? It looks like you are working with the static info in the devicetree, which is already available during the controller probe(). > Above ways can resolve LUT take or stream id out of usage the problem. If > there are not enough stream id resource, not error return, EP hardware > still issue DMA to do transfer, which may transfer to wrong possition. > > Add enable(disable)_device() hook for bridge can return error when not > enough resource, and PCI device can't enabled. > {enable/disable}_device() doesn't convey the fact you are mapping BDF to SID in the hardware. Maybe something like, {map/unmap}_bdf2sid() or similar would make sense. - Mani > Basicallly this version can match Bjorn's requirement: > 1: simple, because it is rare that there are no LUT resource. > 2: EP driver probe failure when no LUT, but lspci can see such device. > > [ 2.164415] nvme nvme0: pci function 0000:01:00.0 > [ 2.169142] pci 0000:00:00.0: Error enabling bridge (-1), continuing > [ 2.175654] nvme 0000:01:00.0: probe with driver nvme failed with error -12 > > > lspci > 0000:00:00.0 PCI bridge: Philips Semiconductors Device 0000 > 0000:01:00.0 Non-Volatile memory controller: Micron Technology Inc 2100AI NVMe SSD [Nitro] (rev 03) > > To: Bjorn Helgaas <bhelgaas@google.com> > To: Richard Zhu <hongxing.zhu@nxp.com> > To: Lucas Stach <l.stach@pengutronix.de> > To: Lorenzo Pieralisi <lpieralisi@kernel.org> > To: Krzysztof Wilczyński <kw@linux.com> > To: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > To: Rob Herring <robh@kernel.org> > To: Shawn Guo <shawnguo@kernel.org> > To: Sascha Hauer <s.hauer@pengutronix.de> > To: Pengutronix Kernel Team <kernel@pengutronix.de> > To: Fabio Estevam <festevam@gmail.com> > Cc: linux-pci@vger.kernel.org > Cc: linux-kernel@vger.kernel.org > Cc: linux-arm-kernel@lists.infradead.org > Cc: imx@lists.linux.dev > Cc: Frank.li@nxp.com \ > Cc: alyssa@rosenzweig.io \ > Cc: bpf@vger.kernel.org \ > Cc: broonie@kernel.org \ > Cc: jgg@ziepe.ca \ > Cc: joro@8bytes.org \ > Cc: l.stach@pengutronix.de \ > Cc: lgirdwood@gmail.com \ > Cc: maz@kernel.org \ > Cc: p.zabel@pengutronix.de \ > Cc: robin.murphy@arm.com \ > Cc: will@kernel.org \ > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > Changes in v2: > - see each patch > - Link to v1: https://lore.kernel.org/r/20240926-imx95_lut-v1-0-d0c62087dbab@nxp.com > > --- > Frank Li (2): > PCI: Add enable_device() and disable_device() callbacks for bridges > PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 > > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > drivers/pci/pci.c | 14 ++++ > include/linux/pci.h | 2 + > 3 files changed, 148 insertions(+), 1 deletion(-) > --- > base-commit: 2849622e7b01d5aea1b060ba3955054798c1e0bb > change-id: 20240926-imx95_lut-1c68222e0944 > > Best regards, > --- > Frank Li <Frank.Li@nxp.com> > > -- மணிவண்ணன் சதாசிவம் ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge 2024-10-03 5:15 ` Manivannan Sadhasivam @ 2024-10-03 19:18 ` Frank Li 2024-10-06 17:50 ` Manivannan Sadhasivam 0 siblings, 1 reply; 12+ messages in thread From: Frank Li @ 2024-10-03 19:18 UTC (permalink / raw) To: Manivannan Sadhasivam Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, robin.murphy, will On Thu, Oct 03, 2024 at 10:45:28AM +0530, Manivannan Sadhasivam wrote: > On Mon, Sep 30, 2024 at 03:42:20PM -0400, Frank Li wrote: > > Some system's IOMMU stream(master) ID bits(such as 6bits) less than > > pci_device_id (16bit). It needs add hardware configuration to enable > > pci_device_id to stream ID convert. > > > > https://lore.kernel.org/imx/20240622173849.GA1432357@bhelgaas/ > > This ways use pcie bus notifier (like apple pci controller), when new PCIe > > device added, bus notifier will call register specific callback to handle > > look up table (LUT) configuration. > > > > https://lore.kernel.org/imx/20240429150842.GC1709920-robh@kernel.org/ > > which parse dt's 'msi-map' and 'iommu-map' property to static config LUT > > table (qcom use this way). This way is rejected by DT maintainer Rob. > > > > What is the issue in doing this during the probe() stage? It looks like you are > working with the static info in the devicetree, which is already available > during the controller probe(). There are problems. One: It is not good to manually parser this property in pci host bridge drivers. Two: of_map default is bypass map. For example: if in dts only 2 sid, 0xA and 0xB. If try to enable 3rd function RID(103), there are no error report. of_map will return RID 103 as stream ID. DMA will write to wrong possition possibly. https://elixir.bootlin.com/linux/v6.12-rc1/source/drivers/of/base.c#L2070 Three: LUT resource is limited, if DT provide 16 entry, but LUT have only 8 items, if more device enable, not LUT avaible and can't return error. of course, it may fix dts, but It'd better that driver can handle error properly when meet wrong dtb file. > > > Above ways can resolve LUT take or stream id out of usage the problem. If > > there are not enough stream id resource, not error return, EP hardware > > still issue DMA to do transfer, which may transfer to wrong possition. > > > > Add enable(disable)_device() hook for bridge can return error when not > > enough resource, and PCI device can't enabled. > > > > {enable/disable}_device() doesn't convey the fact you are mapping BDF to SID in > the hardware. Maybe something like, {map/unmap}_bdf2sid() or similar would make > sense. It is called in PCI common code do_pci_enable_device(), hook functin name should be similar with caller. {map/unmap}_bdf2sid() is just implementation in dwc. stream id is only ARM platform concept. May other host bridge do difference thing at enable/disable_device(). So I am still perfer use {enable/disable}_device(). Frank > > - Mani > > > Basicallly this version can match Bjorn's requirement: > > 1: simple, because it is rare that there are no LUT resource. > > 2: EP driver probe failure when no LUT, but lspci can see such device. > > > > [ 2.164415] nvme nvme0: pci function 0000:01:00.0 > > [ 2.169142] pci 0000:00:00.0: Error enabling bridge (-1), continuing > > [ 2.175654] nvme 0000:01:00.0: probe with driver nvme failed with error -12 > > > > > lspci > > 0000:00:00.0 PCI bridge: Philips Semiconductors Device 0000 > > 0000:01:00.0 Non-Volatile memory controller: Micron Technology Inc 2100AI NVMe SSD [Nitro] (rev 03) > > > > To: Bjorn Helgaas <bhelgaas@google.com> > > To: Richard Zhu <hongxing.zhu@nxp.com> > > To: Lucas Stach <l.stach@pengutronix.de> > > To: Lorenzo Pieralisi <lpieralisi@kernel.org> > > To: Krzysztof Wilczyński <kw@linux.com> > > To: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > > To: Rob Herring <robh@kernel.org> > > To: Shawn Guo <shawnguo@kernel.org> > > To: Sascha Hauer <s.hauer@pengutronix.de> > > To: Pengutronix Kernel Team <kernel@pengutronix.de> > > To: Fabio Estevam <festevam@gmail.com> > > Cc: linux-pci@vger.kernel.org > > Cc: linux-kernel@vger.kernel.org > > Cc: linux-arm-kernel@lists.infradead.org > > Cc: imx@lists.linux.dev > > Cc: Frank.li@nxp.com \ > > Cc: alyssa@rosenzweig.io \ > > Cc: bpf@vger.kernel.org \ > > Cc: broonie@kernel.org \ > > Cc: jgg@ziepe.ca \ > > Cc: joro@8bytes.org \ > > Cc: l.stach@pengutronix.de \ > > Cc: lgirdwood@gmail.com \ > > Cc: maz@kernel.org \ > > Cc: p.zabel@pengutronix.de \ > > Cc: robin.murphy@arm.com \ > > Cc: will@kernel.org \ > > > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > > --- > > Changes in v2: > > - see each patch > > - Link to v1: https://lore.kernel.org/r/20240926-imx95_lut-v1-0-d0c62087dbab@nxp.com > > > > --- > > Frank Li (2): > > PCI: Add enable_device() and disable_device() callbacks for bridges > > PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 > > > > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > > drivers/pci/pci.c | 14 ++++ > > include/linux/pci.h | 2 + > > 3 files changed, 148 insertions(+), 1 deletion(-) > > --- > > base-commit: 2849622e7b01d5aea1b060ba3955054798c1e0bb > > change-id: 20240926-imx95_lut-1c68222e0944 > > > > Best regards, > > --- > > Frank Li <Frank.Li@nxp.com> > > > > > > -- > மணிவண்ணன் சதாசிவம் ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge 2024-10-03 19:18 ` Frank Li @ 2024-10-06 17:50 ` Manivannan Sadhasivam 2024-10-07 15:19 ` Frank Li 0 siblings, 1 reply; 12+ messages in thread From: Manivannan Sadhasivam @ 2024-10-06 17:50 UTC (permalink / raw) To: Frank Li Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, robin.murphy, will On Thu, Oct 03, 2024 at 03:18:12PM -0400, Frank Li wrote: > On Thu, Oct 03, 2024 at 10:45:28AM +0530, Manivannan Sadhasivam wrote: > > On Mon, Sep 30, 2024 at 03:42:20PM -0400, Frank Li wrote: > > > Some system's IOMMU stream(master) ID bits(such as 6bits) less than > > > pci_device_id (16bit). It needs add hardware configuration to enable > > > pci_device_id to stream ID convert. > > > > > > https://lore.kernel.org/imx/20240622173849.GA1432357@bhelgaas/ > > > This ways use pcie bus notifier (like apple pci controller), when new PCIe > > > device added, bus notifier will call register specific callback to handle > > > look up table (LUT) configuration. > > > > > > https://lore.kernel.org/imx/20240429150842.GC1709920-robh@kernel.org/ > > > which parse dt's 'msi-map' and 'iommu-map' property to static config LUT > > > table (qcom use this way). This way is rejected by DT maintainer Rob. > > > > > > > What is the issue in doing this during the probe() stage? It looks like you are > > working with the static info in the devicetree, which is already available > > during the controller probe(). > > There are problems. > One: It is not good to manually parser this property in pci host bridge > drivers. > Why? I see the comment from Rob saying that the host bridge driver should not parse iommu* properties, but this series is essentially doing the same just in a different place. > Two: of_map default is bypass map. For example: if in dts only 2 sid, 0xA > and 0xB. If try to enable 3rd function RID(103), there are no error report. > of_map will return RID 103 as stream ID. DMA will write to wrong > possition possibly. > Well, you can use iommu-map-mask to allow all devices under a bus to share the same SID. It will allow you to work with the LUT limitation. But the downside is that, there would be no isolation between devices under the same bus. > https://elixir.bootlin.com/linux/v6.12-rc1/source/drivers/of/base.c#L2070 > > Three: LUT resource is limited, if DT provide 16 entry, but LUT have only 8 > items, if more device enable, not LUT avaible and can't return error. of > course, it may fix dts, but It'd better that driver can handle error > properly when meet wrong dtb file. > Drivers can trust the DT, unless there are evidence of broken DT available in upstream or got fixed. If you really want to validate DT, use dt-bindings. - Mani > > > > > Above ways can resolve LUT take or stream id out of usage the problem. If > > > there are not enough stream id resource, not error return, EP hardware > > > still issue DMA to do transfer, which may transfer to wrong possition. > > > > > > Add enable(disable)_device() hook for bridge can return error when not > > > enough resource, and PCI device can't enabled. > > > > > > > {enable/disable}_device() doesn't convey the fact you are mapping BDF to SID in > > the hardware. Maybe something like, {map/unmap}_bdf2sid() or similar would make > > sense. > > It is called in PCI common code do_pci_enable_device(), hook functin name > should be similar with caller. {map/unmap}_bdf2sid() is just implementation > in dwc. > > stream id is only ARM platform concept. > > May other host bridge do difference thing at enable/disable_device(). > > So I am still perfer use {enable/disable}_device(). > > > Frank > > > > > - Mani > > > > > Basicallly this version can match Bjorn's requirement: > > > 1: simple, because it is rare that there are no LUT resource. > > > 2: EP driver probe failure when no LUT, but lspci can see such device. > > > > > > [ 2.164415] nvme nvme0: pci function 0000:01:00.0 > > > [ 2.169142] pci 0000:00:00.0: Error enabling bridge (-1), continuing > > > [ 2.175654] nvme 0000:01:00.0: probe with driver nvme failed with error -12 > > > > > > > lspci > > > 0000:00:00.0 PCI bridge: Philips Semiconductors Device 0000 > > > 0000:01:00.0 Non-Volatile memory controller: Micron Technology Inc 2100AI NVMe SSD [Nitro] (rev 03) > > > > > > To: Bjorn Helgaas <bhelgaas@google.com> > > > To: Richard Zhu <hongxing.zhu@nxp.com> > > > To: Lucas Stach <l.stach@pengutronix.de> > > > To: Lorenzo Pieralisi <lpieralisi@kernel.org> > > > To: Krzysztof Wilczyński <kw@linux.com> > > > To: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > > > To: Rob Herring <robh@kernel.org> > > > To: Shawn Guo <shawnguo@kernel.org> > > > To: Sascha Hauer <s.hauer@pengutronix.de> > > > To: Pengutronix Kernel Team <kernel@pengutronix.de> > > > To: Fabio Estevam <festevam@gmail.com> > > > Cc: linux-pci@vger.kernel.org > > > Cc: linux-kernel@vger.kernel.org > > > Cc: linux-arm-kernel@lists.infradead.org > > > Cc: imx@lists.linux.dev > > > Cc: Frank.li@nxp.com \ > > > Cc: alyssa@rosenzweig.io \ > > > Cc: bpf@vger.kernel.org \ > > > Cc: broonie@kernel.org \ > > > Cc: jgg@ziepe.ca \ > > > Cc: joro@8bytes.org \ > > > Cc: l.stach@pengutronix.de \ > > > Cc: lgirdwood@gmail.com \ > > > Cc: maz@kernel.org \ > > > Cc: p.zabel@pengutronix.de \ > > > Cc: robin.murphy@arm.com \ > > > Cc: will@kernel.org \ > > > > > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > > > --- > > > Changes in v2: > > > - see each patch > > > - Link to v1: https://lore.kernel.org/r/20240926-imx95_lut-v1-0-d0c62087dbab@nxp.com > > > > > > --- > > > Frank Li (2): > > > PCI: Add enable_device() and disable_device() callbacks for bridges > > > PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 > > > > > > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > > > drivers/pci/pci.c | 14 ++++ > > > include/linux/pci.h | 2 + > > > 3 files changed, 148 insertions(+), 1 deletion(-) > > > --- > > > base-commit: 2849622e7b01d5aea1b060ba3955054798c1e0bb > > > change-id: 20240926-imx95_lut-1c68222e0944 > > > > > > Best regards, > > > --- > > > Frank Li <Frank.Li@nxp.com> > > > > > > > > > > -- > > மணிவண்ணன் சதாசிவம் -- மணிவண்ணன் சதாசிவம் ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge 2024-10-06 17:50 ` Manivannan Sadhasivam @ 2024-10-07 15:19 ` Frank Li 0 siblings, 0 replies; 12+ messages in thread From: Frank Li @ 2024-10-07 15:19 UTC (permalink / raw) To: Manivannan Sadhasivam Cc: Bjorn Helgaas, Richard Zhu, Lucas Stach, Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-pci, linux-kernel, linux-arm-kernel, imx, alyssa, bpf, broonie, jgg, joro, lgirdwood, maz, p.zabel, robin.murphy, will On Sun, Oct 06, 2024 at 11:20:47PM +0530, Manivannan Sadhasivam wrote: > On Thu, Oct 03, 2024 at 03:18:12PM -0400, Frank Li wrote: > > On Thu, Oct 03, 2024 at 10:45:28AM +0530, Manivannan Sadhasivam wrote: > > > On Mon, Sep 30, 2024 at 03:42:20PM -0400, Frank Li wrote: > > > > Some system's IOMMU stream(master) ID bits(such as 6bits) less than > > > > pci_device_id (16bit). It needs add hardware configuration to enable > > > > pci_device_id to stream ID convert. > > > > > > > > https://lore.kernel.org/imx/20240622173849.GA1432357@bhelgaas/ > > > > This ways use pcie bus notifier (like apple pci controller), when new PCIe > > > > device added, bus notifier will call register specific callback to handle > > > > look up table (LUT) configuration. > > > > > > > > https://lore.kernel.org/imx/20240429150842.GC1709920-robh@kernel.org/ > > > > which parse dt's 'msi-map' and 'iommu-map' property to static config LUT > > > > table (qcom use this way). This way is rejected by DT maintainer Rob. > > > > > > > > > > What is the issue in doing this during the probe() stage? It looks like you are > > > working with the static info in the devicetree, which is already available > > > during the controller probe(). > > > > There are problems. > > One: It is not good to manually parser this property in pci host bridge > > drivers. > > > > Why? I see the comment from Rob saying that the host bridge driver should not > parse iommu* properties, but this series is essentially doing the same just in a > different place. Rob's means is that host bridge driver should NOT parse "msi-map", "msi-mask", "iommu-map", "iommu-mask" by use low level dt read property API function. It should be fine to use high level of_map API to map rid to sid. A typical existed issue of manual parse commom property is drivers/irqchip/irq-ls-extirq.c, which missed consider "#address-size". This series use of_map API, instead of parse msi-map\iommu-map directly. > > > Two: of_map default is bypass map. For example: if in dts only 2 sid, 0xA > > and 0xB. If try to enable 3rd function RID(103), there are no error report. > > of_map will return RID 103 as stream ID. DMA will write to wrong > > possition possibly. > > > > Well, you can use iommu-map-mask to allow all devices under a bus to share the > same SID. It will allow you to work with the LUT limitation. But the downside is > that, there would be no isolation between devices under the same bus. But you can't do that for GIC ITS case. Device A have msi 1-16, device B have msi 1-16. You can't shared one SID for device A and device B. ITS also need stream ID. > > > https://elixir.bootlin.com/linux/v6.12-rc1/source/drivers/of/base.c#L2070 > > > > Three: LUT resource is limited, if DT provide 16 entry, but LUT have only 8 > > items, if more device enable, not LUT avaible and can't return error. of > > course, it may fix dts, but It'd better that driver can handle error > > properly when meet wrong dtb file. > > > > Drivers can trust the DT, unless there are evidence of broken DT available in > upstream or got fixed. The problem is the broken DT should not cause fatal problem as much as possible. for example, broken DT can cause PCIE doesn't work, but should not cause system crash. Frank > > If you really want to validate DT, use dt-bindings. > > - Mani > > > > > > > > Above ways can resolve LUT take or stream id out of usage the problem. If > > > > there are not enough stream id resource, not error return, EP hardware > > > > still issue DMA to do transfer, which may transfer to wrong possition. > > > > > > > > Add enable(disable)_device() hook for bridge can return error when not > > > > enough resource, and PCI device can't enabled. > > > > > > > > > > {enable/disable}_device() doesn't convey the fact you are mapping BDF to SID in > > > the hardware. Maybe something like, {map/unmap}_bdf2sid() or similar would make > > > sense. > > > > It is called in PCI common code do_pci_enable_device(), hook functin name > > should be similar with caller. {map/unmap}_bdf2sid() is just implementation > > in dwc. > > > > stream id is only ARM platform concept. > > > > May other host bridge do difference thing at enable/disable_device(). > > > > So I am still perfer use {enable/disable}_device(). > > > > > > Frank > > > > > > > > - Mani > > > > > > > Basicallly this version can match Bjorn's requirement: > > > > 1: simple, because it is rare that there are no LUT resource. > > > > 2: EP driver probe failure when no LUT, but lspci can see such device. > > > > > > > > [ 2.164415] nvme nvme0: pci function 0000:01:00.0 > > > > [ 2.169142] pci 0000:00:00.0: Error enabling bridge (-1), continuing > > > > [ 2.175654] nvme 0000:01:00.0: probe with driver nvme failed with error -12 > > > > > > > > > lspci > > > > 0000:00:00.0 PCI bridge: Philips Semiconductors Device 0000 > > > > 0000:01:00.0 Non-Volatile memory controller: Micron Technology Inc 2100AI NVMe SSD [Nitro] (rev 03) > > > > > > > > To: Bjorn Helgaas <bhelgaas@google.com> > > > > To: Richard Zhu <hongxing.zhu@nxp.com> > > > > To: Lucas Stach <l.stach@pengutronix.de> > > > > To: Lorenzo Pieralisi <lpieralisi@kernel.org> > > > > To: Krzysztof Wilczyński <kw@linux.com> > > > > To: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > > > > To: Rob Herring <robh@kernel.org> > > > > To: Shawn Guo <shawnguo@kernel.org> > > > > To: Sascha Hauer <s.hauer@pengutronix.de> > > > > To: Pengutronix Kernel Team <kernel@pengutronix.de> > > > > To: Fabio Estevam <festevam@gmail.com> > > > > Cc: linux-pci@vger.kernel.org > > > > Cc: linux-kernel@vger.kernel.org > > > > Cc: linux-arm-kernel@lists.infradead.org > > > > Cc: imx@lists.linux.dev > > > > Cc: Frank.li@nxp.com \ > > > > Cc: alyssa@rosenzweig.io \ > > > > Cc: bpf@vger.kernel.org \ > > > > Cc: broonie@kernel.org \ > > > > Cc: jgg@ziepe.ca \ > > > > Cc: joro@8bytes.org \ > > > > Cc: l.stach@pengutronix.de \ > > > > Cc: lgirdwood@gmail.com \ > > > > Cc: maz@kernel.org \ > > > > Cc: p.zabel@pengutronix.de \ > > > > Cc: robin.murphy@arm.com \ > > > > Cc: will@kernel.org \ > > > > > > > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > > > > --- > > > > Changes in v2: > > > > - see each patch > > > > - Link to v1: https://lore.kernel.org/r/20240926-imx95_lut-v1-0-d0c62087dbab@nxp.com > > > > > > > > --- > > > > Frank Li (2): > > > > PCI: Add enable_device() and disable_device() callbacks for bridges > > > > PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 > > > > > > > > drivers/pci/controller/dwc/pci-imx6.c | 133 +++++++++++++++++++++++++++++++++- > > > > drivers/pci/pci.c | 14 ++++ > > > > include/linux/pci.h | 2 + > > > > 3 files changed, 148 insertions(+), 1 deletion(-) > > > > --- > > > > base-commit: 2849622e7b01d5aea1b060ba3955054798c1e0bb > > > > change-id: 20240926-imx95_lut-1c68222e0944 > > > > > > > > Best regards, > > > > --- > > > > Frank Li <Frank.Li@nxp.com> > > > > > > > > > > > > > > -- > > > மணிவண்ணன் சதாசிவம் > > -- > மணிவண்ணன் சதாசிவம் ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-10-07 15:27 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-09-30 19:42 [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Frank Li 2024-09-30 19:42 ` [PATCH v2 1/2] PCI: Add enable_device() and disable_device() callbacks for bridges Frank Li 2024-10-02 22:46 ` Bjorn Helgaas 2024-10-03 10:30 ` Robin Murphy 2024-09-30 19:42 ` [PATCH v2 2/2] PCI: imx6: Add IOMMU and ITS MSI support for i.MX95 Frank Li 2024-10-03 11:16 ` Robin Murphy 2024-10-03 21:12 ` Frank Li 2024-10-02 22:24 ` [PATCH v2 0/2] PCI: add enabe(disable)_device() hook for bridge Bjorn Helgaas 2024-10-03 5:15 ` Manivannan Sadhasivam 2024-10-03 19:18 ` Frank Li 2024-10-06 17:50 ` Manivannan Sadhasivam 2024-10-07 15:19 ` Frank Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox