public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v9 0/3] Tango PCIe controller support
@ 2017-06-20  8:12 Marc Gonzalez
  2017-06-20  8:14 ` [PATCH v9 1/3] PCI: Add DT binding for tango PCIe controller Marc Gonzalez
                   ` (3 more replies)
  0 siblings, 4 replies; 41+ messages in thread
From: Marc Gonzalez @ 2017-06-20  8:12 UTC (permalink / raw)
  To: linux-arm-kernel

Marc Z pointed out that posting partial series is not ideal.
Collect last-minute fixups into a single patch series.

- Bump series to v9 to avoid any ambiguity
- Add Rob's Ack on patch 1

Marc Gonzalez (3):
  PCI: Add DT binding for tango PCIe controller
  PCI: Add tango PCIe host bridge support
  PCI: Add tango MSI controller support

 .../devicetree/bindings/pci/tango-pcie.txt         |  29 ++
 drivers/pci/host/Kconfig                           |   8 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pcie-tango.c                      | 390 +++++++++++++++++++++
 include/linux/pci_ids.h                            |   2 +
 5 files changed, 430 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/tango-pcie.txt
 create mode 100644 drivers/pci/host/pcie-tango.c

-- 
2.11.0

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 1/3] PCI: Add DT binding for tango PCIe controller
  2017-06-20  8:12 [PATCH v9 0/3] Tango PCIe controller support Marc Gonzalez
@ 2017-06-20  8:14 ` Marc Gonzalez
  2017-06-20  8:17 ` [PATCH v9 2/3] PCI: Add tango PCIe host bridge support Marc Gonzalez
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 41+ messages in thread
From: Marc Gonzalez @ 2017-06-20  8:14 UTC (permalink / raw)
  To: linux-arm-kernel

Binding for the Sigma Designs SMP8759 SoC.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
---
 .../devicetree/bindings/pci/tango-pcie.txt         | 29 ++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/tango-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/tango-pcie.txt b/Documentation/devicetree/bindings/pci/tango-pcie.txt
new file mode 100644
index 000000000000..244683836a79
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/tango-pcie.txt
@@ -0,0 +1,29 @@
+Sigma Designs Tango PCIe controller
+
+Required properties:
+
+- compatible: "sigma,smp8759-pcie"
+- reg: address/size of PCI configuration space, address/size of register area
+- bus-range: defined by size of PCI configuration space
+- device_type: "pci"
+- #size-cells: <2>
+- #address-cells: <3>
+- msi-controller
+- ranges: translation from system to bus addresses
+- interrupts: spec for misc interrupts, spec for MSI
+
+Example:
+
+	pcie at 2e000 {
+		compatible = "sigma,smp8759-pcie";
+		reg = <0x50000000 0x400000>, <0x2e000 0x100>;
+		bus-range = <0 3>;
+		device_type = "pci";
+		#size-cells = <2>;
+		#address-cells = <3>;
+		msi-controller;
+		ranges = <0x02000000 0x0 0x00400000  0x50400000  0x0 0x3c00000>;
+		interrupts =
+			<54 IRQ_TYPE_LEVEL_HIGH>, /* misc interrupts */
+			<55 IRQ_TYPE_LEVEL_HIGH>; /* MSI */
+	};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-06-20  8:12 [PATCH v9 0/3] Tango PCIe controller support Marc Gonzalez
  2017-06-20  8:14 ` [PATCH v9 1/3] PCI: Add DT binding for tango PCIe controller Marc Gonzalez
@ 2017-06-20  8:17 ` Marc Gonzalez
  2017-07-02 23:18   ` Bjorn Helgaas
  2017-06-20  8:18 ` [PATCH v9 3/3] PCI: Add tango MSI controller support Marc Gonzalez
  2017-07-04 20:24 ` [PATCH v9 0/3] Tango PCIe " Bjorn Helgaas
  3 siblings, 1 reply; 41+ messages in thread
From: Marc Gonzalez @ 2017-06-20  8:17 UTC (permalink / raw)
  To: linux-arm-kernel

This driver is required to work around several hardware bugs
in the PCIe controller.

NB: Revision 1 does not support legacy interrupts, or IO space.

Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
---
 drivers/pci/host/Kconfig      |   8 +++
 drivers/pci/host/Makefile     |   1 +
 drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci_ids.h       |   2 +
 4 files changed, 175 insertions(+)
 create mode 100644 drivers/pci/host/pcie-tango.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index d7e7c0a827c3..5183d9095c3a 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -285,6 +285,14 @@ config PCIE_ROCKCHIP
 	  There is 1 internal PCIe port available to support GEN2 with
 	  4 slots.
 
+config PCIE_TANGO
+	bool "Tango PCIe controller"
+	depends on ARCH_TANGO && PCI_MSI && OF
+	select PCI_HOST_COMMON
+	help
+	  Say Y here to enable PCIe controller support for Sigma Designs
+	  Tango systems, such as SMP8759 and later chips.
+
 config VMD
 	depends on PCI_MSI && X86_64
 	tristate "Intel Volume Management Device Driver"
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 084cb4983645..fc7ea90196f3 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -32,4 +32,5 @@ obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
 obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
 obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
 obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
+obj-$(CONFIG_PCIE_TANGO) += pcie-tango.o
 obj-$(CONFIG_VMD) += vmd.o
diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/host/pcie-tango.c
new file mode 100644
index 000000000000..67aaadcc1c5e
--- /dev/null
+++ b/drivers/pci/host/pcie-tango.c
@@ -0,0 +1,164 @@
+#include <linux/pci-ecam.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#define MSI_MAX 256
+
+#define SMP8759_MUX		0x48
+#define SMP8759_TEST_OUT	0x74
+
+struct tango_pcie {
+	void __iomem *mux;
+};
+
+/*** HOST BRIDGE SUPPORT ***/
+
+static int smp8759_config_read(struct pci_bus *bus,
+		unsigned int devfn, int where, int size, u32 *val)
+{
+	int ret;
+	struct pci_config_window *cfg = bus->sysdata;
+	struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);
+
+	/*
+	 * QUIRK #1
+	 * Reads in configuration space outside devfn 0 return garbage.
+	 */
+	if (devfn != 0)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	/*
+	 * QUIRK #2
+	 * Unfortunately, config and mem spaces are muxed.
+	 * Linux does not support such a setting, since drivers are free
+	 * to access mem space directly, at any time.
+	 * Therefore, we can only PRAY that config and mem space accesses
+	 * NEVER occur concurrently.
+	 */
+	writel_relaxed(1, pcie->mux);
+	ret = pci_generic_config_read(bus, devfn, where, size, val);
+	writel_relaxed(0, pcie->mux);
+
+	return ret;
+}
+
+static int smp8759_config_write(struct pci_bus *bus,
+		unsigned int devfn, int where, int size, u32 val)
+{
+	int ret;
+	struct pci_config_window *cfg = bus->sysdata;
+	struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);
+
+	writel_relaxed(1, pcie->mux);
+	ret = pci_generic_config_write(bus, devfn, where, size, val);
+	writel_relaxed(0, pcie->mux);
+
+	return ret;
+}
+
+static struct pci_ecam_ops smp8759_ecam_ops = {
+	.bus_shift	= 20,
+	.pci_ops	= {
+		.map_bus	= pci_ecam_map_bus,
+		.read		= smp8759_config_read,
+		.write		= smp8759_config_write,
+	}
+};
+
+static const struct of_device_id tango_pcie_ids[] = {
+	{ .compatible = "sigma,smp8759-pcie" },
+	{ /* sentinel */ },
+};
+
+static int tango_check_pcie_link(void __iomem *test_out)
+{
+	int i;
+
+	writel_relaxed(16, test_out);
+	for (i = 0; i < 10; ++i) {
+		u32 ltssm_state = readl_relaxed(test_out) >> 8;
+		if ((ltssm_state & 0x1f) == 0xf) /* L0 */
+			return 0;
+		usleep_range(3000, 4000);
+	}
+
+	return -ENODEV;
+}
+
+static int smp8759_init(struct tango_pcie *pcie, void __iomem *base)
+{
+	pcie->mux		= base + SMP8759_MUX;
+
+	return tango_check_pcie_link(base + SMP8759_TEST_OUT);
+}
+
+static int tango_pcie_probe(struct platform_device *pdev)
+{
+	int ret = -EINVAL;
+	void __iomem *base;
+	struct resource *res;
+	struct tango_pcie *pcie;
+	struct device *dev = &pdev->dev;
+
+	pr_err("MAJOR ISSUE: PCIe config and mem spaces are muxed\n");
+	pr_err("Tainting kernel... Use driver at your own risk\n");
+	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+
+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, pcie);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	if (of_device_is_compatible(dev->of_node, "sigma,smp8759-pcie"))
+		ret = smp8759_init(pcie, base);
+
+	if (ret)
+		return ret;
+
+	return pci_host_common_probe(pdev, &smp8759_ecam_ops);
+}
+
+static struct platform_driver tango_pcie_driver = {
+	.probe	= tango_pcie_probe,
+	.driver	= {
+		.name = KBUILD_MODNAME,
+		.of_match_table = tango_pcie_ids,
+	},
+};
+
+builtin_platform_driver(tango_pcie_driver);
+
+/*
+ * QUIRK #3
+ * The root complex advertizes the wrong device class.
+ * Header Type 1 is for PCI-to-PCI bridges.
+ */
+static void tango_fixup_class(struct pci_dev *dev)
+{
+	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x24, tango_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x28, tango_fixup_class);
+
+/*
+ * QUIRK #4
+ * The root complex exposes a "fake" BAR, which is used to filter
+ * bus-to-system accesses. Only accesses within the range defined
+ * by this BAR are forwarded to the host, others are ignored.
+ *
+ * By default, the DMA framework expects an identity mapping,
+ * and DRAM0 is mapped@0x80000000.
+ */
+static void tango_fixup_bar(struct pci_dev *dev)
+{
+	dev->non_compliant_bars = true;
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x80000000);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x24, tango_fixup_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x28, tango_fixup_bar);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f020ab4079d3..b577dbe46f8f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1369,6 +1369,8 @@
 #define PCI_DEVICE_ID_TTI_HPT374	0x0008
 #define PCI_DEVICE_ID_TTI_HPT372N	0x0009	/* apparently a 372N variant? */
 
+#define PCI_VENDOR_ID_SIGMA		0x1105
+
 #define PCI_VENDOR_ID_VIA		0x1106
 #define PCI_DEVICE_ID_VIA_8763_0	0x0198
 #define PCI_DEVICE_ID_VIA_8380_0	0x0204
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v9 3/3] PCI: Add tango MSI controller support
  2017-06-20  8:12 [PATCH v9 0/3] Tango PCIe controller support Marc Gonzalez
  2017-06-20  8:14 ` [PATCH v9 1/3] PCI: Add DT binding for tango PCIe controller Marc Gonzalez
  2017-06-20  8:17 ` [PATCH v9 2/3] PCI: Add tango PCIe host bridge support Marc Gonzalez
@ 2017-06-20  8:18 ` Marc Gonzalez
  2017-07-04 20:24 ` [PATCH v9 0/3] Tango PCIe " Bjorn Helgaas
  3 siblings, 0 replies; 41+ messages in thread
From: Marc Gonzalez @ 2017-06-20  8:18 UTC (permalink / raw)
  To: linux-arm-kernel

The MSI controller in Tango supports 256 message-signaled interrupts,
and a single doorbell address.

Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
---
 drivers/pci/host/pcie-tango.c | 226 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 226 insertions(+)

diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/host/pcie-tango.c
index 67aaadcc1c5e..5c47a4cc03e3 100644
--- a/drivers/pci/host/pcie-tango.c
+++ b/drivers/pci/host/pcie-tango.c
@@ -1,16 +1,229 @@
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/pci-ecam.h>
 #include <linux/delay.h>
+#include <linux/msi.h>
 #include <linux/of.h>
 
 #define MSI_MAX 256
 
 #define SMP8759_MUX		0x48
 #define SMP8759_TEST_OUT	0x74
+#define SMP8759_STATUS		0x80
+#define SMP8759_ENABLE		0xa0
+#define SMP8759_DOORBELL	0xa002e07c
 
 struct tango_pcie {
+	DECLARE_BITMAP(used_msi, MSI_MAX);
+	spinlock_t used_msi_lock;
 	void __iomem *mux;
+	void __iomem *msi_status;
+	void __iomem *msi_enable;
+	phys_addr_t msi_doorbell;
+	struct irq_domain *irq_dom;
+	struct irq_domain *msi_dom;
+	int irq;
 };
 
+/*** MSI CONTROLLER SUPPORT ***/
+
+static void tango_msi_isr(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct tango_pcie *pcie = irq_desc_get_handler_data(desc);
+	unsigned long status, base, virq, idx, pos = 0;
+
+	chained_irq_enter(chip, desc);
+	spin_lock(&pcie->used_msi_lock);
+
+	while ((pos = find_next_bit(pcie->used_msi, MSI_MAX, pos)) < MSI_MAX) {
+		base = round_down(pos, 32);
+		status = readl_relaxed(pcie->msi_status + base / 8);
+		for_each_set_bit(idx, &status, 32) {
+			virq = irq_find_mapping(pcie->irq_dom, base + idx);
+			generic_handle_irq(virq);
+		}
+		pos = base + 32;
+	}
+
+	spin_unlock(&pcie->used_msi_lock);
+	chained_irq_exit(chip, desc);
+}
+
+static void tango_ack(struct irq_data *d)
+{
+	struct tango_pcie *pcie = d->chip_data;
+	u32 offset = (d->hwirq / 32) * 4;
+	u32 bit = BIT(d->hwirq % 32);
+
+	writel_relaxed(bit, pcie->msi_status + offset);
+}
+
+static void update_msi_enable(struct irq_data *d, bool unmask)
+{
+	unsigned long flags;
+	struct tango_pcie *pcie = d->chip_data;
+	u32 offset = (d->hwirq / 32) * 4;
+	u32 bit = BIT(d->hwirq % 32);
+	u32 val;
+
+	spin_lock_irqsave(&pcie->used_msi_lock, flags);
+	val = readl_relaxed(pcie->msi_enable + offset);
+	val = unmask ? val | bit : val & ~bit;
+	writel_relaxed(val, pcie->msi_enable + offset);
+	spin_unlock_irqrestore(&pcie->used_msi_lock, flags);
+}
+
+static void tango_mask(struct irq_data *d)
+{
+	update_msi_enable(d, false);
+}
+
+static void tango_unmask(struct irq_data *d)
+{
+	update_msi_enable(d, true);
+}
+
+static int tango_set_affinity(struct irq_data *d,
+		const struct cpumask *mask, bool force)
+{
+	return -EINVAL;
+}
+
+static void tango_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
+{
+	struct tango_pcie *pcie = d->chip_data;
+	msg->address_lo = lower_32_bits(pcie->msi_doorbell);
+	msg->address_hi = upper_32_bits(pcie->msi_doorbell);
+	msg->data = d->hwirq;
+}
+
+static struct irq_chip tango_chip = {
+	.irq_ack		= tango_ack,
+	.irq_mask		= tango_mask,
+	.irq_unmask		= tango_unmask,
+	.irq_set_affinity	= tango_set_affinity,
+	.irq_compose_msi_msg	= tango_compose_msi_msg,
+};
+
+static void msi_ack(struct irq_data *d)
+{
+	irq_chip_ack_parent(d);
+}
+
+static void msi_mask(struct irq_data *d)
+{
+	pci_msi_mask_irq(d);
+	irq_chip_mask_parent(d);
+}
+
+static void msi_unmask(struct irq_data *d)
+{
+	pci_msi_unmask_irq(d);
+	irq_chip_unmask_parent(d);
+}
+
+static struct irq_chip msi_chip = {
+	.name = "MSI",
+	.irq_ack = msi_ack,
+	.irq_mask = msi_mask,
+	.irq_unmask = msi_unmask,
+};
+
+static struct msi_domain_info msi_dom_info = {
+	.flags	= MSI_FLAG_PCI_MSIX
+		| MSI_FLAG_USE_DEF_DOM_OPS
+		| MSI_FLAG_USE_DEF_CHIP_OPS,
+	.chip	= &msi_chip,
+};
+
+static int tango_irq_domain_alloc(struct irq_domain *dom,
+		unsigned int virq, unsigned int nr_irqs, void *args)
+{
+	int pos;
+	unsigned long flags;
+	struct tango_pcie *pcie = dom->host_data;
+
+	spin_lock_irqsave(&pcie->used_msi_lock, flags);
+	pos = find_first_zero_bit(pcie->used_msi, MSI_MAX);
+	if (pos >= MSI_MAX) {
+		spin_unlock_irqrestore(&pcie->used_msi_lock, flags);
+		return -ENOSPC;
+	}
+	__set_bit(pos, pcie->used_msi);
+	spin_unlock_irqrestore(&pcie->used_msi_lock, flags);
+	irq_domain_set_info(dom, virq, pos, &tango_chip,
+			pcie, handle_edge_irq, NULL, NULL);
+
+	return 0;
+}
+
+static void tango_irq_domain_free(struct irq_domain *dom,
+		unsigned int virq, unsigned int nr_irqs)
+{
+	unsigned long flags;
+	struct irq_data *d = irq_domain_get_irq_data(dom, virq);
+	struct tango_pcie *pcie = d->chip_data;
+
+	spin_lock_irqsave(&pcie->used_msi_lock, flags);
+	__clear_bit(d->hwirq, pcie->used_msi);
+	spin_unlock_irqrestore(&pcie->used_msi_lock, flags);
+}
+
+static const struct irq_domain_ops irq_dom_ops = {
+	.alloc	= tango_irq_domain_alloc,
+	.free	= tango_irq_domain_free,
+};
+
+static int tango_msi_remove(struct platform_device *pdev)
+{
+	struct tango_pcie *pcie = platform_get_drvdata(pdev);
+
+	irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
+	irq_domain_remove(pcie->msi_dom);
+	irq_domain_remove(pcie->irq_dom);
+
+	return 0;
+}
+
+static int tango_msi_probe(struct platform_device *pdev, struct tango_pcie *pcie)
+{
+	int i, virq;
+	struct irq_domain *msi_dom, *irq_dom;
+	struct fwnode_handle *fwnode = of_node_to_fwnode(pdev->dev.of_node);
+
+	spin_lock_init(&pcie->used_msi_lock);
+	for (i = 0; i < MSI_MAX / 32; ++i)
+		writel_relaxed(0, pcie->msi_enable + i * 4);
+
+	virq = platform_get_irq(pdev, 1);
+	if (virq <= 0) {
+		pr_err("Failed to map IRQ\n");
+		return -ENXIO;
+	}
+
+	irq_dom = irq_domain_create_linear(fwnode, MSI_MAX, &irq_dom_ops, pcie);
+	if (!irq_dom) {
+		pr_err("Failed to create IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	msi_dom = pci_msi_create_irq_domain(fwnode, &msi_dom_info, irq_dom);
+	if (!msi_dom) {
+		pr_err("Failed to create MSI domain\n");
+		irq_domain_remove(irq_dom);
+		return -ENOMEM;
+	}
+
+	pcie->irq_dom = irq_dom;
+	pcie->msi_dom = msi_dom;
+	pcie->irq = virq;
+
+	irq_set_chained_handler_and_data(virq, tango_msi_isr, pcie);
+
+	return 0;
+}
+
 /*** HOST BRIDGE SUPPORT ***/
 
 static int smp8759_config_read(struct pci_bus *bus,
@@ -88,6 +301,9 @@ static int tango_check_pcie_link(void __iomem *test_out)
 static int smp8759_init(struct tango_pcie *pcie, void __iomem *base)
 {
 	pcie->mux		= base + SMP8759_MUX;
+	pcie->msi_status	= base + SMP8759_STATUS;
+	pcie->msi_enable	= base + SMP8759_ENABLE;
+	pcie->msi_doorbell	= SMP8759_DOORBELL;
 
 	return tango_check_pcie_link(base + SMP8759_TEST_OUT);
 }
@@ -121,11 +337,21 @@ static int tango_pcie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = tango_msi_probe(pdev, pcie);
+	if (ret)
+		return ret;
+
 	return pci_host_common_probe(pdev, &smp8759_ecam_ops);
 }
 
+static int tango_pcie_remove(struct platform_device *pdev)
+{
+	return tango_msi_remove(pdev);
+}
+
 static struct platform_driver tango_pcie_driver = {
 	.probe	= tango_pcie_probe,
+	.remove	= tango_pcie_remove,
 	.driver	= {
 		.name = KBUILD_MODNAME,
 		.of_match_table = tango_pcie_ids,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-06-20  8:17 ` [PATCH v9 2/3] PCI: Add tango PCIe host bridge support Marc Gonzalez
@ 2017-07-02 23:18   ` Bjorn Helgaas
  2017-07-03  9:35     ` Ard Biesheuvel
  2017-07-03  9:54     ` Marc Gonzalez
  0 siblings, 2 replies; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-02 23:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
> This driver is required to work around several hardware bugs
> in the PCIe controller.
> 
> NB: Revision 1 does not support legacy interrupts, or IO space.

I had to apply these manually because of conflicts in Kconfig and
Makefile.  What are these based on?  Easiest for me is if you base
them on the current -rc1 tag.

> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> ---
>  drivers/pci/host/Kconfig      |   8 +++
>  drivers/pci/host/Makefile     |   1 +
>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pci_ids.h       |   2 +
>  4 files changed, 175 insertions(+)
>  create mode 100644 drivers/pci/host/pcie-tango.c
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index d7e7c0a827c3..5183d9095c3a 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -285,6 +285,14 @@ config PCIE_ROCKCHIP
>  	  There is 1 internal PCIe port available to support GEN2 with
>  	  4 slots.
>  
> +config PCIE_TANGO
> +	bool "Tango PCIe controller"
> +	depends on ARCH_TANGO && PCI_MSI && OF
> +	select PCI_HOST_COMMON
> +	help
> +	  Say Y here to enable PCIe controller support for Sigma Designs
> +	  Tango systems, such as SMP8759 and later chips.
> +
>  config VMD
>  	depends on PCI_MSI && X86_64
>  	tristate "Intel Volume Management Device Driver"
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 084cb4983645..fc7ea90196f3 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -32,4 +32,5 @@ obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
>  obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
>  obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
>  obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
> +obj-$(CONFIG_PCIE_TANGO) += pcie-tango.o
>  obj-$(CONFIG_VMD) += vmd.o
> diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/host/pcie-tango.c
> new file mode 100644
> index 000000000000..67aaadcc1c5e
> --- /dev/null
> +++ b/drivers/pci/host/pcie-tango.c
> @@ -0,0 +1,164 @@
> +#include <linux/pci-ecam.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +
> +#define MSI_MAX 256
> +
> +#define SMP8759_MUX		0x48
> +#define SMP8759_TEST_OUT	0x74
> +
> +struct tango_pcie {
> +	void __iomem *mux;
> +};
> +
> +/*** HOST BRIDGE SUPPORT ***/
> +
> +static int smp8759_config_read(struct pci_bus *bus,
> +		unsigned int devfn, int where, int size, u32 *val)

Wrap these with as much as possible on the first line, e.g.,

  static int smp8759_config_read(struct pci_bus *bus, unsigned int devfn,
                                 int where, int size, u32 *val)


> +{
> +	int ret;
> +	struct pci_config_window *cfg = bus->sysdata;
> +	struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);

Reorder as:

        struct pci_config_window *cfg = bus->sysdata;
        struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);
        int ret;

> +
> +	/*
> +	 * QUIRK #1

Omit "QUIRK #1", "QUIRK #2", etc unless they're actual references to an errata
document.

> +	 * Reads in configuration space outside devfn 0 return garbage.
> +	 */
> +	if (devfn != 0)
> +		return PCIBIOS_FUNC_NOT_SUPPORTED;
> +
> +	/*
> +	 * QUIRK #2
> +	 * Unfortunately, config and mem spaces are muxed.
> +	 * Linux does not support such a setting, since drivers are free
> +	 * to access mem space directly, at any time.
> +	 * Therefore, we can only PRAY that config and mem space accesses
> +	 * NEVER occur concurrently.
> +	 */
> +	writel_relaxed(1, pcie->mux);
> +	ret = pci_generic_config_read(bus, devfn, where, size, val);
> +	writel_relaxed(0, pcie->mux);

I'm very hesitant about this.  When people stress this, we're going to
get reports of data corruption.  Even with the disclaimer below, I
don't feel good about this.  Adding the driver is an implicit claim
that we support the device, but we know it can't be made reliable.

What is the benefit of adding this driver?  How many units are in the
field?  Are you hoping to have support in distros like RHEL?  Are
these running self-built kernels straight from kernel.org?  Is it
feasible for you to distribute this driver separately from the
upstream kernel?

> +	return ret;
> +}
> +
> +static int smp8759_config_write(struct pci_bus *bus,
> +		unsigned int devfn, int where, int size, u32 val)
> +{
> +	int ret;
> +	struct pci_config_window *cfg = bus->sysdata;
> +	struct tango_pcie *pcie = dev_get_drvdata(cfg->parent);
> +
> +	writel_relaxed(1, pcie->mux);
> +	ret = pci_generic_config_write(bus, devfn, where, size, val);
> +	writel_relaxed(0, pcie->mux);
> +
> +	return ret;
> +}
> +
> +static struct pci_ecam_ops smp8759_ecam_ops = {
> +	.bus_shift	= 20,
> +	.pci_ops	= {
> +		.map_bus	= pci_ecam_map_bus,
> +		.read		= smp8759_config_read,
> +		.write		= smp8759_config_write,
> +	}
> +};
> +
> +static const struct of_device_id tango_pcie_ids[] = {
> +	{ .compatible = "sigma,smp8759-pcie" },
> +	{ /* sentinel */ },
> +};

Move table down to point where it's needed.

> +static int tango_check_pcie_link(void __iomem *test_out)

I think this is checking for link up.  Rename to tango_pcie_link_up()
to follow the convention of other drivers.  Take a struct tango_pcie *
instead of an address, if possible.

> +{
> +	int i;
> +
> +	writel_relaxed(16, test_out);
> +	for (i = 0; i < 10; ++i) {
> +		u32 ltssm_state = readl_relaxed(test_out) >> 8;
> +		if ((ltssm_state & 0x1f) == 0xf) /* L0 */
> +			return 0;
> +		usleep_range(3000, 4000);
> +	}
> +
> +	return -ENODEV;
> +}
> +
> +static int smp8759_init(struct tango_pcie *pcie, void __iomem *base)
> +{
> +	pcie->mux		= base + SMP8759_MUX;
> +
> +	return tango_check_pcie_link(base + SMP8759_TEST_OUT);
> +}
> +
> +static int tango_pcie_probe(struct platform_device *pdev)
> +{
> +	int ret = -EINVAL;
> +	void __iomem *base;
> +	struct resource *res;
> +	struct tango_pcie *pcie;
> +	struct device *dev = &pdev->dev;

Reverse declaration order.  Then they'll be declared in order of use.

> +	pr_err("MAJOR ISSUE: PCIe config and mem spaces are muxed\n");
> +	pr_err("Tainting kernel... Use driver at your own risk\n");

These should be dev_err().

> +	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
> +
> +	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, pcie);

Minor style: move this down to the end, so we're not associating an
uninitialized drvdata structure with the pdev.  Better to wait until
it's fully initialized.

> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	base = devm_ioremap_resource(&pdev->dev, res);

Use "dev", not "&pdev->dev".

> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	if (of_device_is_compatible(dev->of_node, "sigma,smp8759-pcie"))

Not necessary, since tango_pcie_ids[] only contains
"sigma,smp8759-pcie".  If/when you need different init for different
versions, you can add something like this back, and it will be obvious
why it's needed.  Right now, there's no need for this, so it looks out
of place.

> +		ret = smp8759_init(pcie, base);
> +
> +	if (ret)
> +		return ret;
> +
> +	return pci_host_common_probe(pdev, &smp8759_ecam_ops);
> +}
> +
> +static struct platform_driver tango_pcie_driver = {
> +	.probe	= tango_pcie_probe,
> +	.driver	= {
> +		.name = KBUILD_MODNAME,
> +		.of_match_table = tango_pcie_ids,

I think you need ".suppress_bind_attrs = true" here to prevent issues
when unbinding driver.  See
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=a5f40e8098fe

> +	},
> +};
> +

Remove blank line.

> +builtin_platform_driver(tango_pcie_driver);
> +
> +/*
> + * QUIRK #3
> + * The root complex advertizes the wrong device class.

s/advertizes/advertises/

> + * Header Type 1 is for PCI-to-PCI bridges.
> + */
> +static void tango_fixup_class(struct pci_dev *dev)
> +{
> +	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
> +}
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x24, tango_fixup_class);
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x28, tango_fixup_class);
> +
> +/*
> + * QUIRK #4
> + * The root complex exposes a "fake" BAR, which is used to filter
> + * bus-to-system accesses. Only accesses within the range defined
> + * by this BAR are forwarded to the host, others are ignored.
> + *
> + * By default, the DMA framework expects an identity mapping,
> + * and DRAM0 is mapped at 0x80000000.
> + */
> +static void tango_fixup_bar(struct pci_dev *dev)
> +{
> +	dev->non_compliant_bars = true;
> +	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x80000000);
> +}
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x24, tango_fixup_bar);
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIGMA, 0x28, tango_fixup_bar);
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index f020ab4079d3..b577dbe46f8f 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -1369,6 +1369,8 @@
>  #define PCI_DEVICE_ID_TTI_HPT374	0x0008
>  #define PCI_DEVICE_ID_TTI_HPT372N	0x0009	/* apparently a 372N variant? */
>  
> +#define PCI_VENDOR_ID_SIGMA		0x1105
> +
>  #define PCI_VENDOR_ID_VIA		0x1106
>  #define PCI_DEVICE_ID_VIA_8763_0	0x0198
>  #define PCI_DEVICE_ID_VIA_8380_0	0x0204
> -- 
> 2.11.0
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-02 23:18   ` Bjorn Helgaas
@ 2017-07-03  9:35     ` Ard Biesheuvel
  2017-07-03 13:27       ` Bjorn Helgaas
  2017-07-03  9:54     ` Marc Gonzalez
  1 sibling, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2017-07-03  9:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
>> This driver is required to work around several hardware bugs
>> in the PCIe controller.
>>
>> NB: Revision 1 does not support legacy interrupts, or IO space.
>
> I had to apply these manually because of conflicts in Kconfig and
> Makefile.  What are these based on?  Easiest for me is if you base
> them on the current -rc1 tag.
>
>> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
>> ---
>>  drivers/pci/host/Kconfig      |   8 +++
>>  drivers/pci/host/Makefile     |   1 +
>>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/pci_ids.h       |   2 +
>>  4 files changed, 175 insertions(+)
>>  create mode 100644 drivers/pci/host/pcie-tango.c
>>
[..]
>> +     /*
>> +      * QUIRK #2
>> +      * Unfortunately, config and mem spaces are muxed.
>> +      * Linux does not support such a setting, since drivers are free
>> +      * to access mem space directly, at any time.
>> +      * Therefore, we can only PRAY that config and mem space accesses
>> +      * NEVER occur concurrently.
>> +      */
>> +     writel_relaxed(1, pcie->mux);
>> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
>> +     writel_relaxed(0, pcie->mux);
>
> I'm very hesitant about this.  When people stress this, we're going to
> get reports of data corruption.  Even with the disclaimer below, I
> don't feel good about this.  Adding the driver is an implicit claim
> that we support the device, but we know it can't be made reliable.
>

I noticed that the Synopsys driver suffers from a similar issue: in
dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
to perform a config space access, and switches it back to I/O space
afterwards (unless it has more than 2 viewports, in which case it uses
dedicated windows for I/O space and config space)

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-02 23:18   ` Bjorn Helgaas
  2017-07-03  9:35     ` Ard Biesheuvel
@ 2017-07-03  9:54     ` Marc Gonzalez
  2017-07-03 13:40       ` Bjorn Helgaas
       [not found]       ` <e57debab-3457-1d9c-a72e-ecdf7d4f742e@sigmadesigns.com>
  1 sibling, 2 replies; 41+ messages in thread
From: Marc Gonzalez @ 2017-07-03  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Bjorn,

On 03/07/2017 01:18, Bjorn Helgaas wrote:

> On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
> 
>> This driver is required to work around several hardware bugs
>> in the PCIe controller.
>
> [ Snip style issues ]

I wish you had pointed these out in your May 23 review, or in
my March 29 version (or even just alluded to them). I would
have fixed them in time for 2.13.


>> +	/*
>> +	 * QUIRK #2
>> +	 * Unfortunately, config and mem spaces are muxed.
>> +	 * Linux does not support such a setting, since drivers are free
>> +	 * to access mem space directly, at any time.
>> +	 * Therefore, we can only PRAY that config and mem space accesses
>> +	 * NEVER occur concurrently.
>> +	 */
>> +	writel_relaxed(1, pcie->mux);
>> +	ret = pci_generic_config_read(bus, devfn, where, size, val);
>> +	writel_relaxed(0, pcie->mux);
> 
> I'm very hesitant about this.  When people stress this, we're going to
> get reports of data corruption.  Even with the disclaimer below, I
> don't feel good about this.  Adding the driver is an implicit claim
> that we support the device, but we know it can't be made reliable.

I can't say I didn't see this coming (I had taken your long silence
as a sign of your reluctance) but back in May, I thought you implied
that a warning + tainting the kernel would be sufficient.

Mark Rutland points out stop_machine. I will test this solution.
Would you find that acceptable?


> What is the benefit of adding this driver?  How many units are in the
> field?  Are you hoping to have support in distros like RHEL?  Are
> these running self-built kernels straight from kernel.org?  Is it
> feasible for you to distribute this driver separately from the
> upstream kernel?

The benefit of upstreaming (for me) is making kernel maintainers
aware that one is using specific internal APIs. Then one may be
notified when these APIs are about to change.

I'm told we have sold ~100k units. Though I don't know how many
are in the field and using PCIe.

There are no plans to use "full-blown" distros, we use embedded
oriented distros, such as buildroot.

Maintaining out-of-tree drivers is what we've been doing for
~15 years, and there are many pain-points involved. Ask Greg
what he thinks of OOT drivers.


>> +static int tango_check_pcie_link(void __iomem *test_out)
> 
> I think this is checking for link up.  Rename to tango_pcie_link_up()
> to follow the convention of other drivers.  Take a struct tango_pcie *
> instead of an address, if possible.

Anything's possible. NB: if I pass the struct, then I have to store
the address in the struct, which isn't the case now, since I never
need the address later. If you don't mind adding an unnecessary
field to the struct, I can do it. What do you say?


>> +static struct platform_driver tango_pcie_driver = {
>> +	.probe	= tango_pcie_probe,
>> +	.driver	= {
>> +		.name = KBUILD_MODNAME,
>> +		.of_match_table = tango_pcie_ids,
> 
> I think you need ".suppress_bind_attrs = true" here to prevent issues
> when unbinding driver.  See
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=a5f40e8098fe

Will do. In that case, I can drop tango_pcie_remove() right?

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03  9:35     ` Ard Biesheuvel
@ 2017-07-03 13:27       ` Bjorn Helgaas
  2017-07-04  6:58         ` Jisheng Zhang
  0 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-03 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

[+cc Jingoo, Joao]

On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:
> On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:
> > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
> >> This driver is required to work around several hardware bugs
> >> in the PCIe controller.
> >>
> >> NB: Revision 1 does not support legacy interrupts, or IO space.
> >
> > I had to apply these manually because of conflicts in Kconfig and
> > Makefile.  What are these based on?  Easiest for me is if you base
> > them on the current -rc1 tag.
> >
> >> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> >> ---
> >>  drivers/pci/host/Kconfig      |   8 +++
> >>  drivers/pci/host/Makefile     |   1 +
> >>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
> >>  include/linux/pci_ids.h       |   2 +
> >>  4 files changed, 175 insertions(+)
> >>  create mode 100644 drivers/pci/host/pcie-tango.c
> >>
> [..]
> >> +     /*
> >> +      * QUIRK #2
> >> +      * Unfortunately, config and mem spaces are muxed.
> >> +      * Linux does not support such a setting, since drivers are free
> >> +      * to access mem space directly, at any time.
> >> +      * Therefore, we can only PRAY that config and mem space accesses
> >> +      * NEVER occur concurrently.
> >> +      */
> >> +     writel_relaxed(1, pcie->mux);
> >> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
> >> +     writel_relaxed(0, pcie->mux);
> >
> > I'm very hesitant about this.  When people stress this, we're going to
> > get reports of data corruption.  Even with the disclaimer below, I
> > don't feel good about this.  Adding the driver is an implicit claim
> > that we support the device, but we know it can't be made reliable.
> 
> I noticed that the Synopsys driver suffers from a similar issue: in
> dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
> to perform a config space access, and switches it back to I/O space
> afterwards (unless it has more than 2 viewports, in which case it uses
> dedicated windows for I/O space and config space)

That doesn't sound good.  Jingoo, Joao?  I remember some discussion
about this, but not the details.

I/O accesses use wrappers (inb(), etc), so there's at least the
possibility of a mutex to serialize them with respect to config
accesses.

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03  9:54     ` Marc Gonzalez
@ 2017-07-03 13:40       ` Bjorn Helgaas
  2017-07-03 14:34         ` Marc Gonzalez
  2017-07-03 18:11         ` Russell King - ARM Linux
       [not found]       ` <e57debab-3457-1d9c-a72e-ecdf7d4f742e@sigmadesigns.com>
  1 sibling, 2 replies; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-03 13:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 03, 2017 at 11:54:20AM +0200, Marc Gonzalez wrote:
> Hello Bjorn,
> 
> On 03/07/2017 01:18, Bjorn Helgaas wrote:
> 
> > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
> > 
> >> This driver is required to work around several hardware bugs
> >> in the PCIe controller.
> >
> > [ Snip style issues ]
> 
> I wish you had pointed these out in your May 23 review, or in
> my March 29 version (or even just alluded to them). I would
> have fixed them in time for 2.13.

They're trivial, and if they were the only issues I would have just
done them myself while merging.

> >> +	/*
> >> +	 * QUIRK #2
> >> +	 * Unfortunately, config and mem spaces are muxed.
> >> +	 * Linux does not support such a setting, since drivers are free
> >> +	 * to access mem space directly, at any time.
> >> +	 * Therefore, we can only PRAY that config and mem space accesses
> >> +	 * NEVER occur concurrently.
> >> +	 */
> >> +	writel_relaxed(1, pcie->mux);
> >> +	ret = pci_generic_config_read(bus, devfn, where, size, val);
> >> +	writel_relaxed(0, pcie->mux);
> > 
> > I'm very hesitant about this.  When people stress this, we're going to
> > get reports of data corruption.  Even with the disclaimer below, I
> > don't feel good about this.  Adding the driver is an implicit claim
> > that we support the device, but we know it can't be made reliable.
> 
> I can't say I didn't see this coming (I had taken your long silence
> as a sign of your reluctance) but back in May, I thought you implied
> that a warning + tainting the kernel would be sufficient.
> 
> Mark Rutland points out stop_machine. I will test this solution.
> Would you find that acceptable?

Sounds possible, though I can't say for sure without seeing the code.

The problem is serializing vs. memory accesses, since they don't use
any wrappers.  However, they are ioremapped(), so it's at least
conceivable that another solution would be to use VM to trap those
accesses.  I'm not a VM person, so I don't know whether that's
feasible in Linux.

> > What is the benefit of adding this driver?  How many units are in the
> > field?  Are you hoping to have support in distros like RHEL?  Are
> > these running self-built kernels straight from kernel.org?  Is it
> > feasible for you to distribute this driver separately from the
> > upstream kernel?
> 
> The benefit of upstreaming (for me) is making kernel maintainers
> aware that one is using specific internal APIs. Then one may be
> notified when these APIs are about to change.
> 
> I'm told we have sold ~100k units. Though I don't know how many
> are in the field and using PCIe.
> 
> There are no plans to use "full-blown" distros, we use embedded
> oriented distros, such as buildroot.
> 
> Maintaining out-of-tree drivers is what we've been doing for
> ~15 years, and there are many pain-points involved. Ask Greg
> what he thinks of OOT drivers.
> 
> 
> >> +static int tango_check_pcie_link(void __iomem *test_out)
> > 
> > I think this is checking for link up.  Rename to tango_pcie_link_up()
> > to follow the convention of other drivers.  Take a struct tango_pcie *
> > instead of an address, if possible.
> 
> Anything's possible. NB: if I pass the struct, then I have to store
> the address in the struct, which isn't the case now, since I never
> need the address later. If you don't mind adding an unnecessary
> field to the struct, I can do it. What do you say?

The benefit of following the same formula as other drivers is pretty
large.  Most drivers save the equivalent of "base" in the struct.  If
you did that, you wouldn't need an extra pointer; you would just use
"base + SMP8759_MUX" in the config accessors and "base +
SMP8759_TEST_OUT" in tango_pcie_link_up().

> >> +static struct platform_driver tango_pcie_driver = {
> >> +	.probe	= tango_pcie_probe,
> >> +	.driver	= {
> >> +		.name = KBUILD_MODNAME,
> >> +		.of_match_table = tango_pcie_ids,
> > 
> > I think you need ".suppress_bind_attrs = true" here to prevent issues
> > when unbinding driver.  See
> > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=a5f40e8098fe
> 
> Will do. In that case, I can drop tango_pcie_remove() right?

I think so; I don't think there would be any way to remove the driver.

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 13:40       ` Bjorn Helgaas
@ 2017-07-03 14:34         ` Marc Gonzalez
  2017-07-04 15:58           ` Bjorn Helgaas
  2017-07-03 18:11         ` Russell King - ARM Linux
  1 sibling, 1 reply; 41+ messages in thread
From: Marc Gonzalez @ 2017-07-03 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

Bjorn Helgaas wrote:

> Marc Gonzalez wrote:
>
>> On 03/07/2017 01:18, Bjorn Helgaas wrote:
>>
>>> On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
>>>
>>>> +static int tango_check_pcie_link(void __iomem *test_out)
>>>
>>> I think this is checking for link up.  Rename to tango_pcie_link_up()
>>> to follow the convention of other drivers.  Take a struct tango_pcie *
>>> instead of an address, if possible.
>>
>> Anything's possible. NB: if I pass the struct, then I have to store
>> the address in the struct, which isn't the case now, since I never
>> need the address later. If you don't mind adding an unnecessary
>> field to the struct, I can do it. What do you say?
> 
> The benefit of following the same formula as other drivers is pretty
> large.  Most drivers save the equivalent of "base" in the struct.  If
> you did that, you wouldn't need an extra pointer; you would just use
> "base + SMP8759_MUX" in the config accessors and "base + SMP8759_TEST_OUT"
> in tango_pcie_link_up().

The problem is that TEST_OUT is at 0x74 on SMP8759, but at 0x138
on my other chip. In fact, all registers have been "reshuffled",
and none have the same offsets on the two chips.

My solution was to define specific registers in the struct.

In my [RFC PATCH v0.2] posted March 23, I tried illustrating
the issue:

+static const struct of_device_id tango_pcie_ids[] = {
+	{ .compatible = "sigma,smp8759-pcie" },
+	{ .compatible = "sigma,rev2-pcie" },
+	{ /* sentinel */ },
+};
+
+static void smp8759_init(struct tango_pcie *pcie, void __iomem *base)
+{
+	pcie->mux		= base + 0x48;
+	pcie->msi_status	= base + 0x80;
+	pcie->msi_mask		= base + 0xa0;
+	pcie->msi_doorbell	= 0xa0000000 + 0x2e07c;
+}
+
+static void rev2_init(struct tango_pcie *pcie, void __iomem *base)
+{
+	void __iomem *misc_irq	= base + 0x40;
+	void __iomem *doorbell	= base + 0x8c;
+
+	pcie->mux		= base + 0x2c;
+	pcie->msi_status	= base + 0x4c;
+	pcie->msi_mask		= base + 0x6c;
+	pcie->msi_doorbell	= 0x80000000;
+
+	writel(lower_32_bits(pcie->msi_doorbell), doorbell + 0);
+	writel(upper_32_bits(pcie->msi_doorbell), doorbell + 4);
+
+	/* Enable legacy PCI interrupts */
+	writel(BIT(15), misc_irq);
+	writel(0xf << 4, misc_irq + 4);
+}


Do you agree that the 'base + OFFSET' idiom does not work in
this specific situation? Would you handle it differently?

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
       [not found]       ` <e57debab-3457-1d9c-a72e-ecdf7d4f742e@sigmadesigns.com>
@ 2017-07-03 15:30         ` Marc Gonzalez
  2017-07-04  7:09           ` Peter Zijlstra
  0 siblings, 1 reply; 41+ messages in thread
From: Marc Gonzalez @ 2017-07-03 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/07/2017 15:13, Marc Gonzalez wrote:

> On 03/07/2017 11:54, Marc Gonzalez wrote:
> 
>> Mark Rutland points out stop_machine. I will test this solution.
>
> I must be misunderstanding some of the requirements for
> calling stop_machine() because my kernel panics, after
> many warnings.

Enabling several kernel debugging features:

+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+CONFIG_PROVE_LOCKING=y

And at the end of smp8759_config_read:

	printk("in_atomic_preempt_off = %d\n", in_atomic_preempt_off());
	stop_machine(do_nothing, NULL, NULL);
	panic("STOP HERE FOR NOW\n");

The kernel outputs:

[    1.022725] in_atomic_preempt_off = 0
[    1.026568] BUG: scheduling while atomic: swapper/0/1/0x00000002
[    1.032625] 5 locks held by swapper/0/1:
[    1.036575]  #0:  (&dev->mutex){......}, at: [<c038c684>] __driver_attach+0x50/0xd0
[    1.044319]  #1:  (&dev->mutex){......}, at: [<c038c694>] __driver_attach+0x60/0xd0
[    1.052050]  #2:  (pci_lock){+.+...}, at: [<c03309d8>] pci_bus_read_config_dword+0x44/0x94
[    1.060398]  #3:  (cpu_hotplug.dep_map){++++++}, at: [<c0119db0>] get_online_cpus+0x2c/0xa0
[    1.068843]  #4:  (stop_cpus_mutex){+.+...}, at: [<c01a1184>] stop_cpus+0x20/0x48
[    1.076404] Modules linked in:
[    1.079483] Preemption disabled at:[    1.082820] [<  (null)>]   (null)
[    1.086165] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.9.23-1-rc4 #13
[    1.092723] Hardware name: Sigma Tango DT
[    1.096765] [<c010f600>] (unwind_backtrace) from [<c010b568>] (show_stack+0x10/0x14)
[    1.104558] [<c010b568>] (show_stack) from [<c0304830>] (dump_stack+0x98/0xc4)
[    1.111823] [<c0304830>] (dump_stack) from [<c013eee0>] (__schedule_bug+0x94/0xec)
[    1.119436] [<c013eee0>] (__schedule_bug) from [<c0516364>] (__schedule+0x4a4/0x5f0)
[    1.127220] [<c0516364>] (__schedule) from [<c05164fc>] (schedule+0x4c/0xac)
[    1.134308] [<c05164fc>] (schedule) from [<c051b010>] (schedule_timeout+0x1f4/0x30c)
[    1.142093] [<c051b010>] (schedule_timeout) from [<c051702c>] (wait_for_common+0x8c/0x13c)
[    1.150401] [<c051702c>] (wait_for_common) from [<c05170ec>] (wait_for_completion+0x10/0x14)
[    1.158886] [<c05170ec>] (wait_for_completion) from [<c01a0d74>] (__stop_cpus+0x50/0x64)
[    1.167021] [<c01a0d74>] (__stop_cpus) from [<c01a1194>] (stop_cpus+0x30/0x48)
[    1.174282] [<c01a1194>] (stop_cpus) from [<c01a1230>] (stop_machine+0x84/0x118)
[    1.181719] [<c01a1230>] (stop_machine) from [<c034c070>] (smp8759_config_read+0x84/0x90)
[    1.189942] [<c034c070>] (smp8759_config_read) from [<c0330a00>] (pci_bus_read_config_dword+0x6c/0x94)
[    1.199301] [<c0330a00>] (pci_bus_read_config_dword) from [<c0332920>] (pci_bus_read_dev_vendor_id+0x24/0xe8)
[    1.209270] [<c0332920>] (pci_bus_read_dev_vendor_id) from [<c033413c>] (pci_scan_single_device+0x40/0xb0)
[    1.218977] [<c033413c>] (pci_scan_single_device) from [<c0334204>] (pci_scan_slot+0x58/0x100)
[    1.227636] [<c0334204>] (pci_scan_slot) from [<c033511c>] (pci_scan_child_bus+0x20/0xf8)
[    1.235858] [<c033511c>] (pci_scan_child_bus) from [<c03353ec>] (pci_scan_root_bus_msi+0xcc/0xd8)
[    1.244779] [<c03353ec>] (pci_scan_root_bus_msi) from [<c0335410>] (pci_scan_root_bus+0x18/0x20)
[    1.253612] [<c0335410>] (pci_scan_root_bus) from [<c034bc5c>] (pci_host_common_probe+0xc8/0x314)
[    1.262533] [<c034bc5c>] (pci_host_common_probe) from [<c034c444>] (tango_pcie_probe+0x148/0x350)
[    1.271455] [<c034c444>] (tango_pcie_probe) from [<c038dbc8>] (platform_drv_probe+0x34/0x6c)
[    1.279939] [<c038dbc8>] (platform_drv_probe) from [<c038c5a8>] (really_probe+0x1c4/0x250)
[    1.288248] [<c038c5a8>] (really_probe) from [<c038c700>] (__driver_attach+0xcc/0xd0)
[    1.296121] [<c038c700>] (__driver_attach) from [<c038aa50>] (bus_for_each_dev+0x68/0x9c)
[    1.304342] [<c038aa50>] (bus_for_each_dev) from [<c038bfac>] (driver_attach+0x1c/0x20)
[    1.312389] [<c038bfac>] (driver_attach) from [<c038bb5c>] (bus_add_driver+0x108/0x214)
[    1.320436] [<c038bb5c>] (bus_add_driver) from [<c038ccb0>] (driver_register+0x78/0xf4)
[    1.328483] [<c038ccb0>] (driver_register) from [<c038db8c>] (__platform_driver_register+0x40/0x48)
[    1.337583] [<c038db8c>] (__platform_driver_register) from [<c0816fc4>] (tango_pcie_driver_init+0x14/0x18)
[    1.347291] [<c0816fc4>] (tango_pcie_driver_init) from [<c01017dc>] (do_one_initcall+0x44/0x174)
[    1.356128] [<c01017dc>] (do_one_initcall) from [<c0800dcc>] (kernel_init_freeable+0x154/0x1e0)
[    1.364875] [<c0800dcc>] (kernel_init_freeable) from [<c0515544>] (kernel_init+0x8/0x10c)
[    1.373097] [<c0515544>] (kernel_init) from [<c01077d0>] (ret_from_fork+0x14/0x24)
[    1.380799] Kernel panic - not syncing: STOP HERE FOR NOW
[    1.380799] 
[    1.387714] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       4.9.23-1-rc4 #13
[    1.395495] Hardware name: Sigma Tango DT
[    1.399529] [<c010f600>] (unwind_backtrace) from [<c010b568>] (show_stack+0x10/0x14)
[    1.407317] [<c010b568>] (show_stack) from [<c0304830>] (dump_stack+0x98/0xc4)
[    1.414582] [<c0304830>] (dump_stack) from [<c01a3bac>] (panic+0xe0/0x258)
[    1.421494] [<c01a3bac>] (panic) from [<c034c07c>] (tango_check_pcie_link+0x0/0x48)
[    1.429192] [<c034c07c>] (tango_check_pcie_link) from [<c034bfec>] (smp8759_config_read+0x0/0x90)
[    1.438114] [<c034bfec>] (smp8759_config_read) from [<00241105>] (0x241105)
[    1.445191] CPU1: stopping
[    1.447910] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G        W       4.9.23-1-rc4 #13
[    1.455690] Hardware name: Sigma Tango DT
[    1.459724] [<c010f600>] (unwind_backtrace) from [<c010b568>] (show_stack+0x10/0x14)
[    1.467512] [<c010b568>] (show_stack) from [<c0304830>] (dump_stack+0x98/0xc4)
[    1.474774] [<c0304830>] (dump_stack) from [<c010e410>] (handle_IPI+0x19c/0x1b0)
[    1.482210] [<c010e410>] (handle_IPI) from [<c010151c>] (gic_handle_irq+0x88/0x8c)
[    1.489819] [<c010151c>] (gic_handle_irq) from [<c010c0b0>] (__irq_svc+0x70/0xb0)
[    1.497339] Exception stack(0xdf46ff80 to 0xdf46ffc8)
[    1.502415] ff80: 00000001 00000001 00000000 df468180 df46e000 c1004be4 c1004c48 00000002
[    1.510636] ffa0: c100f990 413fc090 00000000 00000000 00000000 df46ffd0 c0165ee0 c0108240
[    1.518853] ffc0: 20000113 ffffffff
[    1.522358] [<c010c0b0>] (__irq_svc) from [<c0108240>] (arch_cpu_idle+0x24/0x3c)
[    1.529795] [<c0108240>] (arch_cpu_idle) from [<c051b540>] (default_idle_call+0x20/0x30)
[    1.537934] [<c051b540>] (default_idle_call) from [<c015d6cc>] (cpu_startup_entry+0xd0/0x150)
[    1.546504] [<c015d6cc>] (cpu_startup_entry) from [<c010e048>] (secondary_start_kernel+0x158/0x164)
[    1.555599] [<c010e048>] (secondary_start_kernel) from [<801015ac>] (0x801015ac)
[    1.563063] ---[ end Kernel panic - not syncing: STOP HERE FOR NOW


The panic call stack looks suspicious.

smp8759_config_read() never calls tango_check_pcie_link().

(I compile with -fno-optimize-sibling-calls to get more accurate
call stacks.)

in_atomic_preempt_off is false before calling stop_machine()

I suppose I'm doing something wrong, but I'm not sure what yet.

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 13:40       ` Bjorn Helgaas
  2017-07-03 14:34         ` Marc Gonzalez
@ 2017-07-03 18:11         ` Russell King - ARM Linux
  2017-07-03 18:44           ` Ard Biesheuvel
                             ` (2 more replies)
  1 sibling, 3 replies; 41+ messages in thread
From: Russell King - ARM Linux @ 2017-07-03 18:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 03, 2017 at 08:40:31AM -0500, Bjorn Helgaas wrote:
> The problem is serializing vs. memory accesses, since they don't use
> any wrappers.  However, they are ioremapped(), so it's at least
> conceivable that another solution would be to use VM to trap those
> accesses.  I'm not a VM person, so I don't know whether that's
> feasible in Linux.

Bjorn,

You're forgetting that MMIO (iow, memory returned by ioremap()) must
be accessed through the appropriate accessors, and must not be
directly dereferenced in C.  (We do have buggy drivers that do that
but they are buggy, and in many cases are getting attention to fix
that.)

However, adding a spinlock into them is really not nice, because it
adds extra overhead that's only necessary for rare cases like Sigma
Designs - especially when you consider that these accessors are used
for all MMIO accesses, not just PCI.  It would effectively mean that
we end up serialising all MMIO accesses throughout the kernel when
Sigma Designs SoCs are enabled, destroying some of the SMP benefit.

I don't think we can sanely use the MMU to trap those accesses either,
that would mean sending IPIs to tell other CPUs to do something, and
waiting for them to respond - which can deadlock if we're already in
an IRQ-protected region (iirc, config accesses are made with IRQs
off.)

I don't think there's an easy solution to this problem - and I'm not
sure that stop_machine() can be made to work in this path (which
needs a process context).  I have a suspicion that the Sigma Designs
PCI implementation is just soo insane that it's never going to work
reliably in a multi-SoC kernel without introducing severe performance
issues for everyone else.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 18:11         ` Russell King - ARM Linux
@ 2017-07-03 18:44           ` Ard Biesheuvel
  2017-07-04 15:15           ` Bjorn Helgaas
  2017-07-04 23:59           ` Mason
  2 siblings, 0 replies; 41+ messages in thread
From: Ard Biesheuvel @ 2017-07-03 18:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 3 July 2017 at 19:11, Russell King - ARM Linux <linux@armlinux.org.uk> wrote:
> On Mon, Jul 03, 2017 at 08:40:31AM -0500, Bjorn Helgaas wrote:
>> The problem is serializing vs. memory accesses, since they don't use
>> any wrappers.  However, they are ioremapped(), so it's at least
>> conceivable that another solution would be to use VM to trap those
>> accesses.  I'm not a VM person, so I don't know whether that's
>> feasible in Linux.
>
> Bjorn,
>
> You're forgetting that MMIO (iow, memory returned by ioremap()) must
> be accessed through the appropriate accessors, and must not be
> directly dereferenced in C.  (We do have buggy drivers that do that
> but they are buggy, and in many cases are getting attention to fix
> that.)
>
> However, adding a spinlock into them is really not nice, because it
> adds extra overhead that's only necessary for rare cases like Sigma
> Designs - especially when you consider that these accessors are used
> for all MMIO accesses, not just PCI.  It would effectively mean that
> we end up serialising all MMIO accesses throughout the kernel when
> Sigma Designs SoCs are enabled, destroying some of the SMP benefit.
>
> I don't think we can sanely use the MMU to trap those accesses either,
> that would mean sending IPIs to tell other CPUs to do something, and
> waiting for them to respond - which can deadlock if we're already in
> an IRQ-protected region (iirc, config accesses are made with IRQs
> off.)
>
> I don't think there's an easy solution to this problem - and I'm not
> sure that stop_machine() can be made to work in this path (which
> needs a process context).  I have a suspicion that the Sigma Designs
> PCI implementation is just soo insane that it's never going to work
> reliably in a multi-SoC kernel without introducing severe performance
> issues for everyone else.
>

I suppose we could perhaps use per-cpu spinlocks? That would put the
complexity in the Sigma config space accessors, i.e., to take each
lock before proceeding with reprogramming the outbound window, and
other implementations wouldn't have to care. However, I do agree with
Russell that having this complexity in the first place is hard to
justify if the only implementation that requires it is a wacky design
that needs lots of other quirks to operate somewhat sanely to begin
with.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 13:27       ` Bjorn Helgaas
@ 2017-07-04  6:58         ` Jisheng Zhang
  2017-07-04  7:16           ` Jisheng Zhang
  2017-07-04  8:02           ` Ard Biesheuvel
  0 siblings, 2 replies; 41+ messages in thread
From: Jisheng Zhang @ 2017-07-04  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 3 Jul 2017 08:27:04 -0500 wrote:

> [+cc Jingoo, Joao]
> 
> On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:
> > On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:  
> > > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:  
> > >> This driver is required to work around several hardware bugs
> > >> in the PCIe controller.
> > >>
> > >> NB: Revision 1 does not support legacy interrupts, or IO space.  
> > >
> > > I had to apply these manually because of conflicts in Kconfig and
> > > Makefile.  What are these based on?  Easiest for me is if you base
> > > them on the current -rc1 tag.
> > >  
> > >> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> > >> ---
> > >>  drivers/pci/host/Kconfig      |   8 +++
> > >>  drivers/pci/host/Makefile     |   1 +
> > >>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
> > >>  include/linux/pci_ids.h       |   2 +
> > >>  4 files changed, 175 insertions(+)
> > >>  create mode 100644 drivers/pci/host/pcie-tango.c
> > >>  
> > [..]  
> > >> +     /*
> > >> +      * QUIRK #2
> > >> +      * Unfortunately, config and mem spaces are muxed.
> > >> +      * Linux does not support such a setting, since drivers are free
> > >> +      * to access mem space directly, at any time.
> > >> +      * Therefore, we can only PRAY that config and mem space accesses
> > >> +      * NEVER occur concurrently.
> > >> +      */
> > >> +     writel_relaxed(1, pcie->mux);
> > >> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
> > >> +     writel_relaxed(0, pcie->mux);  
> > >
> > > I'm very hesitant about this.  When people stress this, we're going to
> > > get reports of data corruption.  Even with the disclaimer below, I
> > > don't feel good about this.  Adding the driver is an implicit claim
> > > that we support the device, but we know it can't be made reliable.  
> > 
> > I noticed that the Synopsys driver suffers from a similar issue: in
> > dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
> > to perform a config space access, and switches it back to I/O space
> > afterwards (unless it has more than 2 viewports, in which case it uses
> > dedicated windows for I/O space and config space)  
> 
> That doesn't sound good.  Jingoo, Joao?  I remember some discussion
> about this, but not the details.
> 
> I/O accesses use wrappers (inb(), etc), so there's at least the
> possibility of a mutex to serialize them with respect to config
> accesses.
> 

IIRC, for 2 viewports, we don't need to worry about the config space
access, because config space access is serialized by pci_lock; We
do have race between config space and io space. But the accessing config
space and io space at the same time is rare. And the PCIe EPs which
has io space are rare too, supporting these EPs are not the potential
target of those platforms with 2 viewports.

Thanks,
Jisheng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 15:30         ` Marc Gonzalez
@ 2017-07-04  7:09           ` Peter Zijlstra
  2017-07-04 13:08             ` Mason
  0 siblings, 1 reply; 41+ messages in thread
From: Peter Zijlstra @ 2017-07-04  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 03, 2017 at 05:30:28PM +0200, Marc Gonzalez wrote:

> And at the end of smp8759_config_read:
> 
> 	printk("in_atomic_preempt_off = %d\n", in_atomic_preempt_off());

That's confused...

> 	stop_machine(do_nothing, NULL, NULL);
> 	panic("STOP HERE FOR NOW\n");
> 
> The kernel outputs:
> 
> [    1.022725] in_atomic_preempt_off = 0
> [    1.026568] BUG: scheduling while atomic: swapper/0/1/0x00000002
> [    1.032625] 5 locks held by swapper/0/1:
> [    1.036575]  #0:  (&dev->mutex){......}, at: [<c038c684>] __driver_attach+0x50/0xd0
> [    1.044319]  #1:  (&dev->mutex){......}, at: [<c038c694>] __driver_attach+0x60/0xd0
> [    1.052050]  #2:  (pci_lock){+.+...}, at: [<c03309d8>] pci_bus_read_config_dword+0x44/0x94

This is a raw_spinlock_t, that disables preemption

> [    1.060398]  #3:  (cpu_hotplug.dep_map){++++++}, at: [<c0119db0>] get_online_cpus+0x2c/0xa0
> [    1.068843]  #4:  (stop_cpus_mutex){+.+...}, at: [<c01a1184>] stop_cpus+0x20/0x48

> [    1.076404] Modules linked in:
> [    1.079483] Preemption disabled at:[    1.082820] [<  (null)>]   (null)
> [    1.086165] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.9.23-1-rc4 #13
> [    1.092723] Hardware name: Sigma Tango DT
> [    1.096765] [<c010f600>] (unwind_backtrace) from [<c010b568>] (show_stack+0x10/0x14)
> [    1.104558] [<c010b568>] (show_stack) from [<c0304830>] (dump_stack+0x98/0xc4)
> [    1.111823] [<c0304830>] (dump_stack) from [<c013eee0>] (__schedule_bug+0x94/0xec)
> [    1.119436] [<c013eee0>] (__schedule_bug) from [<c0516364>] (__schedule+0x4a4/0x5f0)
> [    1.127220] [<c0516364>] (__schedule) from [<c05164fc>] (schedule+0x4c/0xac)


And here you try and schedule with preemption disabled.

> [    1.134308] [<c05164fc>] (schedule) from [<c051b010>] (schedule_timeout+0x1f4/0x30c)
> [    1.142093] [<c051b010>] (schedule_timeout) from [<c051702c>] (wait_for_common+0x8c/0x13c)
> [    1.150401] [<c051702c>] (wait_for_common) from [<c05170ec>] (wait_for_completion+0x10/0x14)
> [    1.158886] [<c05170ec>] (wait_for_completion) from [<c01a0d74>] (__stop_cpus+0x50/0x64)
> [    1.167021] [<c01a0d74>] (__stop_cpus) from [<c01a1194>] (stop_cpus+0x30/0x48)
> [    1.174282] [<c01a1194>] (stop_cpus) from [<c01a1230>] (stop_machine+0x84/0x118)
> [    1.181719] [<c01a1230>] (stop_machine) from [<c034c070>] (smp8759_config_read+0x84/0x90)
> [    1.189942] [<c034c070>] (smp8759_config_read) from [<c0330a00>] (pci_bus_read_config_dword+0x6c/0x94)
> [    1.199301] [<c0330a00>] (pci_bus_read_config_dword) from [<c0332920>] (pci_bus_read_dev_vendor_id+0x24/0xe8)
> [    1.209270] [<c0332920>] (pci_bus_read_dev_vendor_id) from [<c033413c>] (pci_scan_single_device+0x40/0xb0)
> [    1.218977] [<c033413c>] (pci_scan_single_device) from [<c0334204>] (pci_scan_slot+0x58/0x100)
> [    1.227636] [<c0334204>] (pci_scan_slot) from [<c033511c>] (pci_scan_child_bus+0x20/0xf8)
> [    1.235858] [<c033511c>] (pci_scan_child_bus) from [<c03353ec>] (pci_scan_root_bus_msi+0xcc/0xd8)
> [    1.244779] [<c03353ec>] (pci_scan_root_bus_msi) from [<c0335410>] (pci_scan_root_bus+0x18/0x20)
> [    1.253612] [<c0335410>] (pci_scan_root_bus) from [<c034bc5c>] (pci_host_common_probe+0xc8/0x314)
> [    1.262533] [<c034bc5c>] (pci_host_common_probe) from [<c034c444>] (tango_pcie_probe+0x148/0x350)
> [    1.271455] [<c034c444>] (tango_pcie_probe) from [<c038dbc8>] (platform_drv_probe+0x34/0x6c)

> The panic call stack looks suspicious.
> 
> smp8759_config_read() never calls tango_check_pcie_link().
> 
> (I compile with -fno-optimize-sibling-calls to get more accurate
> call stacks.)
> 
> in_atomic_preempt_off is false before calling stop_machine()

Yes, but that's a pointless statement.

> I suppose I'm doing something wrong, but I'm not sure what yet.

Using stop_machine() is per definition doing it wrong ;-) But see above.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04  6:58         ` Jisheng Zhang
@ 2017-07-04  7:16           ` Jisheng Zhang
  2017-07-04  8:02           ` Ard Biesheuvel
  1 sibling, 0 replies; 41+ messages in thread
From: Jisheng Zhang @ 2017-07-04  7:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 4 Jul 2017 14:58:40 +0800 Jisheng Zhang wrote:

> On Mon, 3 Jul 2017 08:27:04 -0500 wrote:
> 
> > [+cc Jingoo, Joao]
> > 
> > On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:  
> > > On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:    
> > > > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:    
> > > >> This driver is required to work around several hardware bugs
> > > >> in the PCIe controller.
> > > >>
> > > >> NB: Revision 1 does not support legacy interrupts, or IO space.    
> > > >
> > > > I had to apply these manually because of conflicts in Kconfig and
> > > > Makefile.  What are these based on?  Easiest for me is if you base
> > > > them on the current -rc1 tag.
> > > >    
> > > >> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> > > >> ---
> > > >>  drivers/pci/host/Kconfig      |   8 +++
> > > >>  drivers/pci/host/Makefile     |   1 +
> > > >>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
> > > >>  include/linux/pci_ids.h       |   2 +
> > > >>  4 files changed, 175 insertions(+)
> > > >>  create mode 100644 drivers/pci/host/pcie-tango.c
> > > >>    
> > > [..]    
> > > >> +     /*
> > > >> +      * QUIRK #2
> > > >> +      * Unfortunately, config and mem spaces are muxed.
> > > >> +      * Linux does not support such a setting, since drivers are free
> > > >> +      * to access mem space directly, at any time.
> > > >> +      * Therefore, we can only PRAY that config and mem space accesses
> > > >> +      * NEVER occur concurrently.
> > > >> +      */
> > > >> +     writel_relaxed(1, pcie->mux);
> > > >> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
> > > >> +     writel_relaxed(0, pcie->mux);    
> > > >
> > > > I'm very hesitant about this.  When people stress this, we're going to
> > > > get reports of data corruption.  Even with the disclaimer below, I
> > > > don't feel good about this.  Adding the driver is an implicit claim
> > > > that we support the device, but we know it can't be made reliable.    
> > > 
> > > I noticed that the Synopsys driver suffers from a similar issue: in
> > > dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
> > > to perform a config space access, and switches it back to I/O space
> > > afterwards (unless it has more than 2 viewports, in which case it uses
> > > dedicated windows for I/O space and config space)    
> > 
> > That doesn't sound good.  Jingoo, Joao?  I remember some discussion
> > about this, but not the details.
> > 
> > I/O accesses use wrappers (inb(), etc), so there's at least the
> > possibility of a mutex to serialize them with respect to config
> > accesses.
> >   
> 
> IIRC, for 2 viewports, we don't need to worry about the config space
> access, because config space access is serialized by pci_lock; We
> do have race between config space and io space. But the accessing config
> space and io space at the same time is rare. And the PCIe EPs which
> has io space are rare too, supporting these EPs are not the potential
> target of those platforms with 2 viewports.
> 

PS: I think most platforms choose 2 pcie designware viewports just because
it's the default setting. And I have send a feature request to ASIC people
to increase the viewports to 3 for future marvell berlin SoCs.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04  6:58         ` Jisheng Zhang
  2017-07-04  7:16           ` Jisheng Zhang
@ 2017-07-04  8:02           ` Ard Biesheuvel
  2017-07-04  8:19             ` Jisheng Zhang
  1 sibling, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2017-07-04  8:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 4 July 2017 at 07:58, Jisheng Zhang <jszhang@marvell.com> wrote:
> On Mon, 3 Jul 2017 08:27:04 -0500 wrote:
>
>> [+cc Jingoo, Joao]
>>
>> On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:
>> > On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:
>> > > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
>> > >> This driver is required to work around several hardware bugs
>> > >> in the PCIe controller.
>> > >>
>> > >> NB: Revision 1 does not support legacy interrupts, or IO space.
>> > >
>> > > I had to apply these manually because of conflicts in Kconfig and
>> > > Makefile.  What are these based on?  Easiest for me is if you base
>> > > them on the current -rc1 tag.
>> > >
>> > >> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
>> > >> ---
>> > >>  drivers/pci/host/Kconfig      |   8 +++
>> > >>  drivers/pci/host/Makefile     |   1 +
>> > >>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
>> > >>  include/linux/pci_ids.h       |   2 +
>> > >>  4 files changed, 175 insertions(+)
>> > >>  create mode 100644 drivers/pci/host/pcie-tango.c
>> > >>
>> > [..]
>> > >> +     /*
>> > >> +      * QUIRK #2
>> > >> +      * Unfortunately, config and mem spaces are muxed.
>> > >> +      * Linux does not support such a setting, since drivers are free
>> > >> +      * to access mem space directly, at any time.
>> > >> +      * Therefore, we can only PRAY that config and mem space accesses
>> > >> +      * NEVER occur concurrently.
>> > >> +      */
>> > >> +     writel_relaxed(1, pcie->mux);
>> > >> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
>> > >> +     writel_relaxed(0, pcie->mux);
>> > >
>> > > I'm very hesitant about this.  When people stress this, we're going to
>> > > get reports of data corruption.  Even with the disclaimer below, I
>> > > don't feel good about this.  Adding the driver is an implicit claim
>> > > that we support the device, but we know it can't be made reliable.
>> >
>> > I noticed that the Synopsys driver suffers from a similar issue: in
>> > dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
>> > to perform a config space access, and switches it back to I/O space
>> > afterwards (unless it has more than 2 viewports, in which case it uses
>> > dedicated windows for I/O space and config space)
>>
>> That doesn't sound good.  Jingoo, Joao?  I remember some discussion
>> about this, but not the details.
>>
>> I/O accesses use wrappers (inb(), etc), so there's at least the
>> possibility of a mutex to serialize them with respect to config
>> accesses.
>>
>
> IIRC, for 2 viewports, we don't need to worry about the config space
> access, because config space access is serialized by pci_lock; We
> do have race between config space and io space. But the accessing config
> space and io space at the same time is rare.

Being 'rare' is not sufficient, unfortunately. In the current
situation, I/O space accesses may occur when the outbound window is
directed to the config space of a potentially completely unrelated
device. This is bad.

> And the PCIe EPs which
> has io space are rare too, supporting these EPs are not the potential
> target of those platforms with 2 viewports.
>

I am not sure EP mode is relevant here. What I do know is that boards
like the Marvell 8040 based MacchiatoBin uses this IP in RC mode, and
exposes config, MMIO and IO space windows using only 2 viewports. Note
that this is essentially a bug in the DT description, given that its
version of the IP supports 8 viewports. But the driver needs to be
fixed as well.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04  8:02           ` Ard Biesheuvel
@ 2017-07-04  8:19             ` Jisheng Zhang
  2017-07-04  9:38               ` Ard Biesheuvel
  0 siblings, 1 reply; 41+ messages in thread
From: Jisheng Zhang @ 2017-07-04  8:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 4 Jul 2017 09:02:06 +0100 Ard Biesheuvel wrote:

> On 4 July 2017 at 07:58, Jisheng Zhang <jszhang@marvell.com> wrote:
> > On Mon, 3 Jul 2017 08:27:04 -0500 wrote:
> >  
> >> [+cc Jingoo, Joao]
> >>
> >> On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:  
> >> > On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:  
> >> > > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:  
> >> > >> This driver is required to work around several hardware bugs
> >> > >> in the PCIe controller.
> >> > >>
> >> > >> NB: Revision 1 does not support legacy interrupts, or IO space.  
> >> > >
> >> > > I had to apply these manually because of conflicts in Kconfig and
> >> > > Makefile.  What are these based on?  Easiest for me is if you base
> >> > > them on the current -rc1 tag.
> >> > >  
> >> > >> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> >> > >> ---
> >> > >>  drivers/pci/host/Kconfig      |   8 +++
> >> > >>  drivers/pci/host/Makefile     |   1 +
> >> > >>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
> >> > >>  include/linux/pci_ids.h       |   2 +
> >> > >>  4 files changed, 175 insertions(+)
> >> > >>  create mode 100644 drivers/pci/host/pcie-tango.c
> >> > >>  
> >> > [..]  
> >> > >> +     /*
> >> > >> +      * QUIRK #2
> >> > >> +      * Unfortunately, config and mem spaces are muxed.
> >> > >> +      * Linux does not support such a setting, since drivers are free
> >> > >> +      * to access mem space directly, at any time.
> >> > >> +      * Therefore, we can only PRAY that config and mem space accesses
> >> > >> +      * NEVER occur concurrently.
> >> > >> +      */
> >> > >> +     writel_relaxed(1, pcie->mux);
> >> > >> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
> >> > >> +     writel_relaxed(0, pcie->mux);  
> >> > >
> >> > > I'm very hesitant about this.  When people stress this, we're going to
> >> > > get reports of data corruption.  Even with the disclaimer below, I
> >> > > don't feel good about this.  Adding the driver is an implicit claim
> >> > > that we support the device, but we know it can't be made reliable.  
> >> >
> >> > I noticed that the Synopsys driver suffers from a similar issue: in
> >> > dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
> >> > to perform a config space access, and switches it back to I/O space
> >> > afterwards (unless it has more than 2 viewports, in which case it uses
> >> > dedicated windows for I/O space and config space)  
> >>
> >> That doesn't sound good.  Jingoo, Joao?  I remember some discussion
> >> about this, but not the details.
> >>
> >> I/O accesses use wrappers (inb(), etc), so there's at least the
> >> possibility of a mutex to serialize them with respect to config
> >> accesses.
> >>  
> >
> > IIRC, for 2 viewports, we don't need to worry about the config space
> > access, because config space access is serialized by pci_lock; We
> > do have race between config space and io space. But the accessing config
> > space and io space at the same time is rare.  
> 
> Being 'rare' is not sufficient, unfortunately. In the current
> situation, I/O space accesses may occur when the outbound window is
> directed to the config space of a potentially completely unrelated
> device. This is bad.

Yep, I agree with you.

> 
> > And the PCIe EPs which
> > has io space are rare too, supporting these EPs are not the potential
> > target of those platforms with 2 viewports.
> >  
> 
> I am not sure EP mode is relevant here. What I do know is that boards

I mean those PCIe EP cards which have IO space, but that doesn't matter.

> like the Marvell 8040 based MacchiatoBin uses this IP in RC mode, and
> exposes config, MMIO and IO space windows using only 2 viewports. Note
> that this is essentially a bug in the DT description, given that its
> version of the IP supports 8 viewports. But the driver needs to be
> fixed as well.

To fix for 2 viewports situation, we need to serialize access of the io
and config space. In internal repo, we can achieve it by modifying the
io access helper functions such as inl/outl, but this won't be accepted
by the mainline IMHO. Except fixing the HW, any elegant solution?

Suggestions are appreciated.

Thanks,
Jisheng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04  8:19             ` Jisheng Zhang
@ 2017-07-04  9:38               ` Ard Biesheuvel
  2017-07-05 13:53                 ` Joao Pinto
  0 siblings, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2017-07-04  9:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 4 July 2017 at 09:19, Jisheng Zhang <jszhang@marvell.com> wrote:
> On Tue, 4 Jul 2017 09:02:06 +0100 Ard Biesheuvel wrote:
>
>> On 4 July 2017 at 07:58, Jisheng Zhang <jszhang@marvell.com> wrote:
>> > On Mon, 3 Jul 2017 08:27:04 -0500 wrote:
>> >
>> >> [+cc Jingoo, Joao]
>> >>
>> >> On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:
>> >> > On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:
>> >> > > On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
>> >> > >> This driver is required to work around several hardware bugs
>> >> > >> in the PCIe controller.
>> >> > >>
>> >> > >> NB: Revision 1 does not support legacy interrupts, or IO space.
>> >> > >
>> >> > > I had to apply these manually because of conflicts in Kconfig and
>> >> > > Makefile.  What are these based on?  Easiest for me is if you base
>> >> > > them on the current -rc1 tag.
>> >> > >
>> >> > >> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
>> >> > >> ---
>> >> > >>  drivers/pci/host/Kconfig      |   8 +++
>> >> > >>  drivers/pci/host/Makefile     |   1 +
>> >> > >>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
>> >> > >>  include/linux/pci_ids.h       |   2 +
>> >> > >>  4 files changed, 175 insertions(+)
>> >> > >>  create mode 100644 drivers/pci/host/pcie-tango.c
>> >> > >>
>> >> > [..]
>> >> > >> +     /*
>> >> > >> +      * QUIRK #2
>> >> > >> +      * Unfortunately, config and mem spaces are muxed.
>> >> > >> +      * Linux does not support such a setting, since drivers are free
>> >> > >> +      * to access mem space directly, at any time.
>> >> > >> +      * Therefore, we can only PRAY that config and mem space accesses
>> >> > >> +      * NEVER occur concurrently.
>> >> > >> +      */
>> >> > >> +     writel_relaxed(1, pcie->mux);
>> >> > >> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
>> >> > >> +     writel_relaxed(0, pcie->mux);
>> >> > >
>> >> > > I'm very hesitant about this.  When people stress this, we're going to
>> >> > > get reports of data corruption.  Even with the disclaimer below, I
>> >> > > don't feel good about this.  Adding the driver is an implicit claim
>> >> > > that we support the device, but we know it can't be made reliable.
>> >> >
>> >> > I noticed that the Synopsys driver suffers from a similar issue: in
>> >> > dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
>> >> > to perform a config space access, and switches it back to I/O space
>> >> > afterwards (unless it has more than 2 viewports, in which case it uses
>> >> > dedicated windows for I/O space and config space)
>> >>
>> >> That doesn't sound good.  Jingoo, Joao?  I remember some discussion
>> >> about this, but not the details.
>> >>
>> >> I/O accesses use wrappers (inb(), etc), so there's at least the
>> >> possibility of a mutex to serialize them with respect to config
>> >> accesses.
>> >>
>> >
>> > IIRC, for 2 viewports, we don't need to worry about the config space
>> > access, because config space access is serialized by pci_lock; We
>> > do have race between config space and io space. But the accessing config
>> > space and io space at the same time is rare.
>>
>> Being 'rare' is not sufficient, unfortunately. In the current
>> situation, I/O space accesses may occur when the outbound window is
>> directed to the config space of a potentially completely unrelated
>> device. This is bad.
>
> Yep, I agree with you.
>
>>
>> > And the PCIe EPs which
>> > has io space are rare too, supporting these EPs are not the potential
>> > target of those platforms with 2 viewports.
>> >
>>
>> I am not sure EP mode is relevant here. What I do know is that boards
>
> I mean those PCIe EP cards which have IO space, but that doesn't matter.
>

Ah, ok. But if such EP cards are so rare, why expose I/O space at all
if we cannot do it safely?

>> like the Marvell 8040 based MacchiatoBin uses this IP in RC mode, and
>> exposes config, MMIO and IO space windows using only 2 viewports. Note
>> that this is essentially a bug in the DT description, given that its
>> version of the IP supports 8 viewports. But the driver needs to be
>> fixed as well.
>
> To fix for 2 viewports situation, we need to serialize access of the io
> and config space. In internal repo, we can achieve it by modifying the
> io access helper functions such as inl/outl, but this won't be accepted
> by the mainline IMHO. Except fixing the HW, any elegant solution?
>
> Suggestions are appreciated.
>

I think the safe and upstreamable approach is to disable the I/O
window completely if num-viewports <= 2.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04  7:09           ` Peter Zijlstra
@ 2017-07-04 13:08             ` Mason
  2017-07-04 14:27               ` Peter Zijlstra
  0 siblings, 1 reply; 41+ messages in thread
From: Mason @ 2017-07-04 13:08 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/07/2017 09:09, Peter Zijlstra wrote:

> On Mon, Jul 03, 2017 at 05:30:28PM +0200, Marc Gonzalez wrote:
> 
>> And at the end of smp8759_config_read:
>>
>> 	printk("in_atomic_preempt_off = %d\n", in_atomic_preempt_off());
> 
> That's confused...

That much is certain. I am indeed grasping at straws.

I grepped "scheduling while atomic", found __schedule_bug()
in kernel/sched/core.c and saw

	if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) && in_atomic_preempt_off()) {
		pr_err("Preemption disabled at:");
		print_ip_sym(preempt_disable_ip);
		pr_cont("\n");
	}

I thought printing the value of in_atomic_preempt_off()
in the callback would indicate whether preemption had
already been turned off at that point.

It doesn't work like that?

BTW, why didn't print_ip_sym(preempt_disable_ip); say
where preemption had been disabled?


>> [    1.026568] BUG: scheduling while atomic: swapper/0/1/0x00000002
>> [    1.032625] 5 locks held by swapper/0/1:
>> [    1.036575]  #0:  (&dev->mutex){......}, at: [<c038c684>] __driver_attach+0x50/0xd0
>> [    1.044319]  #1:  (&dev->mutex){......}, at: [<c038c694>] __driver_attach+0x60/0xd0
>> [    1.052050]  #2:  (pci_lock){+.+...}, at: [<c03309d8>] pci_bus_read_config_dword+0x44/0x94
> 
> This is a raw_spinlock_t, that disables preemption

drivers/pci/access.c

/*
 * This interrupt-safe spinlock protects all accesses to PCI
 * configuration space.
 */
DEFINE_RAW_SPINLOCK(pci_lock);


	raw_spin_lock_irqsave(&pci_lock, flags);
	res = bus->ops->read(bus, devfn, pos, len, &data);


IIUC, it's not possible to call stop_machine() while holding
a raw spinlock? What about regular spinlocks? IIUC, in RT,
regular spinlocks may sleep?

I didn't find "preempt" or "schedul" in the spinlock doc.
https://www.kernel.org/doc/Documentation/locking/spinlocks.txt


> Using stop_machine() is per definition doing it wrong ;-)

Here's the high-level view. My HW is borked and muxes
config space and mem space. So I need a way to freeze
the entire system, make the config space access, and
then return the system to normal. (AFAICT, config space
accesses are rare, so if I kill performance for these
accesses, the system might remain usable.)

Is there a way to do this? Mark suggested stop_machine
but it seems using it in my situation is not quite
straight-forward.

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04 13:08             ` Mason
@ 2017-07-04 14:27               ` Peter Zijlstra
  2017-07-04 15:18                 ` Mason
  0 siblings, 1 reply; 41+ messages in thread
From: Peter Zijlstra @ 2017-07-04 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 04, 2017 at 03:08:43PM +0200, Mason wrote:
> On 04/07/2017 09:09, Peter Zijlstra wrote:
> 
> > On Mon, Jul 03, 2017 at 05:30:28PM +0200, Marc Gonzalez wrote:
> > 
> >> And at the end of smp8759_config_read:
> >>
> >> 	printk("in_atomic_preempt_off = %d\n", in_atomic_preempt_off());
> > 
> > That's confused...
> 
> That much is certain. I am indeed grasping at straws.
> 
> I grepped "scheduling while atomic", found __schedule_bug()
> in kernel/sched/core.c and saw
> 
> 	if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) && in_atomic_preempt_off()) {
> 		pr_err("Preemption disabled at:");
> 		print_ip_sym(preempt_disable_ip);
> 		pr_cont("\n");
> 	}
> 
> I thought printing the value of in_atomic_preempt_off()
> in the callback would indicate whether preemption had
> already been turned off at that point.

in_atomic_preempt_off() is a 'weird' construct. It basically checks to
see if preempt_count != 1. So calling it while holding a single preempt,
will return false (like in your case).

> It doesn't work like that?

Not really, you want to just print preempt_count.

> BTW, why didn't print_ip_sym(preempt_disable_ip); say
> where preemption had been disabled?

It does, but it might be non-obvious. We only store the first 0->!0
transition IP in there.

So if you have chains like:

	preempt_disable();		// 0 -> 1
	spin_lock();			// 1 -> 2
	preempt_enable();		// 2 -> 1
	preempt_disable();		// 1 -> 2
	spin_unlock();			// 2 -> 1

	mutex_lock();
	  might_sleep();		*SPLAT* report the IP of 0 -> 1

	preempt_enable():		// 1 -> 0


That IP might not even be part of the current callchain.

> >> [    1.026568] BUG: scheduling while atomic: swapper/0/1/0x00000002
> >> [    1.032625] 5 locks held by swapper/0/1:
> >> [    1.036575]  #0:  (&dev->mutex){......}, at: [<c038c684>] __driver_attach+0x50/0xd0
> >> [    1.044319]  #1:  (&dev->mutex){......}, at: [<c038c694>] __driver_attach+0x60/0xd0
> >> [    1.052050]  #2:  (pci_lock){+.+...}, at: [<c03309d8>] pci_bus_read_config_dword+0x44/0x94
> > 
> > This is a raw_spinlock_t, that disables preemption
> 
> drivers/pci/access.c
> 
> /*
>  * This interrupt-safe spinlock protects all accesses to PCI
>  * configuration space.
>  */
> DEFINE_RAW_SPINLOCK(pci_lock);
> 
> 
> 	raw_spin_lock_irqsave(&pci_lock, flags);
> 	res = bus->ops->read(bus, devfn, pos, len, &data);
> 
> 
> IIUC, it's not possible to call stop_machine() while holding
> a raw spinlock?

Correct. You cannot call blocking primitives while holding a spinlock.

> What about regular spinlocks? IIUC, in RT,
> regular spinlocks may sleep?

Still not, your code should not depend on CONFIG_PREEMPT*.

> I didn't find "preempt" or "schedul" in the spinlock doc.
> https://www.kernel.org/doc/Documentation/locking/spinlocks.txt

Correct... as per usual the documentation is somewhat terse.

But once you think about it, its 'obvious' a spinlock needs to disable
preemption. If you don't you get into heaps of trouble (one of the
reasons userspace spinlocks are an absolute trainwreck).

> > Using stop_machine() is per definition doing it wrong ;-)
> 
> Here's the high-level view. My HW is borked and muxes
> config space and mem space. So I need a way to freeze
> the entire system, make the config space access, and
> then return the system to normal. (AFAICT, config space
> accesses are rare, so if I kill performance for these
> accesses, the system might remain usable.)
> 
> Is there a way to do this? Mark suggested stop_machine
> but it seems using it in my situation is not quite
> straight-forward.

*groan*... so yeah, broken hardware demands crazy stuff... stop machine
is tricky here because I'm not sure we can demand all PCI accessors to
allow sleeping.

And given that PCI lock is irqsave, we can't even assume IRQs are
enabled.

Does your platform have NMIs? If so, you can do yuck things like the
kgdb sync. NMI IPI all other CPUs and have them spin-wait on your state.

Then be careful not to deadlock when two CPUs do that concurrently.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 18:11         ` Russell King - ARM Linux
  2017-07-03 18:44           ` Ard Biesheuvel
@ 2017-07-04 15:15           ` Bjorn Helgaas
  2017-07-04 18:17             ` Russell King - ARM Linux
  2017-07-04 23:59           ` Mason
  2 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-04 15:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 03, 2017 at 07:11:28PM +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 03, 2017 at 08:40:31AM -0500, Bjorn Helgaas wrote:
> > The problem is serializing vs. memory accesses, since they don't use
> > any wrappers.  However, they are ioremapped(), so it's at least
> > conceivable that another solution would be to use VM to trap those
> > accesses.  I'm not a VM person, so I don't know whether that's
> > feasible in Linux.
> 
> Bjorn,
> 
> You're forgetting that MMIO (iow, memory returned by ioremap()) must
> be accessed through the appropriate accessors, and must not be
> directly dereferenced in C.  (We do have buggy drivers that do that
> but they are buggy, and in many cases are getting attention to fix
> that.)

Oh, you're right, thank you!  I guess you're referring to readb()
and friends.  I haven't found an actual prohibition on directly
dereferencing addresses returned from ioremap(), but
Documentation/driver-api/device-io.rst is clear that they're
suitable for passing to readb(), etc.

I recently told someone else my mistaken idea that ioremap() must
return a valid virtual address.  I wish I remembered who it was, so I
could correct that.  Documentation/DMA-API-HOWTO.txt also suggests
that ioremap() returns a virtual address -- I think I wrote that, and
maybe that virtual address reference should be tweaked a bit.

Another wrinkle is that the pci_mmap_resource() interface is exposed
via sysfs and allows direct userspace mmap of PCI MMIO resources.  In
that case, there is no accessor available.  I wonder if we need some
way to disable this mmap when readb() is non-trivial.

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04 14:27               ` Peter Zijlstra
@ 2017-07-04 15:18                 ` Mason
  0 siblings, 0 replies; 41+ messages in thread
From: Mason @ 2017-07-04 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/07/2017 16:27, Peter Zijlstra wrote:

> Mason wrote:
>
>> 	if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) && in_atomic_preempt_off()) {
>> 		pr_err("Preemption disabled at:");
>> 		print_ip_sym(preempt_disable_ip);
>> 		pr_cont("\n");
>> 	}
>>
>> BTW, why didn't print_ip_sym(preempt_disable_ip); say
>> where preemption had been disabled?
> 
> It does, but it might be non-obvious. We only store the first 0->!0
> transition IP in there.

The output was:

[    1.079483] Preemption disabled at:[    1.082820] [<  (null)>]   (null)

so preempt_disable_ip was NULL, right?

Has it been already clobbered?


>> Here's the high-level view. My HW is borked and muxes
>> config space and mem space. So I need a way to freeze
>> the entire system, make the config space access, and
>> then return the system to normal. (AFAICT, config space
>> accesses are rare, so if I kill performance for these
>> accesses, the system might remain usable.)
>>
>> Is there a way to do this? Mark suggested stop_machine
>> but it seems using it in my situation is not quite
>> straight-forward.
> 
> *groan*... so yeah, broken hardware demands crazy stuff... stop machine
> is tricky here because I'm not sure we can demand all PCI accessors to
> allow sleeping.
> 
> And given that PCI lock is irqsave, we can't even assume IRQs are
> enabled.
> 
> Does your platform have NMIs? If so, you can do yuck things like the
> kgdb sync. NMI IPI all other CPUs and have them spin-wait on your state.
> 
> Then be careful not to deadlock when two CPUs do that concurrently.

My platform is arch/arm/mach-tango (Cortex A9, ARMv7-A)

This looks similar to what you described:
https://www.linaro.org/blog/core-dump/debugging-arm-kernels-using-nmifiq/
(I CCed Daniel Thompson)

Quote article:

> Note: On ARMv7-A devices that have security extensions (TrustZone)
> FIQ can only be used by the kernel if it is possible to run Linux in
> secure mode. It is therefore not possible to exploit FIQ for
> debugging and run a secure monitor simultaneously. At the end of this
> blog post we will discuss potential future work to mitigate this
> problem.

On my platform, Linux runs in non-secure mode...

Sounds like I don't have many options left for this driver :-(

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 14:34         ` Marc Gonzalez
@ 2017-07-04 15:58           ` Bjorn Helgaas
  2017-07-04 23:42             ` Mason
  0 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-04 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 03, 2017 at 04:34:29PM +0200, Marc Gonzalez wrote:
> Bjorn Helgaas wrote:
> 
> > Marc Gonzalez wrote:
> >
> >> On 03/07/2017 01:18, Bjorn Helgaas wrote:
> >>
> >>> On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
> >>>
> >>>> +static int tango_check_pcie_link(void __iomem *test_out)
> >>>
> >>> I think this is checking for link up.  Rename to tango_pcie_link_up()
> >>> to follow the convention of other drivers.  Take a struct tango_pcie *
> >>> instead of an address, if possible.
> >>
> >> Anything's possible. NB: if I pass the struct, then I have to store
> >> the address in the struct, which isn't the case now, since I never
> >> need the address later. If you don't mind adding an unnecessary
> >> field to the struct, I can do it. What do you say?
> > 
> > The benefit of following the same formula as other drivers is pretty
> > large.  Most drivers save the equivalent of "base" in the struct.  If
> > you did that, you wouldn't need an extra pointer; you would just use
> > "base + SMP8759_MUX" in the config accessors and "base + SMP8759_TEST_OUT"
> > in tango_pcie_link_up().
> 
> The problem is that TEST_OUT is at 0x74 on SMP8759, but at 0x138
> on my other chip. In fact, all registers have been "reshuffled",
> and none have the same offsets on the two chips.
> 
> My solution was to define specific registers in the struct.
> 
> In my [RFC PATCH v0.2] posted March 23, I tried illustrating
> the issue:
> 
> +static const struct of_device_id tango_pcie_ids[] = {
> +	{ .compatible = "sigma,smp8759-pcie" },
> +	{ .compatible = "sigma,rev2-pcie" },
> +	{ /* sentinel */ },
> +};
> +
> +static void smp8759_init(struct tango_pcie *pcie, void __iomem *base)
> +{
> +	pcie->mux		= base + 0x48;
> +	pcie->msi_status	= base + 0x80;
> +	pcie->msi_mask		= base + 0xa0;
> +	pcie->msi_doorbell	= 0xa0000000 + 0x2e07c;
> +}
> +
> +static void rev2_init(struct tango_pcie *pcie, void __iomem *base)
> +{
> +	void __iomem *misc_irq	= base + 0x40;
> +	void __iomem *doorbell	= base + 0x8c;
> +
> +	pcie->mux		= base + 0x2c;
> +	pcie->msi_status	= base + 0x4c;
> +	pcie->msi_mask		= base + 0x6c;
> +	pcie->msi_doorbell	= 0x80000000;
> +
> +	writel(lower_32_bits(pcie->msi_doorbell), doorbell + 0);
> +	writel(upper_32_bits(pcie->msi_doorbell), doorbell + 4);
> +
> +	/* Enable legacy PCI interrupts */
> +	writel(BIT(15), misc_irq);
> +	writel(0xf << 4, misc_irq + 4);
> +}
> 
> 
> Do you agree that the 'base + OFFSET' idiom does not work in
> this specific situation? Would you handle it differently?

It's definitely a hassle to support chips with different register
layouts.  Your hardware guys are really making your life hard :)

drivers/pci/host/pcie-iproc.c is one strategy.  It has
iproc_pcie_reg_paxb[] and iproc_pcie_reg_paxb_v2[] with register
offsets for different chip versions.

It saves a table of register offsets per controller, which is similar
to saving a set of pointers per controller.  Saving the pointers as
you suggest above is marginally more storage but probably easier to
read.

If the chips are fundamentally different, i.e., if they *operate*
differently in addition to having a different register layout, you
could make two separate drivers.

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04 15:15           ` Bjorn Helgaas
@ 2017-07-04 18:17             ` Russell King - ARM Linux
  0 siblings, 0 replies; 41+ messages in thread
From: Russell King - ARM Linux @ 2017-07-04 18:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 04, 2017 at 10:15:02AM -0500, Bjorn Helgaas wrote:
> On Mon, Jul 03, 2017 at 07:11:28PM +0100, Russell King - ARM Linux wrote:
> > On Mon, Jul 03, 2017 at 08:40:31AM -0500, Bjorn Helgaas wrote:
> > > The problem is serializing vs. memory accesses, since they don't use
> > > any wrappers.  However, they are ioremapped(), so it's at least
> > > conceivable that another solution would be to use VM to trap those
> > > accesses.  I'm not a VM person, so I don't know whether that's
> > > feasible in Linux.
> > 
> > Bjorn,
> > 
> > You're forgetting that MMIO (iow, memory returned by ioremap()) must
> > be accessed through the appropriate accessors, and must not be
> > directly dereferenced in C.  (We do have buggy drivers that do that
> > but they are buggy, and in many cases are getting attention to fix
> > that.)
> 
> Oh, you're right, thank you!  I guess you're referring to readb()
> and friends.  I haven't found an actual prohibition on directly
> dereferencing addresses returned from ioremap(), but
> Documentation/driver-api/device-io.rst is clear that they're
> suitable for passing to readb(), etc.

There was a strong suggestion years ago that what is returned from
ioremap() is a cookie that must not be dereferenced by drivers, and
that there was a suggestion that having ioremap() return the virtual
address with an offset (which read*() and friends would undo) would
be a good idea.  However, even back then, we had some cases where
drivers would directly dereference the pointer.  We have sparse today
which helps point these places out (provided drivers stay away from
__force, but unfortunately, I think we've ended up with people who
think that silencing sparse warnings with __force is more preferable
than leaving them there to point out where things are actually wrong.)

So, imho, unfortunately sparse has lost its usefulness in this regard.

> I recently told someone else my mistaken idea that ioremap() must
> return a valid virtual address.  I wish I remembered who it was, so I
> could correct that.  Documentation/DMA-API-HOWTO.txt also suggests
> that ioremap() returns a virtual address -- I think I wrote that, and
> maybe that virtual address reference should be tweaked a bit.

For most implementations, ioremap() does indeed return a virtual address,
but that was never how the API was defined in the first place - it was
always referred to as returning a cookie.

> Another wrinkle is that the pci_mmap_resource() interface is exposed
> via sysfs and allows direct userspace mmap of PCI MMIO resources.  In
> that case, there is no accessor available.  I wonder if we need some
> way to disable this mmap when readb() is non-trivial.

Hmm, no comment, except that while the PCI MMIO space is available to
userspace, and userspace is capable of running that thread on any CPU,
PCI MMIO space can't be switched to config space.

That's another nail in this coffin...

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-06-20  8:12 [PATCH v9 0/3] Tango PCIe controller support Marc Gonzalez
                   ` (2 preceding siblings ...)
  2017-06-20  8:18 ` [PATCH v9 3/3] PCI: Add tango MSI controller support Marc Gonzalez
@ 2017-07-04 20:24 ` Bjorn Helgaas
  2017-07-04 22:55   ` Mason
  3 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-04 20:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jun 20, 2017 at 10:12:57AM +0200, Marc Gonzalez wrote:
> Marc Z pointed out that posting partial series is not ideal.
> Collect last-minute fixups into a single patch series.
> 
> - Bump series to v9 to avoid any ambiguity
> - Add Rob's Ack on patch 1
> 
> Marc Gonzalez (3):
>   PCI: Add DT binding for tango PCIe controller
>   PCI: Add tango PCIe host bridge support
>   PCI: Add tango MSI controller support
> 
>  .../devicetree/bindings/pci/tango-pcie.txt         |  29 ++
>  drivers/pci/host/Kconfig                           |   8 +
>  drivers/pci/host/Makefile                          |   1 +
>  drivers/pci/host/pcie-tango.c                      | 390 +++++++++++++++++++++
>  include/linux/pci_ids.h                            |   2 +
>  5 files changed, 430 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/tango-pcie.txt
>  create mode 100644 drivers/pci/host/pcie-tango.c

I made the trivial changes I mentioned, added a dependency on
CONFIG_BROKEN (for the config/MMIO muxing issue), and put these on
pci/host-tango.  I can't build or test this, so I probably broke
something in the process.  I think the combination of the boot-time
warning, the taint, and CONFIG_BROKEN is a reasonable amount of
warning that a user should expect issues.

Can you take a look and see if it works for you?

https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-tango

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-04 20:24 ` [PATCH v9 0/3] Tango PCIe " Bjorn Helgaas
@ 2017-07-04 22:55   ` Mason
  2017-07-05 18:03     ` Bjorn Helgaas
  0 siblings, 1 reply; 41+ messages in thread
From: Mason @ 2017-07-04 22:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/07/2017 22:24, Bjorn Helgaas wrote:

> On Tue, Jun 20, 2017 at 10:12:57AM +0200, Marc Gonzalez wrote:
>
>> Marc Z pointed out that posting partial series is not ideal.
>> Collect last-minute fixups into a single patch series.
>>
>> - Bump series to v9 to avoid any ambiguity
>> - Add Rob's Ack on patch 1
>>
>> Marc Gonzalez (3):
>>   PCI: Add DT binding for tango PCIe controller
>>   PCI: Add tango PCIe host bridge support
>>   PCI: Add tango MSI controller support
>>
>>  .../devicetree/bindings/pci/tango-pcie.txt         |  29 ++
>>  drivers/pci/host/Kconfig                           |   8 +
>>  drivers/pci/host/Makefile                          |   1 +
>>  drivers/pci/host/pcie-tango.c                      | 390 +++++++++++++++++++++
>>  include/linux/pci_ids.h                            |   2 +
>>  5 files changed, 430 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pci/tango-pcie.txt
>>  create mode 100644 drivers/pci/host/pcie-tango.c
> 
> I made the trivial changes I mentioned, added a dependency on
> CONFIG_BROKEN (for the config/MMIO muxing issue), and put these on
> pci/host-tango.  I can't build or test this, so I probably broke
> something in the process.  I think the combination of the boot-time
> warning, the taint, and CONFIG_BROKEN is a reasonable amount of
> warning that a user should expect issues.
> 
> Can you take a look and see if it works for you?
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-tango

Thanks. I'll take it for a spin ASAP.

TAINT_CRAP... Smirk. I didn't see that one in the docs:
https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html

Oh wait... TAINT_CRAP is "C" => a staging driver has been loaded

The one issue I anticipate with "depends on BROKEN" is
when I add support for revision 2, which isn't broken.

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04 15:58           ` Bjorn Helgaas
@ 2017-07-04 23:42             ` Mason
  0 siblings, 0 replies; 41+ messages in thread
From: Mason @ 2017-07-04 23:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/07/2017 17:58, Bjorn Helgaas wrote:

> It's definitely a hassle to support chips with different register
> layouts.  Your hardware guys are really making your life hard :)

Now where did I put my foam bat...

> If the chips are fundamentally different, i.e., if they *operate*
> differently in addition to having a different register layout, you
> could make two separate drivers.

It's the exact same underlying IP. Revision 2 is only a
bug fix rev. IIUC, some of the fixes lead to adding a
register here, removing a register there... and I don't
think the HW dev ever considered the pain of supporting
both revs within a single driver.

This dual support explains some of the peculiarities
you noted in my submission.

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-03 18:11         ` Russell King - ARM Linux
  2017-07-03 18:44           ` Ard Biesheuvel
  2017-07-04 15:15           ` Bjorn Helgaas
@ 2017-07-04 23:59           ` Mason
  2017-07-05  5:21             ` Greg Kroah-Hartman
  2017-07-05 12:33             ` Mark Brown
  2 siblings, 2 replies; 41+ messages in thread
From: Mason @ 2017-07-04 23:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/07/2017 20:11, Russell King - ARM Linux wrote:

> I don't think there's an easy solution to this problem - and I'm not
> sure that stop_machine() can be made to work in this path (which
> needs a process context).  I have a suspicion that the Sigma Designs
> PCI implementation is just soo insane that it's never going to work
> reliably in a multi-SoC kernel without introducing severe performance
> issues for everyone else.

If I remember correctly, this is the second HW block from
tango that has been deemed "too insane for Linux".

The first one was the DMA engine, which doesn't interrupt
when a transfer is done, but when a new transfer may be
programmed. (Though there is a simple work-around for
this one, if we give up command pipelining.)

Do larger SoC vendors have HW devs working closely with
Linux devs, to avoid these design bloopers?

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04 23:59           ` Mason
@ 2017-07-05  5:21             ` Greg Kroah-Hartman
  2017-07-05 12:33             ` Mark Brown
  1 sibling, 0 replies; 41+ messages in thread
From: Greg Kroah-Hartman @ 2017-07-05  5:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 05, 2017 at 01:59:55AM +0200, Mason wrote:
> Do larger SoC vendors have HW devs working closely with
> Linux devs, to avoid these design bloopers?

Yes they generally do, as they have learned from their prior mistakes :)

good luck!

greg k-h

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04 23:59           ` Mason
  2017-07-05  5:21             ` Greg Kroah-Hartman
@ 2017-07-05 12:33             ` Mark Brown
  1 sibling, 0 replies; 41+ messages in thread
From: Mark Brown @ 2017-07-05 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 05, 2017 at 01:59:55AM +0200, Mason wrote:

> Do larger SoC vendors have HW devs working closely with
> Linux devs, to avoid these design bloopers?

Yes, or just internal software teams in general - hardware designs tend
to be a lot more usable if there's good dialogue with users about what's
useful and what isn't.  It's going to happen at some point anyway when
people can't get the chip working well.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170705/c86058d6/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 2/3] PCI: Add tango PCIe host bridge support
  2017-07-04  9:38               ` Ard Biesheuvel
@ 2017-07-05 13:53                 ` Joao Pinto
  0 siblings, 0 replies; 41+ messages in thread
From: Joao Pinto @ 2017-07-05 13:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi to all,

?s 10:38 AM de 7/4/2017, Ard Biesheuvel escreveu:
> On 4 July 2017 at 09:19, Jisheng Zhang <jszhang@marvell.com> wrote:
>> On Tue, 4 Jul 2017 09:02:06 +0100 Ard Biesheuvel wrote:
>>
>>> On 4 July 2017 at 07:58, Jisheng Zhang <jszhang@marvell.com> wrote:
>>>> On Mon, 3 Jul 2017 08:27:04 -0500 wrote:
>>>>
>>>>> [+cc Jingoo, Joao]
>>>>>
>>>>> On Mon, Jul 03, 2017 at 10:35:50AM +0100, Ard Biesheuvel wrote:
>>>>>> On 3 July 2017 at 00:18, Bjorn Helgaas <helgaas@kernel.org> wrote:
>>>>>>> On Tue, Jun 20, 2017 at 10:17:40AM +0200, Marc Gonzalez wrote:
>>>>>>>> This driver is required to work around several hardware bugs
>>>>>>>> in the PCIe controller.
>>>>>>>>
>>>>>>>> NB: Revision 1 does not support legacy interrupts, or IO space.
>>>>>>>
>>>>>>> I had to apply these manually because of conflicts in Kconfig and
>>>>>>> Makefile.  What are these based on?  Easiest for me is if you base
>>>>>>> them on the current -rc1 tag.
>>>>>>>
>>>>>>>> Signed-off-by: Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
>>>>>>>> ---
>>>>>>>>  drivers/pci/host/Kconfig      |   8 +++
>>>>>>>>  drivers/pci/host/Makefile     |   1 +
>>>>>>>>  drivers/pci/host/pcie-tango.c | 164 ++++++++++++++++++++++++++++++++++++++++++
>>>>>>>>  include/linux/pci_ids.h       |   2 +
>>>>>>>>  4 files changed, 175 insertions(+)
>>>>>>>>  create mode 100644 drivers/pci/host/pcie-tango.c
>>>>>>>>
>>>>>> [..]
>>>>>>>> +     /*
>>>>>>>> +      * QUIRK #2
>>>>>>>> +      * Unfortunately, config and mem spaces are muxed.
>>>>>>>> +      * Linux does not support such a setting, since drivers are free
>>>>>>>> +      * to access mem space directly, at any time.
>>>>>>>> +      * Therefore, we can only PRAY that config and mem space accesses
>>>>>>>> +      * NEVER occur concurrently.
>>>>>>>> +      */
>>>>>>>> +     writel_relaxed(1, pcie->mux);
>>>>>>>> +     ret = pci_generic_config_read(bus, devfn, where, size, val);
>>>>>>>> +     writel_relaxed(0, pcie->mux);
>>>>>>>
>>>>>>> I'm very hesitant about this.  When people stress this, we're going to
>>>>>>> get reports of data corruption.  Even with the disclaimer below, I
>>>>>>> don't feel good about this.  Adding the driver is an implicit claim
>>>>>>> that we support the device, but we know it can't be made reliable.
>>>>>>
>>>>>> I noticed that the Synopsys driver suffers from a similar issue: in
>>>>>> dw_pcie_rd_other_conf(), it happily reprograms the outbound I/O window
>>>>>> to perform a config space access, and switches it back to I/O space
>>>>>> afterwards (unless it has more than 2 viewports, in which case it uses
>>>>>> dedicated windows for I/O space and config space)
>>>>>
>>>>> That doesn't sound good.  Jingoo, Joao?  I remember some discussion
>>>>> about this, but not the details.
>>>>>
>>>>> I/O accesses use wrappers (inb(), etc), so there's at least the
>>>>> possibility of a mutex to serialize them with respect to config
>>>>> accesses.
>>>>>
>>>>
>>>> IIRC, for 2 viewports, we don't need to worry about the config space
>>>> access, because config space access is serialized by pci_lock; We
>>>> do have race between config space and io space. But the accessing config
>>>> space and io space at the same time is rare.
>>>
>>> Being 'rare' is not sufficient, unfortunately. In the current
>>> situation, I/O space accesses may occur when the outbound window is
>>> directed to the config space of a potentially completely unrelated
>>> device. This is bad.
>>
>> Yep, I agree with you.
>>
>>>
>>>> And the PCIe EPs which
>>>> has io space are rare too, supporting these EPs are not the potential
>>>> target of those platforms with 2 viewports.
>>>>
>>>
>>> I am not sure EP mode is relevant here. What I do know is that boards
>>
>> I mean those PCIe EP cards which have IO space, but that doesn't matter.
>>
> 
> Ah, ok. But if such EP cards are so rare, why expose I/O space at all
> if we cannot do it safely?
> 
>>> like the Marvell 8040 based MacchiatoBin uses this IP in RC mode, and
>>> exposes config, MMIO and IO space windows using only 2 viewports. Note
>>> that this is essentially a bug in the DT description, given that its
>>> version of the IP supports 8 viewports. But the driver needs to be
>>> fixed as well.
>>
>> To fix for 2 viewports situation, we need to serialize access of the io
>> and config space. In internal repo, we can achieve it by modifying the
>> io access helper functions such as inl/outl, but this won't be accepted
>> by the mainline IMHO. Except fixing the HW, any elegant solution?
>>
>> Suggestions are appreciated.
>>
> 
> I think the safe and upstreamable approach is to disable the I/O
> window completely if num-viewports <= 2.
> 

I think that the critical case is when we are using a single ATU region, and
that has to managed by software. The hardware is not capable of managing racing
conditions, like programming the ATU while still transfering data, so problems
can ocurre for sure. In this case we should be able to add to the driver a
simple lock to signal that the ATU is being used. If the ATU was being used we
could make a spinlock for example. Would this acceptable in your opinion? The
problem is when we are transfering data. Are we able to know that data is being
processed?

When using a single region, when we access the config mem, we have to stop all
data transfers, reprogram the ATU to handle the config access, do the config
read/write, put the region "back" and restart the data transfer.

When using 2 or more regions, we can separate the scopes and the data transfers
does not need to be stopped. The race problem is harder to ocurre.

Thanks,
Joao

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-04 22:55   ` Mason
@ 2017-07-05 18:03     ` Bjorn Helgaas
  2017-07-05 20:39       ` Mason
  0 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-05 18:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 05, 2017 at 12:55:37AM +0200, Mason wrote:
> On 04/07/2017 22:24, Bjorn Helgaas wrote:
> 
> > On Tue, Jun 20, 2017 at 10:12:57AM +0200, Marc Gonzalez wrote:
> >
> >> Marc Z pointed out that posting partial series is not ideal.
> >> Collect last-minute fixups into a single patch series.
> >>
> >> - Bump series to v9 to avoid any ambiguity
> >> - Add Rob's Ack on patch 1
> >>
> >> Marc Gonzalez (3):
> >>   PCI: Add DT binding for tango PCIe controller
> >>   PCI: Add tango PCIe host bridge support
> >>   PCI: Add tango MSI controller support
> >>
> >>  .../devicetree/bindings/pci/tango-pcie.txt         |  29 ++
> >>  drivers/pci/host/Kconfig                           |   8 +
> >>  drivers/pci/host/Makefile                          |   1 +
> >>  drivers/pci/host/pcie-tango.c                      | 390 +++++++++++++++++++++
> >>  include/linux/pci_ids.h                            |   2 +
> >>  5 files changed, 430 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/pci/tango-pcie.txt
> >>  create mode 100644 drivers/pci/host/pcie-tango.c
> > 
> > I made the trivial changes I mentioned, added a dependency on
> > CONFIG_BROKEN (for the config/MMIO muxing issue), and put these on
> > pci/host-tango.  I can't build or test this, so I probably broke
> > something in the process.  I think the combination of the boot-time
> > warning, the taint, and CONFIG_BROKEN is a reasonable amount of
> > warning that a user should expect issues.
> > 
> > Can you take a look and see if it works for you?
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-tango
> 
> Thanks. I'll take it for a spin ASAP.
> 
> TAINT_CRAP... Smirk. I didn't see that one in the docs:
> https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html
> 
> Oh wait... TAINT_CRAP is "C" => a staging driver has been loaded

I wish it had a less pejorative, more descriptive name.  But it seems like
the closest to this situation.

> The one issue I anticipate with "depends on BROKEN" is
> when I add support for revision 2, which isn't broken.

How about this:

  - Rename PCIE_TANGO to PCIE_TANGO_REV1
  - PCIE_TANGO_REV1 depends on BROKEN
  - Add rev2 support later, enabled by PCIE_TANGO
  - PCIE_TANGO_REV1 depends on PCIE_TANGO && BROKEN

I updated pci/host-tango along these lines (without rev2 support,
obviously).

I forgot to ask for a MAINTAINERS update.  Can you send that, too,
please?

Which reminds me -- are these two addreses

  Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
  Mason <slash.tmp@free.fr>

different names for the same person?  Conversations are easier for me
if I can keep who's who straight :)

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-05 18:03     ` Bjorn Helgaas
@ 2017-07-05 20:39       ` Mason
  2017-07-05 21:34         ` Bjorn Helgaas
  0 siblings, 1 reply; 41+ messages in thread
From: Mason @ 2017-07-05 20:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/07/2017 20:03, Bjorn Helgaas wrote:

> On Wed, Jul 05, 2017 at 12:55:37AM +0200, Mason wrote:
>
>> On 04/07/2017 22:24, Bjorn Helgaas wrote:
>>
>>> I made the trivial changes I mentioned, added a dependency on
>>> CONFIG_BROKEN (for the config/MMIO muxing issue), and put these on
>>> pci/host-tango.  I can't build or test this, so I probably broke
>>> something in the process.  I think the combination of the boot-time
>>> warning, the taint, and CONFIG_BROKEN is a reasonable amount of
>>> warning that a user should expect issues.
>>>
>>> Can you take a look and see if it works for you?
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-tango
>>
>> Thanks. I'll take it for a spin ASAP.
>>
>> TAINT_CRAP... Smirk. I didn't see that one in the docs:
>> https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html
>>
>> Oh wait... TAINT_CRAP is "C" => a staging driver has been loaded
> 
> I wish it had a less pejorative, more descriptive name.  But it seems like
> the closest to this situation.

Maybe it is not too late to submit a patch to Linus
renaming TAINT_CRAP?

Here are a few candidates, off the top of my head:

TAINT_STAGING
TAINT_STAGING_DRIVER
TAINT_BROKEN_HW
TAINT_BROKEN_HARDWARE
TAINT_USE_AT_YOUR_OWN_RISK

>> The one issue I anticipate with "depends on BROKEN" is
>> when I add support for revision 2, which isn't broken.
> 
> How about this:
> 
>   - Rename PCIE_TANGO to PCIE_TANGO_REV1
>   - PCIE_TANGO_REV1 depends on BROKEN
>   - Add rev2 support later, enabled by PCIE_TANGO
>   - PCIE_TANGO_REV1 depends on PCIE_TANGO && BROKEN
> 
> I updated pci/host-tango along these lines (without rev2 support,
> obviously).

And support for REV1 wouldn't be compiled in, unless
BROKEN is selected? Yes, I think that could fly.

Don't you think the naming should follow the DT
convention of using the first SoC embedding the
IP (for the compatible string) ?

PCIE_TANGO_REV1 vs PCIE_TANGO_SMP8759

> I forgot to ask for a MAINTAINERS update.  Can you send that, too,
> please?

There's a "catch-all" rule for everything tango-related:

ARM/TANGO ARCHITECTURE
M:	Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
L:	linux-arm-kernel at lists.infradead.org
S:	Maintained
N:	tango

Is that enough?

> Which reminds me -- are these two addreses
> 
>   Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
>   Mason <slash.tmp@free.fr>
> 
> different names for the same person?  Conversations are easier for me
> if I can keep who's who straight :)

Well, there are many voices inside my head, but yes,
respectively professional and personal addresses.

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-05 20:39       ` Mason
@ 2017-07-05 21:34         ` Bjorn Helgaas
  2017-07-05 21:59           ` Mason
  0 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-05 21:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 05, 2017 at 10:39:19PM +0200, Mason wrote:
> On 05/07/2017 20:03, Bjorn Helgaas wrote:
> 
> > On Wed, Jul 05, 2017 at 12:55:37AM +0200, Mason wrote:
> >
> >> On 04/07/2017 22:24, Bjorn Helgaas wrote:
> >>
> >>> I made the trivial changes I mentioned, added a dependency on
> >>> CONFIG_BROKEN (for the config/MMIO muxing issue), and put these on
> >>> pci/host-tango.  I can't build or test this, so I probably broke
> >>> something in the process.  I think the combination of the boot-time
> >>> warning, the taint, and CONFIG_BROKEN is a reasonable amount of
> >>> warning that a user should expect issues.
> >>>
> >>> Can you take a look and see if it works for you?
> >>>
> >>> https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-tango
> >>
> >> Thanks. I'll take it for a spin ASAP.
> >>
> >> TAINT_CRAP... Smirk. I didn't see that one in the docs:
> >> https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html
> >>
> >> Oh wait... TAINT_CRAP is "C" => a staging driver has been loaded
> > 
> > I wish it had a less pejorative, more descriptive name.  But it seems like
> > the closest to this situation.
> 
> Maybe it is not too late to submit a patch to Linus
> renaming TAINT_CRAP?
> 
> Here are a few candidates, off the top of my head:
> 
> TAINT_STAGING
> TAINT_STAGING_DRIVER
> TAINT_BROKEN_HW
> TAINT_BROKEN_HARDWARE
> TAINT_USE_AT_YOUR_OWN_RISK

I personally wouldn't object, but it's not a PCI thing so that can all
be separate from this driver.

> >> The one issue I anticipate with "depends on BROKEN" is
> >> when I add support for revision 2, which isn't broken.
> > 
> > How about this:
> > 
> >   - Rename PCIE_TANGO to PCIE_TANGO_REV1
> >   - PCIE_TANGO_REV1 depends on BROKEN
> >   - Add rev2 support later, enabled by PCIE_TANGO
> >   - PCIE_TANGO_REV1 depends on PCIE_TANGO && BROKEN
> > 
> > I updated pci/host-tango along these lines (without rev2 support,
> > obviously).
> 
> And support for REV1 wouldn't be compiled in, unless
> BROKEN is selected? Yes, I think that could fly.

Right.

> Don't you think the naming should follow the DT
> convention of using the first SoC embedding the
> IP (for the compatible string) ?
> 
> PCIE_TANGO_REV1 vs PCIE_TANGO_SMP8759

Sounds reasonable.  So v2 will be something other than SMP8759?
I renamed it to CONFIG_PCIE_TANGO_SMP8759.

> > I forgot to ask for a MAINTAINERS update.  Can you send that, too,
> > please?
> 
> There's a "catch-all" rule for everything tango-related:
> 
> ARM/TANGO ARCHITECTURE
> M:	Marc Gonzalez <marc_gonzalez@sigmadesigns.com>
> L:	linux-arm-kernel at lists.infradead.org
> S:	Maintained
> N:	tango
> 
> Is that enough?

Yep, sorry I didn't notice that.  That's enough for
scripts/get_maintainer.pl to work, which is what I'm looking for.

If you confirm that
https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/commit/?h=pci/host-tango&id=d752a8b29345
works for you, I'll include it in my v4.13 pull request.

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-05 21:34         ` Bjorn Helgaas
@ 2017-07-05 21:59           ` Mason
  2017-07-06  3:39             ` Bjorn Helgaas
  0 siblings, 1 reply; 41+ messages in thread
From: Mason @ 2017-07-05 21:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/07/2017 23:34, Bjorn Helgaas wrote:

> On Wed, Jul 05, 2017 at 10:39:19PM +0200, Mason wrote:
>
>> On 05/07/2017 20:03, Bjorn Helgaas wrote:
>>
>>> On Wed, Jul 05, 2017 at 12:55:37AM +0200, Mason wrote:
>>>
>>>> On 04/07/2017 22:24, Bjorn Helgaas wrote:
>>>>
>>>>> I made the trivial changes I mentioned, added a dependency on
>>>>> CONFIG_BROKEN (for the config/MMIO muxing issue), and put these on
>>>>> pci/host-tango.  I can't build or test this, so I probably broke
>>>>> something in the process.  I think the combination of the boot-time
>>>>> warning, the taint, and CONFIG_BROKEN is a reasonable amount of
>>>>> warning that a user should expect issues.
>>>>>
>>>>> Can you take a look and see if it works for you?
>>>>>
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-tango
>>>>
>>>> Thanks. I'll take it for a spin ASAP.
>>>>
>>>> TAINT_CRAP... Smirk. I didn't see that one in the docs:
>>>> https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html
>>>>
>>>> Oh wait... TAINT_CRAP is "C" => a staging driver has been loaded
>>>
>>> I wish it had a less pejorative, more descriptive name.  But it seems like
>>> the closest to this situation.
>>
>> Maybe it is not too late to submit a patch to Linus
>> renaming TAINT_CRAP?
>>
>> Here are a few candidates, off the top of my head:
>>
>> TAINT_STAGING
>> TAINT_STAGING_DRIVER
>> TAINT_BROKEN_HW
>> TAINT_BROKEN_HARDWARE
>> TAINT_USE_AT_YOUR_OWN_RISK
> 
> I personally wouldn't object, but it's not a PCI thing so that can all
> be separate from this driver.

Yes, of course. I was just asking for your (and anyone's)
opinion, as a Linux dev.

>>>> The one issue I anticipate with "depends on BROKEN" is
>>>> when I add support for revision 2, which isn't broken.
>>>
>>> How about this:
>>>
>>>   - Rename PCIE_TANGO to PCIE_TANGO_REV1
>>>   - PCIE_TANGO_REV1 depends on BROKEN
>>>   - Add rev2 support later, enabled by PCIE_TANGO
>>>   - PCIE_TANGO_REV1 depends on PCIE_TANGO && BROKEN
>>>
>>> I updated pci/host-tango along these lines (without rev2 support,
>>> obviously).
>>
>> And support for REV1 wouldn't be compiled in, unless
>> BROKEN is selected? Yes, I think that could fly.
> 
> Right.
> 
>> Don't you think the naming should follow the DT
>> convention of using the first SoC embedding the
>> IP (for the compatible string) ?
>>
>> PCIE_TANGO_REV1 vs PCIE_TANGO_SMP8759
> 
> Sounds reasonable.  So v2 will be something other than SMP8759?
> I renamed it to CONFIG_PCIE_TANGO_SMP8759.

Right, HW bugs are fixed in newer chips. Old chips rarely
get bug fixes, apparently.

> If you confirm that
> https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/commit/?h=pci/host-tango&id=d752a8b29345
> works for you, I'll include it in my v4.13 pull request.

There were a few nits I wanted to address:

- Since we added suppress_bind_attrs = true, probe()
can only be called at init, so I wanted to mark __init
all the probe functions, to save space.

- I left the definition of MSI_MAX in the wrong patch

- You put a pointer to the pdev in the struct tango_pcie.
I think this is redundant, since the pdev already has a
pointer to the struct, as drvdata.
So I wanted to change tango_msi_probe() to take a pdev
as argument (to make it more like an actual probe function)
and derive pcie from pdev, instead of the other way around.

Can I send you a patch series with these changes on Friday?

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-05 21:59           ` Mason
@ 2017-07-06  3:39             ` Bjorn Helgaas
  2017-07-06 12:26               ` Mason
  0 siblings, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-06  3:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 05, 2017 at 11:59:33PM +0200, Mason wrote:
> On 05/07/2017 23:34, Bjorn Helgaas wrote:
> 
> > On Wed, Jul 05, 2017 at 10:39:19PM +0200, Mason wrote:
> >
> >> On 05/07/2017 20:03, Bjorn Helgaas wrote:

> > If you confirm that
> > https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/commit/?h=pci/host-tango&id=d752a8b29345
> > works for you, I'll include it in my v4.13 pull request.
> 
> There were a few nits I wanted to address:
> 
> - Since we added suppress_bind_attrs = true, probe()
> can only be called at init, so I wanted to mark __init
> all the probe functions, to save space.
> 
> - I left the definition of MSI_MAX in the wrong patch
> 
> - You put a pointer to the pdev in the struct tango_pcie.
> I think this is redundant, since the pdev already has a
> pointer to the struct, as drvdata.
> So I wanted to change tango_msi_probe() to take a pdev
> as argument (to make it more like an actual probe function)
> and derive pcie from pdev, instead of the other way around.

I don't think tango_msi_probe() is really a "probe" function.  It's
all part of the tango driver, and it's not claiming a separate piece
of hardware.  So I would keep the name and structure similar to these:

  advk_pcie_init_msi_irq_domain()
  nwl_pcie_init_msi_irq_domain()

BTW, those functions use irq_domain_add_linear(), while you are one of
the very few callers of irq_domain_create_linear().  Why the difference?
If your code does basically the same thing, it's very helpful to me if
it *looks* basically the same.

> Can I send you a patch series with these changes on Friday?

I was planning to ask Linus to pull my branch tomorrow or Friday
because I'm going on vacation next week and I don't want to leave
right after he pulls it.  So the sooner the better.

Bjorn

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-06  3:39             ` Bjorn Helgaas
@ 2017-07-06 12:26               ` Mason
  2017-07-06 12:40                 ` Marc Zyngier
  2017-07-06 19:46                 ` Bjorn Helgaas
  0 siblings, 2 replies; 41+ messages in thread
From: Mason @ 2017-07-06 12:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/07/2017 05:39, Bjorn Helgaas wrote:

> On Wed, Jul 05, 2017 at 11:59:33PM +0200, Mason wrote:
>
>> There were a few nits I wanted to address:
>>
>> - Since we added suppress_bind_attrs = true, probe()
>> can only be called at init, so I wanted to mark __init
>> all the probe functions, to save space.
>>
>> - I left the definition of MSI_MAX in the wrong patch
>>
>> - You put a pointer to the pdev in the struct tango_pcie.
>> I think this is redundant, since the pdev already has a
>> pointer to the struct, as drvdata.
>> So I wanted to change tango_msi_probe() to take a pdev
>> as argument (to make it more like an actual probe function)
>> and derive pcie from pdev, instead of the other way around.
> 
> I don't think tango_msi_probe() is really a "probe" function.  It's
> all part of the tango driver, and it's not claiming a separate piece
> of hardware.

I agree that tango_msi_probe() is not a probe function;
it is merely a piece of the actual probe function (static
with single call site). I split the probe function in two,
because it seemed to make sense at the time.

Perhaps it's better to inline tango_msi_probe? That would
avoid the issues of that function's name and parameters.

If you think it's better to keep the two pieces separate,
I can rename the MSI part to tango_msi_init() or some such.
But I'd like to avoid adding unnecessary fields to the struct.

>  So I would keep the name and structure similar to these:
> 
>   advk_pcie_init_msi_irq_domain()
>   nwl_pcie_init_msi_irq_domain()
> 
> BTW, those functions use irq_domain_add_linear(), while you are one of
> the very few callers of irq_domain_create_linear().  Why the difference?
> If your code does basically the same thing, it's very helpful to me if
> it *looks* basically the same.

It was a suggestion from Marc Z on 2017-03-23.

<QUOTE>
+ irq_dom = irq_domain_add_linear(NULL, MSI_COUNT, &msi_domain_ops, pcie);

Use irq_domain_create_linear, pass the same fwnode.
</QUOTE>

It seems odd to pass NULL as the first argument.
(As I had first done, when copying the Altera driver.)

>> Can I send you a patch series with these changes on Friday?
> 
> I was planning to ask Linus to pull my branch tomorrow or Friday
> because I'm going on vacation next week and I don't want to leave
> right after he pulls it.  So the sooner the better.

I'm not at the office today, but I'll do it first thing
tomorrow. If it works out, great. If I'm too late, well
there's 4.14 to look forward to.

Regards.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-06 12:26               ` Mason
@ 2017-07-06 12:40                 ` Marc Zyngier
  2017-07-06 19:46                 ` Bjorn Helgaas
  1 sibling, 0 replies; 41+ messages in thread
From: Marc Zyngier @ 2017-07-06 12:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/07/17 13:26, Mason wrote:
> On 06/07/2017 05:39, Bjorn Helgaas wrote:
> 
>> On Wed, Jul 05, 2017 at 11:59:33PM +0200, Mason wrote:
>>
>>> There were a few nits I wanted to address:
>>>
>>> - Since we added suppress_bind_attrs = true, probe()
>>> can only be called at init, so I wanted to mark __init
>>> all the probe functions, to save space.
>>>
>>> - I left the definition of MSI_MAX in the wrong patch
>>>
>>> - You put a pointer to the pdev in the struct tango_pcie.
>>> I think this is redundant, since the pdev already has a
>>> pointer to the struct, as drvdata.
>>> So I wanted to change tango_msi_probe() to take a pdev
>>> as argument (to make it more like an actual probe function)
>>> and derive pcie from pdev, instead of the other way around.
>>
>> I don't think tango_msi_probe() is really a "probe" function.  It's
>> all part of the tango driver, and it's not claiming a separate piece
>> of hardware.
> 
> I agree that tango_msi_probe() is not a probe function;
> it is merely a piece of the actual probe function (static
> with single call site). I split the probe function in two,
> because it seemed to make sense at the time.
> 
> Perhaps it's better to inline tango_msi_probe? That would
> avoid the issues of that function's name and parameters.
> 
> If you think it's better to keep the two pieces separate,
> I can rename the MSI part to tango_msi_init() or some such.
> But I'd like to avoid adding unnecessary fields to the struct.
> 
>>  So I would keep the name and structure similar to these:
>>
>>   advk_pcie_init_msi_irq_domain()
>>   nwl_pcie_init_msi_irq_domain()
>>
>> BTW, those functions use irq_domain_add_linear(), while you are one of
>> the very few callers of irq_domain_create_linear().  Why the difference?
>> If your code does basically the same thing, it's very helpful to me if
>> it *looks* basically the same.

irq_domain_add_linear() can only take an of_node as the identifier for
the domain, while the _create_ variants use a fwnode. Given that an
of+node is also a fwnode, the former is now deprecated in favour of the
latter.

> 
> It was a suggestion from Marc Z on 2017-03-23.
> 
> <QUOTE>
> + irq_dom = irq_domain_add_linear(NULL, MSI_COUNT, &msi_domain_ops, pcie);
> 
> Use irq_domain_create_linear, pass the same fwnode.
> </QUOTE>
> 
> It seems odd to pass NULL as the first argument.
> (As I had first done, when copying the Altera driver.)

Indeed, as it creates a "default" domain, which is almost always wrong.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-06 12:26               ` Mason
  2017-07-06 12:40                 ` Marc Zyngier
@ 2017-07-06 19:46                 ` Bjorn Helgaas
  2017-07-07  9:55                   ` Marc Gonzalez
  1 sibling, 1 reply; 41+ messages in thread
From: Bjorn Helgaas @ 2017-07-06 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 06, 2017 at 02:26:44PM +0200, Mason wrote:
> On 06/07/2017 05:39, Bjorn Helgaas wrote:
> 
> > On Wed, Jul 05, 2017 at 11:59:33PM +0200, Mason wrote:
> >
> >> There were a few nits I wanted to address:
> >>
> >> - Since we added suppress_bind_attrs = true, probe()
> >> can only be called at init, so I wanted to mark __init
> >> all the probe functions, to save space.
> >>
> >> - I left the definition of MSI_MAX in the wrong patch

I moved this.

> >> - You put a pointer to the pdev in the struct tango_pcie.
> >> I think this is redundant, since the pdev already has a
> >> pointer to the struct, as drvdata.
> >> So I wanted to change tango_msi_probe() to take a pdev
> >> as argument (to make it more like an actual probe function)
> >> and derive pcie from pdev, instead of the other way around.
> > 
> > I don't think tango_msi_probe() is really a "probe" function.  It's
> > all part of the tango driver, and it's not claiming a separate piece
> > of hardware.
> 
> I agree that tango_msi_probe() is not a probe function;
> it is merely a piece of the actual probe function (static
> with single call site). I split the probe function in two,
> because it seemed to make sense at the time.
> 
> Perhaps it's better to inline tango_msi_probe? That would
> avoid the issues of that function's name and parameters.
> 
> If you think it's better to keep the two pieces separate,
> I can rename the MSI part to tango_msi_init() or some such.
> But I'd like to avoid adding unnecessary fields to the struct.

I think it's better to follow the structure of existing drivers unless
your hardware dictates a different model.  Same with adding fields to
the struct.  If you have a better way of doing it that works for all
the drivers, great -- but please change all the drivers to do it that
way.  If it's a matter of saving one pointer per system, by making the
code look different than other drivers, that's not so great.

> >  So I would keep the name and structure similar to these:
> > 
> >   advk_pcie_init_msi_irq_domain()
> >   nwl_pcie_init_msi_irq_domain()
> > 
> > BTW, those functions use irq_domain_add_linear(), while you are one of
> > the very few callers of irq_domain_create_linear().  Why the difference?
> > If your code does basically the same thing, it's very helpful to me if
> > it *looks* basically the same.
> 
> It was a suggestion from Marc Z on 2017-03-23.
> 
> <QUOTE>
> + irq_dom = irq_domain_add_linear(NULL, MSI_COUNT, &msi_domain_ops, pcie);
> 
> Use irq_domain_create_linear, pass the same fwnode.
> </QUOTE>
> 
> It seems odd to pass NULL as the first argument.
> (As I had first done, when copying the Altera driver.)

I'm a little queasy about the MSI stuff.  It doesn't feel very settled
yet, and I don't want to keep tweaking it at this stage.

How about we merge the base patch for v4.13 and deal with MSIs for
v4.14?  I need confirmation that the base patch works ASAP.  Or if
it's not really useful by itself, we can defer it all until v4.14.

For v4.14, I'd really like to see some unification of naming and
structure across the drivers in how they handle IRQ domains, and
then have tango follow whatever pattern that ends up being.

Right now we don't have much consistency in the names of legacy and
MSI IRQ domains, what device_node they're associated with, how we
handle the 0-3 vs 1-4 legacy numbering, pci_msi_create_irq_domain()
usage, etc.  Some of this may be dictated by different hardware
requirements, but I doubt all of it is.

Bjorn


P.S. Notes about current IRQ domain usage below, just for reference
about where I'm seeing inconsistencies.

    advk_pcie_probe			# "marvell,armada-3700-pcie"
      advk_pcie_init_irq_domain
        pcie_intc_node =  of_get_next_child(node, NULL)
        irq_domain_add_linear(pcie_intc_node, ...)
      advk_pcie_init_msi_irq_domain
        pcie->msi_inner_domain = irq_domain_add_linear(NULL, ...)
        pcie->msi_domain = pci_msi_create_irq_domain(...)

    altera_pcie_probe			# "altr,pcie-root-port-1.0"
      altera_pcie_init_irq_domain
        pcie->irq_domain = irq_domain_add_linear(node, ...)
    altera_msi_probe			# "altr,msi-1.0"
      altera_allocate_domains
        msi->inner_domain = irq_domain_add_linear(NULL, ...)
        msi->msi_domain = pci_msi_create_irq_domain(fwnode, ...)

    iproc_pcie_pltfm_probe		# "brcm,iproc-pcie", etc
      iproc_pcie_setup
        iproc_pcie_msi_enable
          iproc_msi_init
            iproc_msi_alloc_domains
              msi->inner_domain = irq_domain_add_linear(NULL, ...)
              msi->msi_domain = pci_msi_create_irq_domain(...)

    rcar_pcie_probe			# "renesas,pcie-r8a7779", etc
      rcar_pcie_enable_msi
        msi->domain = irq_domain_add_linear(dev->of_node, ...)

    rockchip_pcie_probe			# "rockchip,rk3399-pcie"
      rockchip_pcie_init_irq_domain
        intc = of_get_next_child(dev->of_node, NULL)
        rockchip->irq_domain = irq_domain_add_linear(intc, ...)
  
    xilinx_pcie_probe			# "xlnx,axi-pcie-host-1.00.a"
      xilinx_pcie_init_irq_domain
        pcie_intc_node = of_get_next_child(node, NULL)
        port->leg_domain = irq_domain_add_linear(pcie_intc_node, ...)
        port->msi_domain = irq_domain_add_linear(node, ...)

    nwl_pcie_probe			# "xlnx,nwl-pcie-2.11"
      nwl_pcie_init_irq_domain
        legacy_intc_node = of_get_next_child(node, NULL)
        pcie->legacy_irq_domain = irq_domain_add_linear(legacy_intc_node, ...)
        nwl_pcie_init_msi_irq_domain
          msi->dev_domain = irq_domain_add_linear(NULL, ...)
          msi->msi_domain = pci_msi_create_irq_domain(fwnode, ...)

    faraday_pci_probe			# "faraday,ftpci100", etc
      faraday_pci_setup_cascaded_irq
        intc = of_get_next_child(p->dev->of_node, NULL)
        p->irqdomain = irq_domain_add_linear(intc, ...)

    hv_pci_probe
      hv_pcie_init_irq_domain
        hbus->irq_domain = pci_msi_create_irq_domain(...)

    tegra_pcie_probe			# "nvidia,tegra210-pcie", etc
      tegra_pcie_enable_msi
        msi->domain = irq_domain_add_linear(dev->of_node, ...)

    xgene_pcie_probe_bridge		# "apm,xgene-pcie"
    xgene_msi_probe			# "apm,xgene1-msi"
      xgene_allocate_domains
        msi->inner_domain = irq_domain_add_linear(NULL, ...)
        msi->msi_domain = pci_msi_create_irq_domain(...)

    vmd_probe				# [8086:201d]
      vmd_enable_domain
        vmd->irq_domain = pci_msi_create_irq_domain(NULL, ...)

    dra7xx_pcie_probe			# "ti,dra7-pcie", etc
      dra7xx_add_pcie_port
        dra7xx_pcie_init_irq_domain
          pcie_intc_node =  of_get_next_child(node, NULL)
          dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, ...)

    dw_pcie_host_init
      pp->ops->msi_host_init
        ks_dw_pcie_msi_host_init	# .msi_host_init
          pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np, ...)

    ks_pcie_probe			# "ti,keystone-pcie"
      ks_add_pcie_port
        ks_dw_pcie_host_init
          ks_pcie->legacy_irq_domain = irq_domain_add_linear(ks_pcie->legacy_intc_np, ...)

    *_add_pcie_port
      dw_pcie_host_init
        pp->irq_domain = irq_domain_add_linear(dev->of_node, ...) # generic

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH v9 0/3] Tango PCIe controller support
  2017-07-06 19:46                 ` Bjorn Helgaas
@ 2017-07-07  9:55                   ` Marc Gonzalez
  0 siblings, 0 replies; 41+ messages in thread
From: Marc Gonzalez @ 2017-07-07  9:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/07/2017 21:46, Bjorn Helgaas wrote:

> I'm a little queasy about the MSI stuff.  It doesn't feel very settled
> yet, and I don't want to keep tweaking it at this stage.
> 
> How about we merge the base patch for v4.13 and deal with MSIs for
> v4.14?  I need confirmation that the base patch works ASAP.  Or if
> it's not really useful by itself, we can defer it all until v4.14.

For what it's worth, the base patch allows enumeration:

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.12.0-rc1 (mgonzalez at misti.france.sdesigns.com) (gcc version 6.3.1 20170109 (Linaro GCC 6.3-2017.02) ) #6 SMP PREEMPT Fri Jul 7 11:43:24 CEST 2017
...
[    0.725488] pcie_tango 50000000.pcie: simultaneous PCI config and MMIO accesses may cause data corruption
[    0.743158] OF: PCI: host bridge /soc/pcie at 2e000 ranges:
[    0.748519] OF: PCI:   MEM 0x50400000..0x53ffffff -> 0x00400000
[    0.754549] pcie_tango 50000000.pcie: ECAM at [mem 0x50000000-0x503fffff] for [bus 00-03]
[    0.762907] pcie_tango 50000000.pcie: PCI host bridge to bus 0000:00
[    0.769308] pci_bus 0000:00: root bus resource [bus 00-03]
[    0.774829] pci_bus 0000:00: root bus resource [mem 0x50400000-0x53ffffff] (bus address [0x00400000-0x03ffffff])
[    0.785303] PCI: bus0: Fast back to back transfers disabled
[    0.790916] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
[    0.807282] PCI: bus1: Fast back to back transfers disabled
[    0.812925] pci 0000:00:00.0: BAR 8: assigned [mem 0x50400000-0x504fffff]
[    0.819759] pci 0000:01:00.0: BAR 0: assigned [mem 0x50400000-0x50401fff 64bit]
[    0.827126] pci 0000:00:00.0: PCI bridge to [bus 01]
[    0.832121] pci 0000:00:00.0:   bridge window [mem 0x50400000-0x504fffff]
[    0.839004] pcieport 0000:00:00.0: enabling device (0140 -> 0142)
[    0.845274] pci 0000:01:00.0: enabling device (0140 -> 0142)



# lspci -v  
00:00.0 PCI bridge: Sigma Designs, Inc. Device 0024 (rev 01) (prog-if 00 [Normal decode])
        Flags: bus master, fast devsel, latency 0
        Memory at <ignored> (64-bit, non-prefetchable)
        Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
        I/O behind bridge: 00000000-00000fff
        Memory behind bridge: 00400000-004fffff
        Prefetchable memory behind bridge: 00000000-000fffff
        Capabilities: [50] MSI: Enable- Count=1/4 Maskable- 64bit+
        Capabilities: [78] Power Management version 3
        Capabilities: [80] Express Root Port (Slot-), MSI 03
        Capabilities: [100] Virtual Channel
        Capabilities: [800] Advanced Error Reporting
        Kernel driver in use: pcieport

01:00.0 USB controller: Renesas Technology Corp. uPD720201 USB 3.0 Host Controller (rev 03) (prog-if 30 [XHCI])
        Flags: fast devsel
        Memory at 50400000 (64-bit, non-prefetchable) [size=8K]
        Capabilities: [50] Power Management version 3
        Capabilities: [70] MSI: Enable- Count=1/8 Maskable- 64bit+
        Capabilities: [90] MSI-X: Enable- Count=8 Masked-
        Capabilities: [a0] Express Endpoint, MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [150] Latency Tolerance Reporting



# lspci -vvv
00:00.0 PCI bridge: Sigma Designs, Inc. Device 0024 (rev 01) (prog-if 00 [Normal decode])
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Region 0: Memory@<ignored> (64-bit, non-prefetchable)
        Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
        I/O behind bridge: 00000000-00000fff
        Memory behind bridge: 00400000-004fffff
        Prefetchable memory behind bridge: 00000000-000fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [50] MSI: Enable- Count=1/4 Maskable- 64bit+
                Address: 0000000000000000  Data: 0000
        Capabilities: [78] Power Management version 3
                Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=3 PME-
        Capabilities: [80] Express (v2) Root Port (Slot-), MSI 03
                DevCap: MaxPayload 256 bytes, PhantFunc 0
                        ExtTag- RBE+
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend+
                LnkCap: Port #1, Speed 5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <2us, L1 <4us
                        ClockPM- Surprise- LLActRep- BwNot+ ASPMOptComp-
                LnkCtl: ASPM Disabled; RCB 128 bytes Disabled- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-
                RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
                RootCap: CRSVisible-
                RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                DevCap2: Completion Timeout: Range B, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd-
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v1] Virtual Channel
                Caps:   LPEVC=0 RefClk=100ns PATEntryBits=1
                Arb:    Fixed- WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
                        Status: NegoPending- InProgress-
        Capabilities: [800 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
        Kernel driver in use: pcieport

01:00.0 USB controller: Renesas Technology Corp. uPD720201 USB 3.0 Host Controller (rev 03) (prog-if 30 [XHCI])
        Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Interrupt: pin A routed to IRQ 0
        Region 0: Memory@50400000 (64-bit, non-prefetchable) [size=8K]
        Capabilities: [50] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=375mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [70] MSI: Enable- Count=1/8 Maskable- 64bit+
                Address: 0000000000000000  Data: 0000
        Capabilities: [90] MSI-X: Enable- Count=8 Masked-
                Vector table: BAR=0 offset=00001000
                PBA: BAR=0 offset=00001080
        Capabilities: [a0] Express (v2) Endpoint, MSI 00
                DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset- SlotPowerLimit 0.000W
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <4us, L1 unlimited
                        ClockPM+ Surprise- LLActRep- BwNot- ASPMOptComp-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR+, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP+ Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
        Capabilities: [150 v1] Latency Tolerance Reporting
                Max snoop latency: 0ns
                Max no snoop latency: 0ns

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2017-07-07  9:55 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-20  8:12 [PATCH v9 0/3] Tango PCIe controller support Marc Gonzalez
2017-06-20  8:14 ` [PATCH v9 1/3] PCI: Add DT binding for tango PCIe controller Marc Gonzalez
2017-06-20  8:17 ` [PATCH v9 2/3] PCI: Add tango PCIe host bridge support Marc Gonzalez
2017-07-02 23:18   ` Bjorn Helgaas
2017-07-03  9:35     ` Ard Biesheuvel
2017-07-03 13:27       ` Bjorn Helgaas
2017-07-04  6:58         ` Jisheng Zhang
2017-07-04  7:16           ` Jisheng Zhang
2017-07-04  8:02           ` Ard Biesheuvel
2017-07-04  8:19             ` Jisheng Zhang
2017-07-04  9:38               ` Ard Biesheuvel
2017-07-05 13:53                 ` Joao Pinto
2017-07-03  9:54     ` Marc Gonzalez
2017-07-03 13:40       ` Bjorn Helgaas
2017-07-03 14:34         ` Marc Gonzalez
2017-07-04 15:58           ` Bjorn Helgaas
2017-07-04 23:42             ` Mason
2017-07-03 18:11         ` Russell King - ARM Linux
2017-07-03 18:44           ` Ard Biesheuvel
2017-07-04 15:15           ` Bjorn Helgaas
2017-07-04 18:17             ` Russell King - ARM Linux
2017-07-04 23:59           ` Mason
2017-07-05  5:21             ` Greg Kroah-Hartman
2017-07-05 12:33             ` Mark Brown
     [not found]       ` <e57debab-3457-1d9c-a72e-ecdf7d4f742e@sigmadesigns.com>
2017-07-03 15:30         ` Marc Gonzalez
2017-07-04  7:09           ` Peter Zijlstra
2017-07-04 13:08             ` Mason
2017-07-04 14:27               ` Peter Zijlstra
2017-07-04 15:18                 ` Mason
2017-06-20  8:18 ` [PATCH v9 3/3] PCI: Add tango MSI controller support Marc Gonzalez
2017-07-04 20:24 ` [PATCH v9 0/3] Tango PCIe " Bjorn Helgaas
2017-07-04 22:55   ` Mason
2017-07-05 18:03     ` Bjorn Helgaas
2017-07-05 20:39       ` Mason
2017-07-05 21:34         ` Bjorn Helgaas
2017-07-05 21:59           ` Mason
2017-07-06  3:39             ` Bjorn Helgaas
2017-07-06 12:26               ` Mason
2017-07-06 12:40                 ` Marc Zyngier
2017-07-06 19:46                 ` Bjorn Helgaas
2017-07-07  9:55                   ` Marc Gonzalez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox