LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/3] powerpc/pci: use of_irq_parse_and_map_pci helper
From: Rob Herring @ 2018-01-04 21:12 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: devicetree, linux-kernel, Benjamin Herrenschmidt, Paul Mackerras,
	Michael Ellerman, Frank Rowand, linuxppc-dev, linux-pci
In-Reply-To: <20180104211215.11344-1-robh@kernel.org>

Instead of calling both of_irq_parse_pci and irq_create_of_mapping, call
of_irq_parse_and_map_pci instead which does the same thing. This will
allow making of_irq_parse_pci a private, static function.

This changes the logic slightly in that the fallback path will also be
taken if irq_create_of_mapping fails internally.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Rob Herring <robh@kernel.org>
---
 arch/powerpc/kernel/pci-common.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 0ac7aa346c69..f65c07dec23e 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -339,7 +339,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
  */
 static int pci_read_irq_line(struct pci_dev *pci_dev)
 {
-	struct of_phandle_args oirq;
 	unsigned int virq;
 
 	pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev));
@@ -348,7 +347,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
 	memset(&oirq, 0xff, sizeof(oirq));
 #endif
 	/* Try to get a mapping from the device-tree */
-	if (of_irq_parse_pci(pci_dev, &oirq)) {
+	if (!of_irq_parse_and_map_pci(pci_dev, 0, 0)) {
 		u8 line, pin;
 
 		/* If that fails, lets fallback to what is in the config
@@ -372,11 +371,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
 		virq = irq_create_mapping(NULL, line);
 		if (virq)
 			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	} else {
-		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %pOF\n",
-			 oirq.args_count, oirq.args[0], oirq.args[1], oirq.np);
-
-		virq = irq_create_of_mapping(&oirq);
 	}
 
 	if (!virq) {
-- 
2.14.1

^ permalink raw reply related

* [PATCH 1/3] PCI: move OF related PCI functions into PCI core
From: Rob Herring @ 2018-01-04 21:12 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: devicetree, linux-kernel, Benjamin Herrenschmidt, Paul Mackerras,
	Michael Ellerman, Frank Rowand, linuxppc-dev, linux-pci
In-Reply-To: <20180104211215.11344-1-robh@kernel.org>

Following what has been done for other subsystems, move the remaining PCI
related code out of drivers/of/ and into drivers/pci/of.c

With this, we can kill a few kconfig symbols.

Cc: Frank Rowand <frowand.list@gmail.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
---
 arch/arm/mach-mvebu/Kconfig |   1 -
 drivers/of/Kconfig          |  16 --
 drivers/of/Makefile         |   2 -
 drivers/of/address.c        |   8 +-
 drivers/of/of_pci.c         | 384 ---------------------------------
 drivers/of/of_pci_irq.c     | 131 ------------
 drivers/pci/of.c            | 506 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h      |   2 +-
 8 files changed, 510 insertions(+), 540 deletions(-)
 delete mode 100644 drivers/of/of_pci.c
 delete mode 100644 drivers/of/of_pci_irq.c

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 9b49867154bf..6b32dc527edc 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -10,7 +10,6 @@ menuconfig ARCH_MVEBU
 	select ZONE_DMA if ARM_LPAE
 	select GPIOLIB
 	select PCI_QUIRKS if PCI
-	select OF_ADDRESS_PCI
 
 if ARCH_MVEBU
 
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 5020d7ef7494..35b5b8ec13c9 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -63,10 +63,6 @@ config OF_DYNAMIC
 config OF_ADDRESS
 	def_bool y
 	depends on !SPARC && (HAS_IOMEM || UML)
-	select OF_ADDRESS_PCI if PCI
-
-config OF_ADDRESS_PCI
-	bool
 
 config OF_IRQ
 	def_bool y
@@ -83,18 +79,6 @@ config OF_MDIO
 	help
 	  OpenFirmware MDIO bus (Ethernet PHY) accessors
 
-config OF_PCI
-	def_tristate PCI
-	depends on PCI
-	help
-	  OpenFirmware PCI bus accessors
-
-config OF_PCI_IRQ
-	def_tristate PCI
-	depends on OF_PCI && OF_IRQ
-	help
-	  OpenFirmware PCI IRQ routing helpers
-
 config OF_RESERVED_MEM
 	depends on OF_EARLY_FLATTREE
 	bool
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 63a4be62ce19..663a4af0cccd 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -10,8 +10,6 @@ obj-$(CONFIG_OF_IRQ)    += irq.o
 obj-$(CONFIG_OF_NET)	+= of_net.o
 obj-$(CONFIG_OF_UNITTEST) += unittest.o
 obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
-obj-$(CONFIG_OF_PCI)	+= of_pci.o
-obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
 obj-$(CONFIG_OF_RESOLVE)  += resolver.o
 obj-$(CONFIG_OF_OVERLAY) += overlay.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index fa6cabfc3cb9..8591afbdfe99 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -96,7 +96,7 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
 	return IORESOURCE_MEM;
 }
 
-#ifdef CONFIG_OF_ADDRESS_PCI
+#ifdef CONFIG_PCI
 /*
  * PCI bus specific translator
  */
@@ -171,9 +171,7 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
 {
 	return of_bus_default_translate(addr + 1, offset, na - 1);
 }
-#endif /* CONFIG_OF_ADDRESS_PCI */
 
-#ifdef CONFIG_PCI
 const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
 			unsigned int *flags)
 {
@@ -426,7 +424,7 @@ static unsigned int of_bus_isa_get_flags(const __be32 *addr)
  */
 
 static struct of_bus of_busses[] = {
-#ifdef CONFIG_OF_ADDRESS_PCI
+#ifdef CONFIG_PCI
 	/* PCI */
 	{
 		.name = "pci",
@@ -437,7 +435,7 @@ static struct of_bus of_busses[] = {
 		.translate = of_bus_pci_translate,
 		.get_flags = of_bus_pci_get_flags,
 	},
-#endif /* CONFIG_OF_ADDRESS_PCI */
+#endif /* CONFIG_PCI */
 	/* ISA */
 	{
 		.name = "isa",
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
deleted file mode 100644
index a7b1cb6c2f65..000000000000
--- a/drivers/of/of_pci.c
+++ /dev/null
@@ -1,384 +0,0 @@
-#define pr_fmt(fmt)	"OF: PCI: " fmt
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_pci.h>
-#include <linux/slab.h>
-
-static inline int __of_pci_pci_compare(struct device_node *node,
-				       unsigned int data)
-{
-	int devfn;
-
-	devfn = of_pci_get_devfn(node);
-	if (devfn < 0)
-		return 0;
-
-	return devfn == data;
-}
-
-struct device_node *of_pci_find_child_device(struct device_node *parent,
-					     unsigned int devfn)
-{
-	struct device_node *node, *node2;
-
-	for_each_child_of_node(parent, node) {
-		if (__of_pci_pci_compare(node, devfn))
-			return node;
-		/*
-		 * Some OFs create a parent node "multifunc-device" as
-		 * a fake root for all functions of a multi-function
-		 * device we go down them as well.
-		 */
-		if (!strcmp(node->name, "multifunc-device")) {
-			for_each_child_of_node(node, node2) {
-				if (__of_pci_pci_compare(node2, devfn)) {
-					of_node_put(node);
-					return node2;
-				}
-			}
-		}
-	}
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(of_pci_find_child_device);
-
-/**
- * of_pci_get_devfn() - Get device and function numbers for a device node
- * @np: device node
- *
- * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
- * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
- * and function numbers respectively. On error a negative error code is
- * returned.
- */
-int of_pci_get_devfn(struct device_node *np)
-{
-	u32 reg[5];
-	int error;
-
-	error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
-	if (error)
-		return error;
-
-	return (reg[0] >> 8) & 0xff;
-}
-EXPORT_SYMBOL_GPL(of_pci_get_devfn);
-
-/**
- * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
- * @node: device node
- * @res: address to a struct resource to return the bus-range
- *
- * Returns 0 on success or a negative error-code on failure.
- */
-int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
-{
-	u32 bus_range[2];
-	int error;
-
-	error = of_property_read_u32_array(node, "bus-range", bus_range,
-					   ARRAY_SIZE(bus_range));
-	if (error)
-		return error;
-
-	res->name = node->name;
-	res->start = bus_range[0];
-	res->end = bus_range[1];
-	res->flags = IORESOURCE_BUS;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
-
-/**
- * This function will try to obtain the host bridge domain number by
- * finding a property called "linux,pci-domain" of the given device node.
- *
- * @node: device tree node with the domain information
- *
- * Returns the associated domain number from DT in the range [0-0xffff], or
- * a negative value if the required property is not found.
- */
-int of_get_pci_domain_nr(struct device_node *node)
-{
-	u32 domain;
-	int error;
-
-	error = of_property_read_u32(node, "linux,pci-domain", &domain);
-	if (error)
-		return error;
-
-	return (u16)domain;
-}
-EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
-
-/**
- * This function will try to find the limitation of link speed by finding
- * a property called "max-link-speed" of the given device node.
- *
- * @node: device tree node with the max link speed information
- *
- * Returns the associated max link speed from DT, or a negative value if the
- * required property is not found or is invalid.
- */
-int of_pci_get_max_link_speed(struct device_node *node)
-{
-	u32 max_link_speed;
-
-	if (of_property_read_u32(node, "max-link-speed", &max_link_speed) ||
-	    max_link_speed > 4)
-		return -EINVAL;
-
-	return max_link_speed;
-}
-EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed);
-
-/**
- * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only
- *                           is present and valid
- */
-void of_pci_check_probe_only(void)
-{
-	u32 val;
-	int ret;
-
-	ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val);
-	if (ret) {
-		if (ret == -ENODATA || ret == -EOVERFLOW)
-			pr_warn("linux,pci-probe-only without valid value, ignoring\n");
-		return;
-	}
-
-	if (val)
-		pci_add_flags(PCI_PROBE_ONLY);
-	else
-		pci_clear_flags(PCI_PROBE_ONLY);
-
-	pr_info("PROBE_ONLY %sabled\n", val ? "en" : "dis");
-}
-EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
-
-#if defined(CONFIG_OF_ADDRESS)
-/**
- * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
- * @dev: device node of the host bridge having the range property
- * @busno: bus number associated with the bridge root bus
- * @bus_max: maximum number of buses for this bridge
- * @resources: list where the range of resources will be added after DT parsing
- * @io_base: pointer to a variable that will contain on return the physical
- * address for the start of the I/O range. Can be NULL if the caller doesn't
- * expect IO ranges to be present in the device tree.
- *
- * It is the caller's job to free the @resources list.
- *
- * This function will parse the "ranges" property of a PCI host bridge device
- * node and setup the resource mapping based on its content. It is expected
- * that the property conforms with the Power ePAPR document.
- *
- * It returns zero if the range parsing has been successful or a standard error
- * value if it failed.
- */
-int of_pci_get_host_bridge_resources(struct device_node *dev,
-			unsigned char busno, unsigned char bus_max,
-			struct list_head *resources, resource_size_t *io_base)
-{
-	struct resource_entry *window;
-	struct resource *res;
-	struct resource *bus_range;
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
-	char range_type[4];
-	int err;
-
-	if (io_base)
-		*io_base = (resource_size_t)OF_BAD_ADDR;
-
-	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
-	if (!bus_range)
-		return -ENOMEM;
-
-	pr_info("host bridge %pOF ranges:\n", dev);
-
-	err = of_pci_parse_bus_range(dev, bus_range);
-	if (err) {
-		bus_range->start = busno;
-		bus_range->end = bus_max;
-		bus_range->flags = IORESOURCE_BUS;
-		pr_info("  No bus range found for %pOF, using %pR\n",
-			dev, bus_range);
-	} else {
-		if (bus_range->end > bus_range->start + bus_max)
-			bus_range->end = bus_range->start + bus_max;
-	}
-	pci_add_resource(resources, bus_range);
-
-	/* Check for ranges property */
-	err = of_pci_range_parser_init(&parser, dev);
-	if (err)
-		goto parse_failed;
-
-	pr_debug("Parsing ranges property...\n");
-	for_each_of_pci_range(&parser, &range) {
-		/* Read next ranges element */
-		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
-			snprintf(range_type, 4, " IO");
-		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
-			snprintf(range_type, 4, "MEM");
-		else
-			snprintf(range_type, 4, "err");
-		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
-			range.cpu_addr, range.cpu_addr + range.size - 1,
-			range.pci_addr);
-
-		/*
-		 * If we failed translation or got a zero-sized region
-		 * then skip this range
-		 */
-		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
-			continue;
-
-		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
-		if (!res) {
-			err = -ENOMEM;
-			goto parse_failed;
-		}
-
-		err = of_pci_range_to_resource(&range, dev, res);
-		if (err) {
-			kfree(res);
-			continue;
-		}
-
-		if (resource_type(res) == IORESOURCE_IO) {
-			if (!io_base) {
-				pr_err("I/O range found for %pOF. Please provide an io_base pointer to save CPU base address\n",
-					dev);
-				err = -EINVAL;
-				goto conversion_failed;
-			}
-			if (*io_base != (resource_size_t)OF_BAD_ADDR)
-				pr_warn("More than one I/O resource converted for %pOF. CPU base address for old range lost!\n",
-					dev);
-			*io_base = range.cpu_addr;
-		}
-
-		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
-	}
-
-	return 0;
-
-conversion_failed:
-	kfree(res);
-parse_failed:
-	resource_list_for_each_entry(window, resources)
-		kfree(window->res);
-	pci_free_resource_list(resources);
-	return err;
-}
-EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
-#endif /* CONFIG_OF_ADDRESS */
-
-/**
- * of_pci_map_rid - Translate a requester ID through a downstream mapping.
- * @np: root complex device node.
- * @rid: PCI requester ID to map.
- * @map_name: property name of the map to use.
- * @map_mask_name: optional property name of the mask to use.
- * @target: optional pointer to a target device node.
- * @id_out: optional pointer to receive the translated ID.
- *
- * Given a PCI requester ID, look up the appropriate implementation-defined
- * platform ID and/or the target device which receives transactions on that
- * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
- * @id_out may be NULL if only the other is required. If @target points to
- * a non-NULL device node pointer, only entries targeting that node will be
- * matched; if it points to a NULL value, it will receive the device node of
- * the first matching target phandle, with a reference held.
- *
- * Return: 0 on success or a standard error code on failure.
- */
-int of_pci_map_rid(struct device_node *np, u32 rid,
-		   const char *map_name, const char *map_mask_name,
-		   struct device_node **target, u32 *id_out)
-{
-	u32 map_mask, masked_rid;
-	int map_len;
-	const __be32 *map = NULL;
-
-	if (!np || !map_name || (!target && !id_out))
-		return -EINVAL;
-
-	map = of_get_property(np, map_name, &map_len);
-	if (!map) {
-		if (target)
-			return -ENODEV;
-		/* Otherwise, no map implies no translation */
-		*id_out = rid;
-		return 0;
-	}
-
-	if (!map_len || map_len % (4 * sizeof(*map))) {
-		pr_err("%pOF: Error: Bad %s length: %d\n", np,
-			map_name, map_len);
-		return -EINVAL;
-	}
-
-	/* The default is to select all bits. */
-	map_mask = 0xffffffff;
-
-	/*
-	 * Can be overridden by "{iommu,msi}-map-mask" property.
-	 * If of_property_read_u32() fails, the default is used.
-	 */
-	if (map_mask_name)
-		of_property_read_u32(np, map_mask_name, &map_mask);
-
-	masked_rid = map_mask & rid;
-	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
-		struct device_node *phandle_node;
-		u32 rid_base = be32_to_cpup(map + 0);
-		u32 phandle = be32_to_cpup(map + 1);
-		u32 out_base = be32_to_cpup(map + 2);
-		u32 rid_len = be32_to_cpup(map + 3);
-
-		if (rid_base & ~map_mask) {
-			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n",
-				np, map_name, map_name,
-				map_mask, rid_base);
-			return -EFAULT;
-		}
-
-		if (masked_rid < rid_base || masked_rid >= rid_base + rid_len)
-			continue;
-
-		phandle_node = of_find_node_by_phandle(phandle);
-		if (!phandle_node)
-			return -ENODEV;
-
-		if (target) {
-			if (*target)
-				of_node_put(phandle_node);
-			else
-				*target = phandle_node;
-
-			if (*target != phandle_node)
-				continue;
-		}
-
-		if (id_out)
-			*id_out = masked_rid - rid_base + out_base;
-
-		pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n",
-			np, map_name, map_mask, rid_base, out_base,
-			rid_len, rid, masked_rid - rid_base + out_base);
-		return 0;
-	}
-
-	pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n",
-		np, map_name, rid, target && *target ? *target : NULL);
-	return -EFAULT;
-}
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
deleted file mode 100644
index 3a05568f65df..000000000000
--- a/drivers/of/of_pci_irq.c
+++ /dev/null
@@ -1,131 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/of_pci.h>
-#include <linux/of_irq.h>
-#include <linux/export.h>
-
-/**
- * of_irq_parse_pci - Resolve the interrupt for a PCI device
- * @pdev:       the device whose interrupt is to be resolved
- * @out_irq:    structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
-{
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	__be32 laddr[3];
-	u8 pin;
-	int rc;
-
-	/* Check if we have a device node, if yes, fallback to standard
-	 * device tree parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn) {
-		rc = of_irq_parse_one(dn, 0, out_irq);
-		if (!rc)
-			return rc;
-	}
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		goto err;
-	/* No pin, exit with no error message. */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-			ppnode = pci_bus_to_OF_node(pdev->bus);
-
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL) {
-				rc = -EINVAL;
-				goto err;
-			}
-		} else {
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-		}
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't
-		 * include the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
-
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
-		 */
-		pin = pci_swizzle_interrupt_pin(pdev, pin);
-		pdev = ppdev;
-	}
-
-	out_irq->np = ppnode;
-	out_irq->args_count = 1;
-	out_irq->args[0] = pin;
-	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
-	laddr[1] = laddr[2] = cpu_to_be32(0);
-	rc = of_irq_parse_raw(laddr, out_irq);
-	if (rc)
-		goto err;
-	return 0;
-err:
-	if (rc == -ENOENT) {
-		dev_warn(&pdev->dev,
-			"%s: no interrupt-map found, INTx interrupts not available\n",
-			__func__);
-		pr_warn_once("%s: possibly some PCI slots don't have level triggered interrupts capability\n",
-			__func__);
-	} else {
-		dev_err(&pdev->dev, "%s: failed with rc=%d\n", __func__, rc);
-	}
-	return rc;
-}
-EXPORT_SYMBOL_GPL(of_irq_parse_pci);
-
-/**
- * of_irq_parse_and_map_pci() - Decode a PCI irq from the device tree and map to a virq
- * @dev: The pci device needing an irq
- * @slot: PCI slot number; passed when used as map_irq callback. Unused
- * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
- *
- * @slot and @pin are unused, but included in the function so that this
- * function can be used directly as the map_irq callback to
- * pci_assign_irq() and struct pci_host_bridge.map_irq pointer
- */
-int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct of_phandle_args oirq;
-	int ret;
-
-	ret = of_irq_parse_pci(dev, &oirq);
-	if (ret)
-		return 0; /* Proper return code 0 == NO_IRQ */
-
-	return irq_create_of_mapping(&oirq);
-}
-EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
-
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index e112da11630e..859a43dd098d 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -8,12 +8,14 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#define pr_fmt(fmt)	"PCI: OF: " fmt
 
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/of_address.h>
 #include <linux/of_pci.h>
 #include "pci.h"
 
@@ -88,3 +90,507 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
 	return NULL;
 #endif
 }
+
+
+static inline int __of_pci_pci_compare(struct device_node *node,
+				       unsigned int data)
+{
+	int devfn;
+
+	devfn = of_pci_get_devfn(node);
+	if (devfn < 0)
+		return 0;
+
+	return devfn == data;
+}
+
+struct device_node *of_pci_find_child_device(struct device_node *parent,
+					     unsigned int devfn)
+{
+	struct device_node *node, *node2;
+
+	for_each_child_of_node(parent, node) {
+		if (__of_pci_pci_compare(node, devfn))
+			return node;
+		/*
+		 * Some OFs create a parent node "multifunc-device" as
+		 * a fake root for all functions of a multi-function
+		 * device we go down them as well.
+		 */
+		if (!strcmp(node->name, "multifunc-device")) {
+			for_each_child_of_node(node, node2) {
+				if (__of_pci_pci_compare(node2, devfn)) {
+					of_node_put(node);
+					return node2;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_pci_find_child_device);
+
+/**
+ * of_pci_get_devfn() - Get device and function numbers for a device node
+ * @np: device node
+ *
+ * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
+ * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
+ * and function numbers respectively. On error a negative error code is
+ * returned.
+ */
+int of_pci_get_devfn(struct device_node *np)
+{
+	u32 reg[5];
+	int error;
+
+	error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+	if (error)
+		return error;
+
+	return (reg[0] >> 8) & 0xff;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_devfn);
+
+/**
+ * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
+ * @node: device node
+ * @res: address to a struct resource to return the bus-range
+ *
+ * Returns 0 on success or a negative error-code on failure.
+ */
+int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
+{
+	u32 bus_range[2];
+	int error;
+
+	error = of_property_read_u32_array(node, "bus-range", bus_range,
+					   ARRAY_SIZE(bus_range));
+	if (error)
+		return error;
+
+	res->name = node->name;
+	res->start = bus_range[0];
+	res->end = bus_range[1];
+	res->flags = IORESOURCE_BUS;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+
+/**
+ * This function will try to obtain the host bridge domain number by
+ * finding a property called "linux,pci-domain" of the given device node.
+ *
+ * @node: device tree node with the domain information
+ *
+ * Returns the associated domain number from DT in the range [0-0xffff], or
+ * a negative value if the required property is not found.
+ */
+int of_get_pci_domain_nr(struct device_node *node)
+{
+	u32 domain;
+	int error;
+
+	error = of_property_read_u32(node, "linux,pci-domain", &domain);
+	if (error)
+		return error;
+
+	return (u16)domain;
+}
+EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
+
+/**
+ * This function will try to find the limitation of link speed by finding
+ * a property called "max-link-speed" of the given device node.
+ *
+ * @node: device tree node with the max link speed information
+ *
+ * Returns the associated max link speed from DT, or a negative value if the
+ * required property is not found or is invalid.
+ */
+int of_pci_get_max_link_speed(struct device_node *node)
+{
+	u32 max_link_speed;
+
+	if (of_property_read_u32(node, "max-link-speed", &max_link_speed) ||
+	    max_link_speed > 4)
+		return -EINVAL;
+
+	return max_link_speed;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_max_link_speed);
+
+/**
+ * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only
+ *                           is present and valid
+ */
+void of_pci_check_probe_only(void)
+{
+	u32 val;
+	int ret;
+
+	ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val);
+	if (ret) {
+		if (ret == -ENODATA || ret == -EOVERFLOW)
+			pr_warn("linux,pci-probe-only without valid value, ignoring\n");
+		return;
+	}
+
+	if (val)
+		pci_add_flags(PCI_PROBE_ONLY);
+	else
+		pci_clear_flags(PCI_PROBE_ONLY);
+
+	pr_info("PROBE_ONLY %sabled\n", val ? "en" : "dis");
+}
+EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
+
+#if defined(CONFIG_OF_ADDRESS)
+/**
+ * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
+ * @dev: device node of the host bridge having the range property
+ * @busno: bus number associated with the bridge root bus
+ * @bus_max: maximum number of buses for this bridge
+ * @resources: list where the range of resources will be added after DT parsing
+ * @io_base: pointer to a variable that will contain on return the physical
+ * address for the start of the I/O range. Can be NULL if the caller doesn't
+ * expect IO ranges to be present in the device tree.
+ *
+ * It is the caller's job to free the @resources list.
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping based on its content. It is expected
+ * that the property conforms with the Power ePAPR document.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base)
+{
+	struct resource_entry *window;
+	struct resource *res;
+	struct resource *bus_range;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	char range_type[4];
+	int err;
+
+	if (io_base)
+		*io_base = (resource_size_t)OF_BAD_ADDR;
+
+	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
+	if (!bus_range)
+		return -ENOMEM;
+
+	pr_info("host bridge %pOF ranges:\n", dev);
+
+	err = of_pci_parse_bus_range(dev, bus_range);
+	if (err) {
+		bus_range->start = busno;
+		bus_range->end = bus_max;
+		bus_range->flags = IORESOURCE_BUS;
+		pr_info("  No bus range found for %pOF, using %pR\n",
+			dev, bus_range);
+	} else {
+		if (bus_range->end > bus_range->start + bus_max)
+			bus_range->end = bus_range->start + bus_max;
+	}
+	pci_add_resource(resources, bus_range);
+
+	/* Check for ranges property */
+	err = of_pci_range_parser_init(&parser, dev);
+	if (err)
+		goto parse_failed;
+
+	pr_debug("Parsing ranges property...\n");
+	for_each_of_pci_range(&parser, &range) {
+		/* Read next ranges element */
+		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
+			snprintf(range_type, 4, " IO");
+		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
+			snprintf(range_type, 4, "MEM");
+		else
+			snprintf(range_type, 4, "err");
+		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
+			range.cpu_addr, range.cpu_addr + range.size - 1,
+			range.pci_addr);
+
+		/*
+		 * If we failed translation or got a zero-sized region
+		 * then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		if (!res) {
+			err = -ENOMEM;
+			goto parse_failed;
+		}
+
+		err = of_pci_range_to_resource(&range, dev, res);
+		if (err) {
+			kfree(res);
+			continue;
+		}
+
+		if (resource_type(res) == IORESOURCE_IO) {
+			if (!io_base) {
+				pr_err("I/O range found for %pOF. Please provide an io_base pointer to save CPU base address\n",
+					dev);
+				err = -EINVAL;
+				goto conversion_failed;
+			}
+			if (*io_base != (resource_size_t)OF_BAD_ADDR)
+				pr_warn("More than one I/O resource converted for %pOF. CPU base address for old range lost!\n",
+					dev);
+			*io_base = range.cpu_addr;
+		}
+
+		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
+	}
+
+	return 0;
+
+conversion_failed:
+	kfree(res);
+parse_failed:
+	resource_list_for_each_entry(window, resources)
+		kfree(window->res);
+	pci_free_resource_list(resources);
+	return err;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
+#endif /* CONFIG_OF_ADDRESS */
+
+/**
+ * of_pci_map_rid - Translate a requester ID through a downstream mapping.
+ * @np: root complex device node.
+ * @rid: PCI requester ID to map.
+ * @map_name: property name of the map to use.
+ * @map_mask_name: optional property name of the mask to use.
+ * @target: optional pointer to a target device node.
+ * @id_out: optional pointer to receive the translated ID.
+ *
+ * Given a PCI requester ID, look up the appropriate implementation-defined
+ * platform ID and/or the target device which receives transactions on that
+ * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
+ * @id_out may be NULL if only the other is required. If @target points to
+ * a non-NULL device node pointer, only entries targeting that node will be
+ * matched; if it points to a NULL value, it will receive the device node of
+ * the first matching target phandle, with a reference held.
+ *
+ * Return: 0 on success or a standard error code on failure.
+ */
+int of_pci_map_rid(struct device_node *np, u32 rid,
+		   const char *map_name, const char *map_mask_name,
+		   struct device_node **target, u32 *id_out)
+{
+	u32 map_mask, masked_rid;
+	int map_len;
+	const __be32 *map = NULL;
+
+	if (!np || !map_name || (!target && !id_out))
+		return -EINVAL;
+
+	map = of_get_property(np, map_name, &map_len);
+	if (!map) {
+		if (target)
+			return -ENODEV;
+		/* Otherwise, no map implies no translation */
+		*id_out = rid;
+		return 0;
+	}
+
+	if (!map_len || map_len % (4 * sizeof(*map))) {
+		pr_err("%pOF: Error: Bad %s length: %d\n", np,
+			map_name, map_len);
+		return -EINVAL;
+	}
+
+	/* The default is to select all bits. */
+	map_mask = 0xffffffff;
+
+	/*
+	 * Can be overridden by "{iommu,msi}-map-mask" property.
+	 * If of_property_read_u32() fails, the default is used.
+	 */
+	if (map_mask_name)
+		of_property_read_u32(np, map_mask_name, &map_mask);
+
+	masked_rid = map_mask & rid;
+	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
+		struct device_node *phandle_node;
+		u32 rid_base = be32_to_cpup(map + 0);
+		u32 phandle = be32_to_cpup(map + 1);
+		u32 out_base = be32_to_cpup(map + 2);
+		u32 rid_len = be32_to_cpup(map + 3);
+
+		if (rid_base & ~map_mask) {
+			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n",
+				np, map_name, map_name,
+				map_mask, rid_base);
+			return -EFAULT;
+		}
+
+		if (masked_rid < rid_base || masked_rid >= rid_base + rid_len)
+			continue;
+
+		phandle_node = of_find_node_by_phandle(phandle);
+		if (!phandle_node)
+			return -ENODEV;
+
+		if (target) {
+			if (*target)
+				of_node_put(phandle_node);
+			else
+				*target = phandle_node;
+
+			if (*target != phandle_node)
+				continue;
+		}
+
+		if (id_out)
+			*id_out = masked_rid - rid_base + out_base;
+
+		pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n",
+			np, map_name, map_mask, rid_base, out_base,
+			rid_len, rid, masked_rid - rid_base + out_base);
+		return 0;
+	}
+
+	pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n",
+		np, map_name, rid, target && *target ? *target : NULL);
+	return -EFAULT;
+}
+
+#if IS_ENABLED(CONFIG_OF_IRQ)
+/**
+ * of_irq_parse_pci - Resolve the interrupt for a PCI device
+ * @pdev:       the device whose interrupt is to be resolved
+ * @out_irq:    structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
+{
+	struct device_node *dn, *ppnode;
+	struct pci_dev *ppdev;
+	__be32 laddr[3];
+	u8 pin;
+	int rc;
+
+	/* Check if we have a device node, if yes, fallback to standard
+	 * device tree parsing
+	 */
+	dn = pci_device_to_OF_node(pdev);
+	if (dn) {
+		rc = of_irq_parse_one(dn, 0, out_irq);
+		if (!rc)
+			return rc;
+	}
+
+	/* Ok, we don't, time to have fun. Let's start by building up an
+	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
+	 * for PCI. If you do different, then don't use that routine.
+	 */
+	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+	if (rc != 0)
+		goto err;
+	/* No pin, exit with no error message. */
+	if (pin == 0)
+		return -ENODEV;
+
+	/* Now we walk up the PCI tree */
+	for (;;) {
+		/* Get the pci_dev of our parent */
+		ppdev = pdev->bus->self;
+
+		/* Ouch, it's a host bridge... */
+		if (ppdev == NULL) {
+			ppnode = pci_bus_to_OF_node(pdev->bus);
+
+			/* No node for host bridge ? give up */
+			if (ppnode == NULL) {
+				rc = -EINVAL;
+				goto err;
+			}
+		} else {
+			/* We found a P2P bridge, check if it has a node */
+			ppnode = pci_device_to_OF_node(ppdev);
+		}
+
+		/* Ok, we have found a parent with a device-node, hand over to
+		 * the OF parsing code.
+		 * We build a unit address from the linux device to be used for
+		 * resolution. Note that we use the linux bus number which may
+		 * not match your firmware bus numbering.
+		 * Fortunately, in most cases, interrupt-map-mask doesn't
+		 * include the bus number as part of the matching.
+		 * You should still be careful about that though if you intend
+		 * to rely on this function (you ship  a firmware that doesn't
+		 * create device nodes for all PCI devices).
+		 */
+		if (ppnode)
+			break;
+
+		/* We can only get here if we hit a P2P bridge with no node,
+		 * let's do standard swizzling and try again
+		 */
+		pin = pci_swizzle_interrupt_pin(pdev, pin);
+		pdev = ppdev;
+	}
+
+	out_irq->np = ppnode;
+	out_irq->args_count = 1;
+	out_irq->args[0] = pin;
+	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+	laddr[1] = laddr[2] = cpu_to_be32(0);
+	rc = of_irq_parse_raw(laddr, out_irq);
+	if (rc)
+		goto err;
+	return 0;
+err:
+	if (rc == -ENOENT) {
+		dev_warn(&pdev->dev,
+			"%s: no interrupt-map found, INTx interrupts not available\n",
+			__func__);
+		pr_warn_once("%s: possibly some PCI slots don't have level triggered interrupts capability\n",
+			__func__);
+	} else {
+		dev_err(&pdev->dev, "%s: failed with rc=%d\n", __func__, rc);
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(of_irq_parse_pci);
+
+/**
+ * of_irq_parse_and_map_pci() - Decode a PCI irq from the device tree and map to a virq
+ * @dev: The pci device needing an irq
+ * @slot: PCI slot number; passed when used as map_irq callback. Unused
+ * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
+ *
+ * @slot and @pin are unused, but included in the function so that this
+ * function can be used directly as the map_irq callback to
+ * pci_assign_irq() and struct pci_host_bridge.map_irq pointer
+ */
+int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct of_phandle_args oirq;
+	int ret;
+
+	ret = of_irq_parse_pci(dev, &oirq);
+	if (ret)
+		return 0; /* Proper return code 0 == NO_IRQ */
+
+	return irq_create_of_mapping(&oirq);
+}
+EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
+#endif	/* CONFIG_OF_IRQ */
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index bf588a05d0d0..f0e129e848ea 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -9,7 +9,7 @@ struct pci_dev;
 struct of_phandle_args;
 struct device_node;
 
-#ifdef CONFIG_OF_PCI
+#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PCI)
 int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
 struct device_node *of_pci_find_child_device(struct device_node *parent,
 					     unsigned int devfn);
-- 
2.14.1

^ permalink raw reply related

* [PATCH 0/3] PCI: move DT PCI functions to PCI core
From: Rob Herring @ 2018-01-04 21:12 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: devicetree, linux-kernel, Benjamin Herrenschmidt, Paul Mackerras,
	Michael Ellerman, Frank Rowand, linuxppc-dev, linux-pci

Most subsystem specific functions have been moved into the respective
subsystems. Only PCI and networking remain. This series moves most of the
PCI related code to drivers/pci/of.c. Some bus address functions for PCI
remain in of/address.c because we don't have infrastructure to split up
the per bus helper functions.

I expect Bjorn to take this series, so PPC maintainers please ack.

Rob

Rob Herring (3):
  PCI: move OF related PCI functions into PCI core
  powerpc/pci: use of_irq_parse_and_map_pci helper
  PCI: make of_irq_parse_pci static

 arch/arm/mach-mvebu/Kconfig      |   1 -
 arch/powerpc/kernel/pci-common.c |   8 +-
 drivers/of/Kconfig               |  16 --
 drivers/of/Makefile              |   2 -
 drivers/of/address.c             |   8 +-
 drivers/of/of_pci.c              | 384 -----------------------------
 drivers/of/of_pci_irq.c          | 131 ----------
 drivers/pci/of.c                 | 505 +++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h           |   8 +-
 9 files changed, 510 insertions(+), 553 deletions(-)
 delete mode 100644 drivers/of/of_pci.c
 delete mode 100644 drivers/of/of_pci_irq.c

--
2.14.1

^ permalink raw reply

* Re: [PATCH v1 11/15] ASoC: fsl_ssi: Setup AC97 in dai_probe()
From: Nicolin Chen @ 2018-01-04 20:58 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: timur, broonie, linux-kernel, linuxppc-dev, alsa-devel, lgirdwood,
	fabio.estevam, caleb, arnaud.mouiche, lukma, kernel
In-Reply-To: <61acf616-dd63-bccd-2c91-ce244b799f09@maciej.szmigiero.name>

On Thu, Jan 04, 2018 at 09:38:52PM +0100, Maciej S. Szmigiero wrote:

> > Hmm...What's the dependency here? Why is it required like this?

> And a AC'97 CODEC probe needs AC'97 communication to be working,
> since it has to detect the CODEC model, configure it, etc.

Okay. If the CODEC configurations depend on (or are done via)
the AC link, it has to be in this way then.

> > I am okay to put everything to a separate fsl_ssi_hw_init() and
> > move it back to the platform probe() though.
> 
> This could be a solution - I assume that by "everything" in the above
> sentence you mean (at least) enabling the AC'97 communication at the
> SSI.

All register configurations -- I was trying to move them to dai
probe() so a deferring probe or the platform remove() does not
need to revert these register configurations.

^ permalink raw reply

* Re: [PATCH] ps3_gelic_net: Delete an error message for a failed memory allocation in gelic_descr_prepare_rx()
From: Geoff Levand @ 2018-01-04 20:44 UTC (permalink / raw)
  To: SF Markus Elfring, netdev, linuxppc-dev, Benjamin Herrenschmidt,
	Michael Ellerman, Paul Mackerras
  Cc: kernel-janitors, LKML
In-Reply-To: <9613bfbf-11cc-1e66-484a-84fcda022861@users.sourceforge.net>

On 01/03/2018 06:40 AM, SF Markus Elfring wrote:
> Omit an extra message for a memory allocation failure in this function.

I applied this to my ps3-queue branch.

As I mentioned to you several times before, please keep
the commit subject line to less than 50 characters.
Also, in this case the prefix would be 'net/ps3_gelic_net:"

-Geoff

^ permalink raw reply

* Re: [PATCH v1 11/15] ASoC: fsl_ssi: Setup AC97 in dai_probe()
From: Maciej S. Szmigiero @ 2018-01-04 20:38 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: timur, broonie, linux-kernel, linuxppc-dev, alsa-devel, lgirdwood,
	fabio.estevam, caleb, arnaud.mouiche, lukma, kernel
In-Reply-To: <20180104190732.GA27975@Asurada-Nvidia>

On 04.01.2018 20:07, Nicolin Chen wrote:
> On Mon, Jan 01, 2018 at 04:17:20PM +0100, Maciej S. Szmigiero wrote:
>>> AC97 configures some registers earlier to start a communication
>>> with CODECs, so this patch moves those register settings to the
>>> dai_probe() as well, along with other register configurations.
>  
>> This patch breaks AC'97 CODEC probing.
>>
>> Namely, the fsl_ssi DAI probe callback is only called after the AC'97
>> CODEC probe callback, so when you move SSI AC'97 startup to its DAI
>> probe callback it won't be done yet when the CODEC is probed (and this
>> requires a working AC'97 interface to successfully complete).
> 
> Hmm...What's the dependency here? Why is it required like this?

This patch moves enabling AC'97 communication (done by
fsl_ssi_setup_ac97() ) from SSI _platform device_ probe path to
SSI _DAI_ probe path.

However, it turns out that a SSI _DAI_ probe happens after a AC'97
CODEC probe (that is, ac97_soc_probe() in sound/soc/codecs/ac97.c).
And a AC'97 CODEC probe needs AC'97 communication to be working,
since it has to detect the CODEC model, configure it, etc.

> I am okay to put everything to a separate fsl_ssi_hw_init() and
> move it back to the platform probe() though.
> 

This could be a solution - I assume that by "everything" in the above
sentence you mean (at least) enabling the AC'97 communication at the
SSI.

Maciej

^ permalink raw reply

* Re: [PATCH v1 00/15] ASoC: fsl_ssi: Clean up - program flow level
From: Caleb Crome @ 2018-01-04 19:50 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: Timur Tabi, Mark Brown, linux-kernel, linuxppc-dev, alsa-devel,
	Liam Girdwood, Fabio Estevam, mail, Arnaud Mouiche, lukma,
	Sascha Hauer
In-Reply-To: <20180104194842.GE27975@Asurada-Nvidia>

On Thu, Jan 4, 2018 at 11:48 AM, Nicolin Chen <nicoleotsuka@gmail.com> wrote:
> On Tue, Jan 02, 2018 at 03:28:11PM -0800, Caleb Crome wrote:
>
>> tested this patch set on MX6 SSI against broonie for-next (4.15-rc5),
>> no problems.
>> Do I send a separate Tested-by for each patch, or just the 00/15 one?
>
>> Tested-by: Caleb Crome <caleb@crome.org>
>
> I will include your Tested-by to each patch in v2 unless there is
> going to be a critical change suggested by the future reviews so
> that we need another round of full testing. Thank you

Great.

-Caleb

^ permalink raw reply

* Re: [PATCH v1 00/15] ASoC: fsl_ssi: Clean up - program flow level
From: Nicolin Chen @ 2018-01-04 19:48 UTC (permalink / raw)
  To: Caleb Crome
  Cc: Timur Tabi, Mark Brown, linux-kernel, linuxppc-dev, alsa-devel,
	Liam Girdwood, Fabio Estevam, mail, Arnaud Mouiche, lukma,
	Sascha Hauer
In-Reply-To: <CAG5mAdxBOvrE3U-PAZVKepZfTZc91kKOLrC_UoMnBsoZvJ9hyA@mail.gmail.com>

On Tue, Jan 02, 2018 at 03:28:11PM -0800, Caleb Crome wrote:

> tested this patch set on MX6 SSI against broonie for-next (4.15-rc5),
> no problems.
> Do I send a separate Tested-by for each patch, or just the 00/15 one?
 
> Tested-by: Caleb Crome <caleb@crome.org>

I will include your Tested-by to each patch in v2 unless there is
going to be a critical change suggested by the future reviews so
that we need another round of full testing. Thank you.

^ permalink raw reply

* Re: [PATCH v1 05/15] ASoC: fsl_ssi: Clean up helper functions of trigger()
From: Nicolin Chen @ 2018-01-04 19:44 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: timur, broonie, linux-kernel, linuxppc-dev, alsa-devel, lgirdwood,
	fabio.estevam, caleb, arnaud.mouiche, lukma, kernel
In-Reply-To: <59aa58b7-aeda-ef87-e150-9fec9c6229ae@maciej.szmigiero.name>

On Mon, Jan 01, 2018 at 10:59:30PM +0100, Maciej S. Szmigiero wrote:

> > +static void fsl_ssi_config_enable(struct fsl_ssi *ssi, bool tx)

> > +		srcr = vals[tx].srcr;
> > +		stcr = vals[tx].stcr;
> > +		sier = vals[tx].sier;
> 
> Implicit assumption here that RX == 0, TX == 1, as in the 03 patch.

Could replace it with "bool dir" as well. Thanks for the review.

^ permalink raw reply

* Re: [PATCH v1 03/15] ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro
From: Nicolin Chen @ 2018-01-04 19:42 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: timur, broonie, linux-kernel, linuxppc-dev, alsa-devel, lgirdwood,
	fabio.estevam, caleb, arnaud.mouiche, lukma, kernel
In-Reply-To: <7509f512-1c7f-2fd2-e127-510106e2d9d5@maciej.szmigiero.name>

On Mon, Jan 01, 2018 at 10:29:24PM +0100, Maciej S. Szmigiero wrote:

> > @@ -445,16 +445,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
> >  	bool tx = &ssi->regvals[TX] == vals;

> > +	/* Check if the opposite stream is active */
> > +	aactive = ssi->streams & BIT(!tx);
> 
> I don't think that hardcoding an implicit assumption here that RX == 0,
> TX == 1 is a good thing.
> If in the future, for any reason, somebody changes values of these macros
> this code will silently break.
> 
> I would instead change this line into something like
> "aactive = ssi->streams & (tx ? BIT(RX) : BIT(TX));" or similar.

You have a point. I could add a "bool dir" to make it clear. Thanks.

^ permalink raw reply

* Re: [PATCH v1 01/15] ASoC: fsl_ssi: Clean up set_dai_tdm_slot()
From: Nicolin Chen @ 2018-01-04 19:08 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: timur, broonie, linux-kernel, linuxppc-dev, alsa-devel, lgirdwood,
	fabio.estevam, caleb, arnaud.mouiche, lukma, kernel
In-Reply-To: <b910e12c-bee7-18ba-f878-bece9a9f9cc1@maciej.szmigiero.name>

On Mon, Jan 01, 2018 at 07:39:52PM +0100, Maciej S. Szmigiero wrote:

> >  	/* The slot number should be >= 2 if using Network mode or I2S mode */
> > -	regmap_read(regs, REG_SSI_SCR, &val);
> > -	val &= SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET;
> > -	if (val && slots < 2) {
> > +	if (ssi->i2s_net && slots < 2) {
> >  		dev_err(dai->dev, "slot number should be >= 2 in I2S or NET\n");
> >  		return -EINVAL;
> >  	}
> 
> Are you sure that ssi->i2s_net SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET bits
> (also known as SSI_SCR_I2S_NET_MASK) zero or non-zero status is always
> consistent with that in the SCR register?
> 
> I can see that in fsl_ssi_hw_params() these bits in SCR are zeroed in
> a one special case and in the second special case they are hardcoded
> to SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET, in both cases regardless of
> what is currently in ssi->i2s_net.

You are right. I should update the i2s_net in hw_params() too. Thanks!

^ permalink raw reply

* Re: [PATCH v1 11/15] ASoC: fsl_ssi: Setup AC97 in dai_probe()
From: Nicolin Chen @ 2018-01-04 19:07 UTC (permalink / raw)
  To: Maciej S. Szmigiero
  Cc: timur, broonie, linux-kernel, linuxppc-dev, alsa-devel, lgirdwood,
	fabio.estevam, caleb, arnaud.mouiche, lukma, kernel
In-Reply-To: <b8e41d81-948a-fbac-af75-3e31c3382426@maciej.szmigiero.name>

On Mon, Jan 01, 2018 at 04:17:20PM +0100, Maciej S. Szmigiero wrote:
> > AC97 configures some registers earlier to start a communication
> > with CODECs, so this patch moves those register settings to the
> > dai_probe() as well, along with other register configurations.
 
> This patch breaks AC'97 CODEC probing.
> 
> Namely, the fsl_ssi DAI probe callback is only called after the AC'97
> CODEC probe callback, so when you move SSI AC'97 startup to its DAI
> probe callback it won't be done yet when the CODEC is probed (and this
> requires a working AC'97 interface to successfully complete).

Hmm...What's the dependency here? Why is it required like this?
I am okay to put everything to a separate fsl_ssi_hw_init() and
move it back to the platform probe() though.

^ permalink raw reply

* Re: [PATCH v3] powerpc/64s: Improve local TLB flush for boot and MCE on POWER9
From: Nicholas Piggin @ 2018-01-04 18:11 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: linuxppc-dev
In-Reply-To: <87d12r2zjx.fsf@linux.vnet.ibm.com>

On Wed, 03 Jan 2018 12:34:34 +0530
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:

> Nicholas Piggin <npiggin@gmail.com> writes:
> 
> > There are several cases outside the normal address space management
> > where a CPU's entire local TLB is to be flushed:
> >
> >   1. Booting the kernel, in case something has left stale entries in
> >      the TLB (e.g., kexec).
> >
> >   2. Machine check, to clean corrupted TLB entries.
> >
> > One other place where the TLB is flushed, is waking from deep idle
> > states. The flush is a side-effect of calling ->cpu_restore with the
> > intention of re-setting various SPRs. The flush itself is unnecessary
> > because in the first case, the TLB should not acquire new corrupted
> > TLB entries as part of sleep/wake (though they may be lost).
> >
> > This type of TLB flush is coded inflexibly, several times for each CPU
> > type, and they have a number of problems with ISA v3.0B:
> >
> > - The current radix mode of the MMU is not taken into account, it is
> >   always done as a hash flushn For IS=2 (LPID-matching flush from host)
> >   and IS=3 with HV=0 (guest kernel flush), tlbie(l) is undefined if
> >   the R field does not match the current radix mode.
> >
> > - ISA v3.0B hash must flush the partition and process table caches as
> >   well.
> >
> > - ISA v3.0B radix must flush partition and process scoped translations,
> >   partition and process table caches, and also the page walk cache.
> >
> > So consolidate the flushing code and implement it in C and inline asm
> > under the mm/ directory with the rest of the flush code. Add ISA v3.0B
> > cases for radix and hash, and use the radix flush in radix environment.
> >
> > Provide a way for IS=2 (LPID flush) to specify the radix mode of the
> > partition. Have KVM pass in the radix mode of the guest.
> >
> > Take out the flushes from early cputable/dt_cpu_ftrs detection hooks,
> > and move it later in the boot process after, the MMU registers are set
> > up and before relocation is first turned on.
> >
> > The TLB flush is no longer called when restoring from deep idle states.
> > This was not be done as a separate step because booting secondaries
> > uses the same cpu_restore as idle restore, which needs the TLB flush.
> >
> > Signed-off-by: Nicholas Piggin <npiggin@gmail.com>  
> 
> ......
> 
> > diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
> > index c356f9a40b24..e61066bb6725 100644
> > --- a/arch/powerpc/kvm/book3s_hv_ras.c
> > +++ b/arch/powerpc/kvm/book3s_hv_ras.c
> > @@ -87,8 +87,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
> >  				   DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
> >  		}
> >  		if (dsisr & DSISR_MC_TLB_MULTI) {
> > -			if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
> > -				cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_LPID);
> > +			tlbiel_all_lpid(vcpu->kvm->arch.radix);  
> 
> Why use vcpu->kvm-arch.radix? why not TLB_INVAL_SCOPE_LPID?

tlbiel_all_lpid always does TLB_INVAL_SCOPE_LPID. The radix field needs to
be supplied to LPID flushes because by the ISA, the operation is undefined
if R field does not match the radix mode of the target partition. This is
the first dot point of problems in the changelog.

Thanks,
Nick

^ permalink raw reply

* [PATCH] powerpc: restore alphabetic order in Kconfig
From: Christophe Leroy @ 2018-01-04 15:35 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	Scott Wood, Balbir Singh
  Cc: linux-kernel, linuxppc-dev

This patch restores the alphabetic order which was broken by
commit 1e0fc9d1eb2b0 ("powerpc/Kconfig: Enable STRICT_KERNEL_RWX
for some configs")

Fixes: 1e0fc9d1eb2b0 ("powerpc/Kconfig: Enable STRICT_KERNEL_RWX for some configs")
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 arch/powerpc/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 00417150185c..80c285f80f7c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -142,6 +142,7 @@ config PPC
 	select ARCH_HAS_PMEM_API                if PPC64
 	select ARCH_HAS_SCALED_CPUTIME		if VIRT_CPU_ACCOUNTING_NATIVE
 	select ARCH_HAS_SG_CHAIN
+	select ARCH_HAS_STRICT_KERNEL_RWX	if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION)
 	select ARCH_HAS_TICK_BROADCAST		if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_HAS_UACCESS_FLUSHCACHE	if PPC64
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
@@ -149,6 +150,7 @@ config PPC
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
+	select ARCH_OPTIONAL_KERNEL_RWX		if ARCH_HAS_STRICT_KERNEL_RWX
 	select ARCH_SUPPORTS_ATOMIC_RMW
 	select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
 	select ARCH_USE_BUILTIN_BSWAP
@@ -179,8 +181,6 @@ config PPC
 	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if COMPAT
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
-	select ARCH_HAS_STRICT_KERNEL_RWX	if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION)
-	select ARCH_OPTIONAL_KERNEL_RWX		if ARCH_HAS_STRICT_KERNEL_RWX
 	select HAVE_CBPF_JIT			if !PPC64
 	select HAVE_CONTEXT_TRACKING		if PPC64
 	select HAVE_DEBUG_KMEMLEAK
-- 
2.13.3

^ permalink raw reply related

* Spectre+Meltdown
From: Christian Zigotzky @ 2018-01-04 15:09 UTC (permalink / raw)
  To: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 375 bytes --]

Hi All,

Do we have some information regarding Spectre+Meltdown for our users?

It could be that we have some security issues in our PowerPC CPUs.

Links:

https://www.phoronix.com/scan.php?page=news_item&px=Linux-Kernel-Retpoline-Patches

https://www.phoronix.com/scan.php?page=news_item&px=x86-PTI-EPYC-Linux-4.15-Test

Thanks,
Christian

Sent from my iPhone

[-- Attachment #2: Type: text/html, Size: 1795 bytes --]

^ permalink raw reply

* Re: [PATCH 30/67] dma-direct: retry allocations using GFP_DMA for small masks
From: Christoph Hellwig @ 2018-01-04  9:02 UTC (permalink / raw)
  To: Vladimir Murzin
  Cc: Christoph Hellwig, iommu, linux-mips, linux-ia64, linux-sh,
	sparclinux, Guan Xuetao, linux-arch, linux-s390, linux-c6x-dev,
	linux-hexagon, x86, linux-snps-arc, adi-buildroot-devel,
	linux-m68k, patches, linux-metag, linux-arm-kernel, Michal Simek,
	linux-parisc, linux-cris-kernel, linux-kernel, linux-alpha,
	linuxppc-dev
In-Reply-To: <f6139b03-0a4a-a9fe-4818-9b0bccf419e4@arm.com>

On Tue, Jan 02, 2018 at 04:43:15PM +0000, Vladimir Murzin wrote:
> On 29/12/17 08:18, Christoph Hellwig wrote:
> > If we got back an allocation that wasn't inside the support coherent mask,
> > retry the allocation using GFP_DMA.
> > 
> > Based on the x86 code.
> > 
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
> > ---
> >  lib/dma-direct.c | 25 ++++++++++++++++++++++++-
> >  1 file changed, 24 insertions(+), 1 deletion(-)
> > 
> > diff --git a/lib/dma-direct.c b/lib/dma-direct.c
> > index ab81de3ac1d3..f8467cb3d89a 100644
> > --- a/lib/dma-direct.c
> > +++ b/lib/dma-direct.c
> > @@ -28,6 +28,11 @@ check_addr(struct device *dev, dma_addr_t dma_addr, size_t size,
> >  	return true;
> >  }
> >  
> > +static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
> > +{
> > +	return phys_to_dma(dev, phys) + size <= dev->coherent_dma_mask;
> 
> Shouldn't it be: phys_to_dma(dev, phys) + size - 1 <= dev->coherent_dma_mask ?

Yes, I think it should.  The existing code was blindly copy and pasted
from x86.

> > +	if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
> > +		__free_pages(page, page_order);
> > +		page = NULL;
> > +
> > +		if (dev->coherent_dma_mask < DMA_BIT_MASK(32) &&
> > +		    !(gfp & GFP_DMA)) {
> > +			gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
> > +			goto again;
> 
> Shouldn't we limit number of attempts?

We only retty once anyway, due to the !GFP_DMA check first and then
ORing in GFP_DMA.

^ permalink raw reply

* Re: [PATCH 02/67] alpha: mark jensen as broken
From: Christoph Hellwig @ 2018-01-04  8:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Christoph Hellwig, iommu, alpha, arcml, linux-arm-kernel,
	adi-buildroot-devel, linux-c6x-dev, Cris,
	open list:QUALCOMM HEXAGON..., linux-ia64, linux-m68k,
	open list:METAG ARCHITECTURE, Michal Simek,
	Linux MIPS Mailing List, Parisc List, linuxppc-dev, patches,
	linux-s390, Linux-sh list, sparclinux, Guan Xuetao,
	the arch/x86 maintainers, Linux-Arch, Linux Kernel Mailing List,
	Christian Borntraeger
In-Reply-To: <CAMuHMdUXSMuQ=RoZp86CODVk5Ubd3R+jtqOur_Uqnu+7h_m9AA@mail.gmail.com>

On Tue, Jan 02, 2018 at 11:36:00AM +0100, Geert Uytterhoeven wrote:
> Hi Christoph,
> 
> On Fri, Dec 29, 2017 at 9:18 AM, Christoph Hellwig <hch@lst.de> wrote:
> > CONFIG_ALPHA_JENSEN has failed to compile since commit aca05038
> > ("alpha/dma: use common noop dma ops"), so mark it as broken.
> 
> unknown revision or path not in the working tree.
> Ah, you dropped the leading "6":
> 6aca0503847f6329460b15b3ab2b0e30bb752793
> is less than 2 years old, though.

I'll fix the reference.

But 23 month of a whole sub-architecture not compiling should still be
enough to mark it broken.

^ permalink raw reply

* Re: [PATCH 27/67] dma-direct: add dma address sanity checks
From: Christoph Hellwig @ 2018-01-04  8:52 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Christoph Hellwig, iommu, Linux MIPS Mailing List, linux-ia64,
	Linux-sh list, sparclinux, Guan Xuetao, Linux-Arch, linux-s390,
	linux-c6x-dev, open list:QUALCOMM HEXAGON...,
	the arch/x86 maintainers, arcml, adi-buildroot-devel, linux-m68k,
	patches, open list:METAG ARCHITECTURE, linux-arm-kernel,
	Michal Simek, Parisc List, Cris, Linux Kernel Mailing List, alpha,
	linuxppc-dev
In-Reply-To: <CAMuHMdWg3PnTXezMCcr3oGf-83-cjvcj4wGiPk7j2pY1Tgzo9Q@mail.gmail.com>

On Fri, Dec 29, 2017 at 03:12:25PM +0100, Geert Uytterhoeven wrote:
> > +check_addr(struct device *dev, dma_addr_t dma_addr, size_t size,
> > +               const char *caller)
> > +{
> > +       if (unlikely(dev && !dma_capable(dev, dma_addr, size))) {
> > +               if (*dev->dma_mask >= DMA_BIT_MASK(32)) {
> > +                       dev_err(dev,
> > +                               "%s: overflow %llx+%zu of device mask %llx\n",
> 
> Please use "%pad" to format dma_addr_t ...
> 
> > +                               caller, (long long)dma_addr, size,
> 
> ... and use &dma_addr.
> 
> > +                               (long long)*dev->dma_mask);
> 
> This cast is not needed, as u64 is unsigned long long in kernelspace on
> all architectures.

Thanks, fixed.

^ permalink raw reply

* Re: [PATCH 16/67] powerpc: rename dma_direct_ to dma_nommu_
From: Christoph Hellwig @ 2018-01-04  8:49 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christoph Hellwig, iommu, linux-mips, linux-ia64, linux-sh,
	sparclinux, Guan Xuetao, linux-arch, linux-s390, linux-c6x-dev,
	linux-hexagon, x86, linux-snps-arc, adi-buildroot-devel,
	linux-m68k, patches, linux-metag, linux-arm-kernel, Michal Simek,
	linux-parisc, linux-cris-kernel, linux-kernel, linux-alpha,
	linuxppc-dev
In-Reply-To: <878tdgtwzp.fsf@concordia.ellerman.id.au>

On Tue, Jan 02, 2018 at 08:45:30PM +1100, Michael Ellerman wrote:
> Christoph Hellwig <hch@lst.de> writes:
> 
> > We want to use the dma_direct_ namespace for a generic implementation,
> > so rename powerpc to the second best choice: dma_nommu_.
> 
> I'm not a fan of "nommu". Some of the users of direct ops *are* using an
> IOMMU, they're just setting up a 1:1 mapping once at init time, rather
> than mapping dynamically.
> 
> Though I don't have a good idea for a better name, maybe "1to1",
> "linear", "premapped" ?

It seems like a nice counter part to the dma_iommu_ops used just about
anywhere else in ppc.

But I'll happily take any maintainer bike shed decision for the next
series.  Remember that in a merge window or two it will hopefully
go away in favor of the new generic dma_direct ops.

^ permalink raw reply

* Re: [PATCH 16/67] powerpc: rename dma_direct_ to dma_nommu_
From: Christoph Hellwig @ 2018-01-04  8:48 UTC (permalink / raw)
  To: Julian Calaby
  Cc: Geert Uytterhoeven, Michael Ellerman, Christoph Hellwig, iommu,
	Linux MIPS Mailing List, linux-ia64, Linux-sh list, sparclinux,
	Guan Xuetao, Linux-Arch, linux-s390, linux-c6x-dev,
	open list:QUALCOMM HEXAGON..., the arch/x86 maintainers, arcml,
	adi-buildroot-devel, linux-m68k, patches,
	open list:METAG ARCHITECTURE, Mailing List, Arm, Michal Simek,
	Parisc List, Cris, Linux Kernel Mailing List, alpha, linuxppc-dev
In-Reply-To: <CAGRGNgV+DnZAAtiE5oe8rxp4=_JHJrtSQc8F5jrgN0rgYKfwjA@mail.gmail.com>

On Wed, Jan 03, 2018 at 07:19:46PM +1100, Julian Calaby wrote:
> If this is indeed a linear mapping, can we just remove this and
> replace it with the new "generic" mapping being introduced by this
> patchset?

That is the long-term plan.  But as the powerpc one includes support
for non-coherent DMA it will have to wait for the next batch.

^ permalink raw reply

* Re: [PATCH 17/67] microblaze: rename dma_direct to dma_microblaze
From: Christoph Hellwig @ 2018-01-04  8:45 UTC (permalink / raw)
  To: Julian Calaby
  Cc: Christoph Hellwig, iommu, linux-alpha, linux-snps-arc,
	Mailing List, Arm, adi-buildroot-devel, linux-c6x-dev,
	linux-cris-kernel, linux-hexagon, linux-ia64, linux-m68k,
	linux-metag, Michal Simek, linux-mips, linux-parisc, linuxppc-dev,
	patches, linux-s390, linux-sh, sparclinux, Guan Xuetao, x86,
	linux-arch, linux-kernel@vger.kernel.org
In-Reply-To: <CAGRGNgW1qwLcCAvU2Jc=3_7b-0Bu016to3cQUgVsc+ca0No_6g@mail.gmail.com>

On Fri, Dec 29, 2017 at 09:11:56PM +1100, Julian Calaby wrote:
> Hi Christoph,
> 
> On Fri, Dec 29, 2017 at 7:18 PM, Christoph Hellwig <hch@lst.de> wrote:
> > This frees the dma_direct_* namespace for a generic implementation.
> 
> Don't you mean "dma_nommu" not "dma_microblaze" in the subject line?

Yes, thanks.

^ permalink raw reply

* Re: [PATCH 1/6] cxlflash: Reset command ioasc
From: Andrew Donnellan @ 2018-01-04  6:33 UTC (permalink / raw)
  To: Uma Krishnan, linux-scsi, James Bottomley, Martin K. Petersen,
	Matthew R. Ochs, Manoj N. Kumar
  Cc: linuxppc-dev, Frederic Barrat, Christophe Lombard
In-Reply-To: <1515020042-43590-1-git-send-email-ukrishn@linux.vnet.ibm.com>

On 04/01/18 09:54, Uma Krishnan wrote:
> In the event of a command failure, cxlflash returns the failure to the
> upper layers to process. After processing the error, when the command is
> queued again, the private command structure will not be zeroed and the
> ioasc could be stale. Per the SISLite specification, the AFU only sets the
> ioasc in the presence of a failure. Thus, even though the original command
> succeeds the second time, the command is considered a failure due to stale
> ioasc. This cycle repeats indefinitely and can cause a hang or IO failure.
> 
> To fix the issue, clear the ioasc before queuing any command.
> 
> Fixes: 479ad8e9d48c ("scsi: cxlflash: Remove zeroing of private command
> data")
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Should this go to stable?


> ---
>   drivers/scsi/cxlflash/main.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
> index 38b3a9c..48d3663 100644
> --- a/drivers/scsi/cxlflash/main.c
> +++ b/drivers/scsi/cxlflash/main.c
> @@ -620,6 +620,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
>   	cmd->parent = afu;
>   	cmd->hwq_index = hwq_index;
> 
> +	cmd->sa.ioasc = 0;
>   	cmd->rcb.ctx_id = hwq->ctx_hndl;
>   	cmd->rcb.msi = SISL_MSI_RRQ_UPDATED;
>   	cmd->rcb.port_sel = CHAN2PORTMASK(scp->device->channel);
> 

-- 
Andrew Donnellan              OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com  IBM Australia Limited

^ permalink raw reply

* Re: [PATCH v3 1/1] powerpc/pseries: Make RAS IRQ explicitly dependent on DLPAR WQ
From: David Gibson @ 2018-01-04  0:48 UTC (permalink / raw)
  To: Jose Ricardo Ziviani; +Cc: linuxppc-dev, mpe, benh
In-Reply-To: <20180103211252.24615-2-joserz@linux.vnet.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 1099 bytes --]

On Wed, Jan 03, 2018 at 07:12:52PM -0200, Jose Ricardo Ziviani wrote:
> The hotplug engine uses its own workqueue to handle IRQ requests, the
> problem is that such workqueue is initialized after init_ras_IRQ, which
> will cause a kernel panic if any hotplug interruption is issued in that
> period of time.
> 
> This patch makes RAS IRQ registration explicitly dependent on DLPAR
> workqueue and adds a check to make sure that the workqueue is not
> initialized more than once.
> 
> Reported-by: Min Deng <mdeng@redhat.com>
> Reported-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
> Tested-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Michael, If this can be merged to a non-rebasing tree sooner rather
than later, that would be quite helpful to me.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [PATCH 6/6] cxlflash: Staging to support future accelerators
From: Uma Krishnan @ 2018-01-03 22:55 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard
In-Reply-To: <1515020002-43551-1-git-send-email-ukrishn@linux.vnet.ibm.com>

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

As staging to support future accelerator transports, add a shim layer
such that the underlying services the cxlflash driver requires can be
conditional upon the accelerator infrastructure.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/Makefile    |   2 +-
 drivers/scsi/cxlflash/backend.h   |  41 ++++++++++
 drivers/scsi/cxlflash/common.h    |   3 +
 drivers/scsi/cxlflash/cxl_hw.c    | 168 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/cxlflash/main.c      |  79 +++++++-----------
 drivers/scsi/cxlflash/superpipe.c |  48 +++++------
 6 files changed, 263 insertions(+), 78 deletions(-)
 create mode 100644 drivers/scsi/cxlflash/backend.h
 create mode 100644 drivers/scsi/cxlflash/cxl_hw.c

diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile
index 9e39866..7ec3f6b 100644
--- a/drivers/scsi/cxlflash/Makefile
+++ b/drivers/scsi/cxlflash/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_CXLFLASH) += cxlflash.o
-cxlflash-y += main.o superpipe.o lunmgt.o vlun.o
+cxlflash-y += main.o superpipe.o lunmgt.o vlun.o cxl_hw.o
diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h
new file mode 100644
index 0000000..339e42b
--- /dev/null
+++ b/drivers/scsi/cxlflash/backend.h
@@ -0,0 +1,41 @@
+/*
+ * CXL Flash Device Driver
+ *
+ * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
+ *             Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
+ *
+ * Copyright (C) 2018 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+extern const struct cxlflash_backend_ops cxlflash_cxl_ops;
+
+struct cxlflash_backend_ops {
+	struct module *module;
+	void __iomem * (*psa_map)(void *);
+	void (*psa_unmap)(void __iomem *);
+	int (*process_element)(void *);
+	int (*map_afu_irq)(void *, int, irq_handler_t, void *, char *);
+	void (*unmap_afu_irq)(void *, int, void *);
+	int (*start_context)(void *);
+	int (*stop_context)(void *);
+	int (*afu_reset)(void *);
+	void (*set_master)(void *);
+	void * (*get_context)(struct pci_dev *, void *);
+	void * (*dev_context_init)(struct pci_dev *, void *);
+	int (*release_context)(void *);
+	void (*perst_reloads_same_image)(void *, bool);
+	ssize_t (*read_adapter_vpd)(struct pci_dev *, void *, size_t);
+	int (*allocate_afu_irqs)(void *, int);
+	void (*free_afu_irqs)(void *);
+	void * (*create_afu)(struct pci_dev *);
+	struct file * (*get_fd)(void *, struct file_operations *, int *);
+	void * (*fops_get_context)(struct file *);
+	int (*start_work)(void *, u64);
+	int (*fd_mmap)(struct file *, struct vm_area_struct *);
+	int (*fd_release)(struct inode *, struct file *);
+};
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 48df89f..102fd26 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -25,6 +25,8 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 
+#include "backend.h"
+
 extern const struct file_operations cxlflash_cxl_fops;
 
 #define MAX_CONTEXT	CXLFLASH_MAX_CONTEXT	/* num contexts per afu */
@@ -114,6 +116,7 @@ enum cxlflash_hwq_mode {
 struct cxlflash_cfg {
 	struct afu *afu;
 
+	const struct cxlflash_backend_ops *ops;
 	struct pci_dev *dev;
 	struct pci_device_id *dev_id;
 	struct Scsi_Host *host;
diff --git a/drivers/scsi/cxlflash/cxl_hw.c b/drivers/scsi/cxlflash/cxl_hw.c
new file mode 100644
index 0000000..db1cada
--- /dev/null
+++ b/drivers/scsi/cxlflash/cxl_hw.c
@@ -0,0 +1,168 @@
+/*
+ * CXL Flash Device Driver
+ *
+ * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
+ *             Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
+ *
+ * Copyright (C) 2018 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <misc/cxl.h>
+
+#include "backend.h"
+
+/*
+ * The following routines map the cxlflash backend operations to existing CXL
+ * kernel API function and are largely simple shims that provide an abstraction
+ * for converting generic context and AFU cookies into cxl_context or cxl_afu
+ * pointers.
+ */
+
+static void __iomem *cxlflash_psa_map(void *ctx_cookie)
+{
+	return cxl_psa_map(ctx_cookie);
+}
+
+static void cxlflash_psa_unmap(void __iomem *addr)
+{
+	cxl_psa_unmap(addr);
+}
+
+static int cxlflash_process_element(void *ctx_cookie)
+{
+	return cxl_process_element(ctx_cookie);
+}
+
+static int cxlflash_map_afu_irq(void *ctx_cookie, int num,
+				irq_handler_t handler, void *cookie, char *name)
+{
+	return cxl_map_afu_irq(ctx_cookie, num, handler, cookie, name);
+}
+
+static void cxlflash_unmap_afu_irq(void *ctx_cookie, int num, void *cookie)
+{
+	cxl_unmap_afu_irq(ctx_cookie, num, cookie);
+}
+
+static int cxlflash_start_context(void *ctx_cookie)
+{
+	return cxl_start_context(ctx_cookie, 0, NULL);
+}
+
+static int cxlflash_stop_context(void *ctx_cookie)
+{
+	return cxl_stop_context(ctx_cookie);
+}
+
+static int cxlflash_afu_reset(void *ctx_cookie)
+{
+	return cxl_afu_reset(ctx_cookie);
+}
+
+static void cxlflash_set_master(void *ctx_cookie)
+{
+	cxl_set_master(ctx_cookie);
+}
+
+static void *cxlflash_get_context(struct pci_dev *dev, void *afu_cookie)
+{
+	return cxl_get_context(dev);
+}
+
+static void *cxlflash_dev_context_init(struct pci_dev *dev, void *afu_cookie)
+{
+	return cxl_dev_context_init(dev);
+}
+
+static int cxlflash_release_context(void *ctx_cookie)
+{
+	return cxl_release_context(ctx_cookie);
+}
+
+static void cxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
+{
+	cxl_perst_reloads_same_image(afu_cookie, image);
+}
+
+static ssize_t cxlflash_read_adapter_vpd(struct pci_dev *dev,
+					 void *buf, size_t count)
+{
+	return cxl_read_adapter_vpd(dev, buf, count);
+}
+
+static int cxlflash_allocate_afu_irqs(void *ctx_cookie, int num)
+{
+	return cxl_allocate_afu_irqs(ctx_cookie, num);
+}
+
+static void cxlflash_free_afu_irqs(void *ctx_cookie)
+{
+	cxl_free_afu_irqs(ctx_cookie);
+}
+
+static void *cxlflash_create_afu(struct pci_dev *dev)
+{
+	return cxl_pci_to_afu(dev);
+}
+
+static struct file *cxlflash_get_fd(void *ctx_cookie,
+				    struct file_operations *fops, int *fd)
+{
+	return cxl_get_fd(ctx_cookie, fops, fd);
+}
+
+static void *cxlflash_fops_get_context(struct file *file)
+{
+	return cxl_fops_get_context(file);
+}
+
+static int cxlflash_start_work(void *ctx_cookie, u64 irqs)
+{
+	struct cxl_ioctl_start_work work = { 0 };
+
+	work.num_interrupts = irqs;
+	work.flags = CXL_START_WORK_NUM_IRQS;
+
+	return cxl_start_work(ctx_cookie, &work);
+}
+
+static int cxlflash_fd_mmap(struct file *file, struct vm_area_struct *vm)
+{
+	return cxl_fd_mmap(file, vm);
+}
+
+static int cxlflash_fd_release(struct inode *inode, struct file *file)
+{
+	return cxl_fd_release(inode, file);
+}
+
+const struct cxlflash_backend_ops cxlflash_cxl_ops = {
+	.module			= THIS_MODULE,
+	.psa_map		= cxlflash_psa_map,
+	.psa_unmap		= cxlflash_psa_unmap,
+	.process_element	= cxlflash_process_element,
+	.map_afu_irq		= cxlflash_map_afu_irq,
+	.unmap_afu_irq		= cxlflash_unmap_afu_irq,
+	.start_context		= cxlflash_start_context,
+	.stop_context		= cxlflash_stop_context,
+	.afu_reset		= cxlflash_afu_reset,
+	.set_master		= cxlflash_set_master,
+	.get_context		= cxlflash_get_context,
+	.dev_context_init	= cxlflash_dev_context_init,
+	.release_context	= cxlflash_release_context,
+	.perst_reloads_same_image = cxlflash_perst_reloads_same_image,
+	.read_adapter_vpd	= cxlflash_read_adapter_vpd,
+	.allocate_afu_irqs	= cxlflash_allocate_afu_irqs,
+	.free_afu_irqs		= cxlflash_free_afu_irqs,
+	.create_afu		= cxlflash_create_afu,
+	.get_fd			= cxlflash_get_fd,
+	.fops_get_context	= cxlflash_fops_get_context,
+	.start_work		= cxlflash_start_work,
+	.fd_mmap		= cxlflash_fd_mmap,
+	.fd_release		= cxlflash_fd_release,
+};
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 32014e8..d8fe7ab8 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -711,7 +711,7 @@ static void stop_afu(struct cxlflash_cfg *cfg)
 		}
 
 		if (likely(afu->afu_map)) {
-			cxl_psa_unmap((void __iomem *)afu->afu_map);
+			cfg->ops->psa_unmap(afu->afu_map);
 			afu->afu_map = NULL;
 		}
 	}
@@ -748,13 +748,13 @@ static void term_intr(struct cxlflash_cfg *cfg, enum undo_level level,
 	case UNMAP_THREE:
 		/* SISL_MSI_ASYNC_ERROR is setup only for the primary HWQ */
 		if (index == PRIMARY_HWQ)
-			cxl_unmap_afu_irq(hwq->ctx_cookie, 3, hwq);
+			cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 3, hwq);
 	case UNMAP_TWO:
-		cxl_unmap_afu_irq(hwq->ctx_cookie, 2, hwq);
+		cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 2, hwq);
 	case UNMAP_ONE:
-		cxl_unmap_afu_irq(hwq->ctx_cookie, 1, hwq);
+		cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 1, hwq);
 	case FREE_IRQ:
-		cxl_free_afu_irqs(hwq->ctx_cookie);
+		cfg->ops->free_afu_irqs(hwq->ctx_cookie);
 		/* fall through */
 	case UNDO_NOOP:
 		/* No action required */
@@ -788,9 +788,9 @@ static void term_mc(struct cxlflash_cfg *cfg, u32 index)
 		return;
 	}
 
-	WARN_ON(cxl_stop_context(hwq->ctx_cookie));
+	WARN_ON(cfg->ops->stop_context(hwq->ctx_cookie));
 	if (index != PRIMARY_HWQ)
-		WARN_ON(cxl_release_context(hwq->ctx_cookie));
+		WARN_ON(cfg->ops->release_context(hwq->ctx_cookie));
 	hwq->ctx_cookie = NULL;
 
 	spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
@@ -1599,25 +1599,6 @@ static irqreturn_t cxlflash_async_err_irq(int irq, void *data)
 }
 
 /**
- * start_context() - starts the master context
- * @cfg:	Internal structure associated with the host.
- * @index:	Index of the hardware queue.
- *
- * Return: A success or failure value from CXL services.
- */
-static int start_context(struct cxlflash_cfg *cfg, u32 index)
-{
-	struct device *dev = &cfg->dev->dev;
-	struct hwq *hwq = get_hwq(cfg->afu, index);
-	int rc = 0;
-
-	rc = cxl_start_context(hwq->ctx_cookie, 0, NULL);
-
-	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
-	return rc;
-}
-
-/**
  * read_vpd() - obtains the WWPNs from VPD
  * @cfg:	Internal structure associated with the host.
  * @wwpn:	Array of size MAX_FC_PORTS to pass back WWPNs
@@ -1639,7 +1620,7 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
 	const char *wwpn_vpd_tags[MAX_FC_PORTS] = { "V5", "V6", "V7", "V8" };
 
 	/* Get the VPD data from the device */
-	vpd_size = cxl_read_adapter_vpd(pdev, vpd_data, sizeof(vpd_data));
+	vpd_size = cfg->ops->read_adapter_vpd(pdev, vpd_data, sizeof(vpd_data));
 	if (unlikely(vpd_size <= 0)) {
 		dev_err(dev, "%s: Unable to read VPD (size = %ld)\n",
 			__func__, vpd_size);
@@ -1731,6 +1712,7 @@ static void init_pcr(struct cxlflash_cfg *cfg)
 	struct afu *afu = cfg->afu;
 	struct sisl_ctrl_map __iomem *ctrl_map;
 	struct hwq *hwq;
+	void *cookie;
 	int i;
 
 	for (i = 0; i < MAX_CONTEXT; i++) {
@@ -1745,8 +1727,9 @@ static void init_pcr(struct cxlflash_cfg *cfg)
 	/* Copy frequently used fields into hwq */
 	for (i = 0; i < afu->num_hwqs; i++) {
 		hwq = get_hwq(afu, i);
+		cookie = hwq->ctx_cookie;
 
-		hwq->ctx_hndl = (u16) cxl_process_element(hwq->ctx_cookie);
+		hwq->ctx_hndl = (u16) cfg->ops->process_element(cookie);
 		hwq->host_map = &afu->afu_map->hosts[hwq->ctx_hndl].host;
 		hwq->ctrl_map = &afu->afu_map->ctrls[hwq->ctx_hndl].ctrl;
 
@@ -1930,7 +1913,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg,
 	bool is_primary_hwq = (hwq->index == PRIMARY_HWQ);
 	int num_irqs = is_primary_hwq ? 3 : 2;
 
-	rc = cxl_allocate_afu_irqs(ctx, num_irqs);
+	rc = cfg->ops->allocate_afu_irqs(ctx, num_irqs);
 	if (unlikely(rc)) {
 		dev_err(dev, "%s: allocate_afu_irqs failed rc=%d\n",
 			__func__, rc);
@@ -1938,16 +1921,16 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg,
 		goto out;
 	}
 
-	rc = cxl_map_afu_irq(ctx, 1, cxlflash_sync_err_irq, hwq,
-			     "SISL_MSI_SYNC_ERROR");
+	rc = cfg->ops->map_afu_irq(ctx, 1, cxlflash_sync_err_irq, hwq,
+				   "SISL_MSI_SYNC_ERROR");
 	if (unlikely(rc <= 0)) {
 		dev_err(dev, "%s: SISL_MSI_SYNC_ERROR map failed\n", __func__);
 		level = FREE_IRQ;
 		goto out;
 	}
 
-	rc = cxl_map_afu_irq(ctx, 2, cxlflash_rrq_irq, hwq,
-			     "SISL_MSI_RRQ_UPDATED");
+	rc = cfg->ops->map_afu_irq(ctx, 2, cxlflash_rrq_irq, hwq,
+				   "SISL_MSI_RRQ_UPDATED");
 	if (unlikely(rc <= 0)) {
 		dev_err(dev, "%s: SISL_MSI_RRQ_UPDATED map failed\n", __func__);
 		level = UNMAP_ONE;
@@ -1958,8 +1941,8 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg,
 	if (!is_primary_hwq)
 		goto out;
 
-	rc = cxl_map_afu_irq(ctx, 3, cxlflash_async_err_irq, hwq,
-			     "SISL_MSI_ASYNC_ERROR");
+	rc = cfg->ops->map_afu_irq(ctx, 3, cxlflash_async_err_irq, hwq,
+				   "SISL_MSI_ASYNC_ERROR");
 	if (unlikely(rc <= 0)) {
 		dev_err(dev, "%s: SISL_MSI_ASYNC_ERROR map failed\n", __func__);
 		level = UNMAP_TWO;
@@ -1989,9 +1972,9 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 	INIT_LIST_HEAD(&hwq->pending_cmds);
 
 	if (index == PRIMARY_HWQ)
-		ctx = cxl_get_context(cfg->dev);
+		ctx = cfg->ops->get_context(cfg->dev, cfg->afu_cookie);
 	else
-		ctx = cxl_dev_context_init(cfg->dev);
+		ctx = cfg->ops->dev_context_init(cfg->dev, cfg->afu_cookie);
 	if (IS_ERR_OR_NULL(ctx)) {
 		rc = -ENOMEM;
 		goto err1;
@@ -2001,11 +1984,11 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 	hwq->ctx_cookie = ctx;
 
 	/* Set it up as a master with the CXL */
-	cxl_set_master(ctx);
+	cfg->ops->set_master(ctx);
 
 	/* Reset AFU when initializing primary context */
 	if (index == PRIMARY_HWQ) {
-		rc = cxl_afu_reset(ctx);
+		rc = cfg->ops->afu_reset(ctx);
 		if (unlikely(rc)) {
 			dev_err(dev, "%s: AFU reset failed rc=%d\n",
 				      __func__, rc);
@@ -2019,11 +2002,8 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 		goto err2;
 	}
 
-	/* This performs the equivalent of the CXL_IOCTL_START_WORK.
-	 * The CXL_IOCTL_GET_PROCESS_ELEMENT is implicit in the process
-	 * element (pe) that is embedded in the context (ctx)
-	 */
-	rc = start_context(cfg, index);
+	/* Finally, activate the context by starting it */
+	rc = cfg->ops->start_context(hwq->ctx_cookie);
 	if (unlikely(rc)) {
 		dev_err(dev, "%s: start context failed rc=%d\n", __func__, rc);
 		level = UNMAP_THREE;
@@ -2036,7 +2016,7 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 err2:
 	term_intr(cfg, level, index);
 	if (index != PRIMARY_HWQ)
-		cxl_release_context(ctx);
+		cfg->ops->release_context(ctx);
 err1:
 	hwq->ctx_cookie = NULL;
 	goto out;
@@ -2093,7 +2073,7 @@ static int init_afu(struct cxlflash_cfg *cfg)
 	struct hwq *hwq;
 	int i;
 
-	cxl_perst_reloads_same_image(cfg->afu_cookie, true);
+	cfg->ops->perst_reloads_same_image(cfg->afu_cookie, true);
 
 	afu->num_hwqs = afu->desired_hwqs;
 	for (i = 0; i < afu->num_hwqs; i++) {
@@ -2107,9 +2087,9 @@ static int init_afu(struct cxlflash_cfg *cfg)
 
 	/* Map the entire MMIO space of the AFU using the first context */
 	hwq = get_hwq(afu, PRIMARY_HWQ);
-	afu->afu_map = cxl_psa_map(hwq->ctx_cookie);
+	afu->afu_map = cfg->ops->psa_map(hwq->ctx_cookie);
 	if (!afu->afu_map) {
-		dev_err(dev, "%s: cxl_psa_map failed\n", __func__);
+		dev_err(dev, "%s: psa_map failed\n", __func__);
 		rc = -ENOMEM;
 		goto err1;
 	}
@@ -3669,6 +3649,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
 
 	cfg->init_state = INIT_STATE_NONE;
 	cfg->dev = pdev;
+	cfg->ops = &cxlflash_cxl_ops;
 	cfg->cxl_fops = cxlflash_cxl_fops;
 
 	/*
@@ -3700,7 +3681,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
 
 	pci_set_drvdata(pdev, cfg);
 
-	cfg->afu_cookie = cxl_pci_to_afu(pdev);
+	cfg->afu_cookie = cfg->ops->create_afu(pdev);
 
 	rc = init_pci(cfg);
 	if (rc) {
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index 51f67dc..2fe79df 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -978,9 +978,9 @@ static int cxlflash_disk_detach(struct scsi_device *sdev,
  */
 static int cxlflash_cxl_release(struct inode *inode, struct file *file)
 {
-	void *ctx = cxl_fops_get_context(file);
 	struct cxlflash_cfg *cfg = container_of(file->f_op, struct cxlflash_cfg,
 						cxl_fops);
+	void *ctx = cfg->ops->fops_get_context(file);
 	struct device *dev = &cfg->dev->dev;
 	struct ctx_info *ctxi = NULL;
 	struct dk_cxlflash_detach detach = { { 0 }, 0 };
@@ -988,7 +988,7 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file)
 	enum ctx_ctrl ctrl = CTX_CTRL_ERR_FALLBACK | CTX_CTRL_FILE;
 	int ctxid;
 
-	ctxid = cxl_process_element(ctx);
+	ctxid = cfg->ops->process_element(ctx);
 	if (unlikely(ctxid < 0)) {
 		dev_err(dev, "%s: Context %p was closed ctxid=%d\n",
 			__func__, ctx, ctxid);
@@ -1016,7 +1016,7 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file)
 	list_for_each_entry_safe(lun_access, t, &ctxi->luns, list)
 		_cxlflash_disk_detach(lun_access->sdev, ctxi, &detach);
 out_release:
-	cxl_fd_release(inode, file);
+	cfg->ops->fd_release(inode, file);
 out:
 	dev_dbg(dev, "%s: returning\n", __func__);
 	return 0;
@@ -1091,9 +1091,9 @@ static int cxlflash_mmap_fault(struct vm_fault *vmf)
 {
 	struct vm_area_struct *vma = vmf->vma;
 	struct file *file = vma->vm_file;
-	void *ctx = cxl_fops_get_context(file);
 	struct cxlflash_cfg *cfg = container_of(file->f_op, struct cxlflash_cfg,
 						cxl_fops);
+	void *ctx = cfg->ops->fops_get_context(file);
 	struct device *dev = &cfg->dev->dev;
 	struct ctx_info *ctxi = NULL;
 	struct page *err_page = NULL;
@@ -1101,7 +1101,7 @@ static int cxlflash_mmap_fault(struct vm_fault *vmf)
 	int rc = 0;
 	int ctxid;
 
-	ctxid = cxl_process_element(ctx);
+	ctxid = cfg->ops->process_element(ctx);
 	if (unlikely(ctxid < 0)) {
 		dev_err(dev, "%s: Context %p was closed ctxid=%d\n",
 			__func__, ctx, ctxid);
@@ -1164,16 +1164,16 @@ static const struct vm_operations_struct cxlflash_mmap_vmops = {
  */
 static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	void *ctx = cxl_fops_get_context(file);
 	struct cxlflash_cfg *cfg = container_of(file->f_op, struct cxlflash_cfg,
 						cxl_fops);
+	void *ctx = cfg->ops->fops_get_context(file);
 	struct device *dev = &cfg->dev->dev;
 	struct ctx_info *ctxi = NULL;
 	enum ctx_ctrl ctrl = CTX_CTRL_ERR_FALLBACK | CTX_CTRL_FILE;
 	int ctxid;
 	int rc = 0;
 
-	ctxid = cxl_process_element(ctx);
+	ctxid = cfg->ops->process_element(ctx);
 	if (unlikely(ctxid < 0)) {
 		dev_err(dev, "%s: Context %p was closed ctxid=%d\n",
 			__func__, ctx, ctxid);
@@ -1190,7 +1190,7 @@ static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma)
 
 	dev_dbg(dev, "%s: mmap for context %d\n", __func__, ctxid);
 
-	rc = cxl_fd_mmap(file, vma);
+	rc = cfg->ops->fd_mmap(file, vma);
 	if (likely(!rc)) {
 		/* Insert ourself in the mmap fault handler path */
 		ctxi->cxl_mmap_vmops = vma->vm_ops;
@@ -1309,7 +1309,6 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
 	struct afu *afu = cfg->afu;
 	struct llun_info *lli = sdev->hostdata;
 	struct glun_info *gli = lli->parent;
-	struct cxl_ioctl_start_work work = { 0 };
 	struct ctx_info *ctxi = NULL;
 	struct lun_access *lun_access = NULL;
 	int rc = 0;
@@ -1397,7 +1396,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
 		goto err;
 	}
 
-	ctx = cxl_dev_context_init(cfg->dev);
+	ctx = cfg->ops->dev_context_init(cfg->dev, cfg->afu_cookie);
 	if (IS_ERR_OR_NULL(ctx)) {
 		dev_err(dev, "%s: Could not initialize context %p\n",
 			__func__, ctx);
@@ -1405,24 +1404,21 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
 		goto err;
 	}
 
-	work.num_interrupts = irqs;
-	work.flags = CXL_START_WORK_NUM_IRQS;
-
-	rc = cxl_start_work(ctx, &work);
+	rc = cfg->ops->start_work(ctx, irqs);
 	if (unlikely(rc)) {
 		dev_dbg(dev, "%s: Could not start context rc=%d\n",
 			__func__, rc);
 		goto err;
 	}
 
-	ctxid = cxl_process_element(ctx);
+	ctxid = cfg->ops->process_element(ctx);
 	if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
 		dev_err(dev, "%s: ctxid=%d invalid\n", __func__, ctxid);
 		rc = -EPERM;
 		goto err;
 	}
 
-	file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
+	file = cfg->ops->get_fd(ctx, &cfg->cxl_fops, &fd);
 	if (unlikely(fd < 0)) {
 		rc = -ENODEV;
 		dev_err(dev, "%s: Could not get file descriptor\n", __func__);
@@ -1481,8 +1477,8 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
 err:
 	/* Cleanup CXL context; okay to 'stop' even if it was not started */
 	if (!IS_ERR_OR_NULL(ctx)) {
-		cxl_stop_context(ctx);
-		cxl_release_context(ctx);
+		cfg->ops->stop_context(ctx);
+		cfg->ops->release_context(ctx);
 		ctx = NULL;
 	}
 
@@ -1533,9 +1529,8 @@ static int recover_context(struct cxlflash_cfg *cfg,
 	struct file *file;
 	void *ctx;
 	struct afu *afu = cfg->afu;
-	struct cxl_ioctl_start_work work = { 0 };
 
-	ctx = cxl_dev_context_init(cfg->dev);
+	ctx = cfg->ops->dev_context_init(cfg->dev, cfg->afu_cookie);
 	if (IS_ERR_OR_NULL(ctx)) {
 		dev_err(dev, "%s: Could not initialize context %p\n",
 			__func__, ctx);
@@ -1543,24 +1538,21 @@ static int recover_context(struct cxlflash_cfg *cfg,
 		goto out;
 	}
 
-	work.num_interrupts = ctxi->irqs;
-	work.flags = CXL_START_WORK_NUM_IRQS;
-
-	rc = cxl_start_work(ctx, &work);
+	rc = cfg->ops->start_work(ctx, ctxi->irqs);
 	if (unlikely(rc)) {
 		dev_dbg(dev, "%s: Could not start context rc=%d\n",
 			__func__, rc);
 		goto err1;
 	}
 
-	ctxid = cxl_process_element(ctx);
+	ctxid = cfg->ops->process_element(ctx);
 	if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
 		dev_err(dev, "%s: ctxid=%d invalid\n", __func__, ctxid);
 		rc = -EPERM;
 		goto err2;
 	}
 
-	file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
+	file = cfg->ops->get_fd(ctx, &cfg->cxl_fops, &fd);
 	if (unlikely(fd < 0)) {
 		rc = -ENODEV;
 		dev_err(dev, "%s: Could not get file descriptor\n", __func__);
@@ -1607,9 +1599,9 @@ static int recover_context(struct cxlflash_cfg *cfg,
 	fput(file);
 	put_unused_fd(fd);
 err2:
-	cxl_stop_context(ctx);
+	cfg->ops->stop_context(ctx);
 err1:
-	cxl_release_context(ctx);
+	cfg->ops->release_context(ctx);
 	goto out;
 }
 
-- 
2.1.0

^ permalink raw reply related

* [PATCH 5/6] cxlflash: Adapter context init can return error
From: Uma Krishnan @ 2018-01-03 22:55 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard
In-Reply-To: <1515020002-43551-1-git-send-email-ukrishn@linux.vnet.ibm.com>

Adapter context creation can return either NULL or an error pointer.
Updating the check condition to reflect this.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index b6cadeb..32014e8 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -1992,7 +1992,7 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 		ctx = cxl_get_context(cfg->dev);
 	else
 		ctx = cxl_dev_context_init(cfg->dev);
-	if (unlikely(!ctx)) {
+	if (IS_ERR_OR_NULL(ctx)) {
 		rc = -ENOMEM;
 		goto err1;
 	}
-- 
2.1.0

^ permalink raw reply related


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