[PATCH v3 2/2] mcb: refactor bus operations out of common code

Filip Jensen posted 2 patches 1 month, 1 week ago
[PATCH v3 2/2] mcb: refactor bus operations out of common code
Posted by Filip Jensen 1 month, 1 week ago
Two operations can be identified that are bus dependent and are needed
in both modules mcb-pci and mcb-lpc. In order to avoid having info of both
buses in common code, two callbacks operations (is_bar_iomapped and
get_bars) are defined and passed as parameters to the mcb-parser.

Reviewed-by: Jose Javier Rodriguez Barbarin <dev-josejavier.rodriguez@duagon.com>
Signed-off-by: Filip Jensen <dev-Felipe.Jensen@duagon.com>
---
V2 -> V3: Adapt to line moved in patch V3 1/2
V1 -> V2: Patch V1 2/3 is removed as its changes were removed in V1 3/3. V2
has the refactor of the previous V1 3/3

V2: https://lore.kernel.org/lkml/20260302134703.29913-3-dev-Felipe.Jensen@duagon.com/
V1: https://lore.kernel.org/lkml/20260226151339.48800-3-dev-Felipe.Jensen@duagon.com/

 drivers/mcb/mcb-internal.h |  9 ++++-
 drivers/mcb/mcb-lpc.c      | 56 +++++++++++++++++++++++++-
 drivers/mcb/mcb-parse.c    | 81 +++++---------------------------------
 drivers/mcb/mcb-pci.c      | 40 ++++++++++++++++++-
 4 files changed, 111 insertions(+), 75 deletions(-)

diff --git a/drivers/mcb/mcb-internal.h b/drivers/mcb/mcb-internal.h
index 180ba97cfc08..3152cb4bd1b5 100644
--- a/drivers/mcb/mcb-internal.h
+++ b/drivers/mcb/mcb-internal.h
@@ -122,6 +122,13 @@ struct chameleon_bar {
 #define CHAMELEON_BAR_MAX	6
 #define BAR_DESC_SIZE(x)	((x) * sizeof(struct chameleon_bar) + sizeof(__le32))
 
-int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base);
+struct chameleon_parse_ops {
+	bool (*is_bar_iomapped)(struct device *dev, struct chameleon_bar *cb,
+				  int bar);
+	int (*get_bars)(void __iomem **base, struct chameleon_bar **cb,
+			struct device *dev);
+};
 
+int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base,
+			  struct chameleon_parse_ops *cham_bus_ops);
 #endif
diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c
index d3f48e1ea08b..9dbf9604e5a9 100644
--- a/drivers/mcb/mcb-lpc.c
+++ b/drivers/mcb/mcb-lpc.c
@@ -19,6 +19,60 @@ struct priv {
 	void __iomem *base;
 };
 
+static int mcb_lpc_get_bars(void __iomem **base, struct chameleon_bar **cb,
+			    struct device *pdev)
+{
+	struct chameleon_bar *c;
+	int bar_count;
+	__le32 reg;
+	char __iomem *p = *base;
+	int i;
+
+	/*
+	 * For those devices which are not connected
+	 * to the PCI Bus (e.g. LPC) there is a bar
+	 * descriptor located directly after the
+	 * chameleon header. This header is comparable
+	 * to a PCI header.
+	 */
+	reg = readl(*base);
+
+	bar_count = BAR_CNT(reg);
+	if (bar_count <= 0 || bar_count > CHAMELEON_BAR_MAX)
+		return -ENODEV;
+
+	c = kzalloc_objs(struct chameleon_bar, bar_count);
+	if (!c)
+		return -ENOMEM;
+
+	/* skip reg1 */
+	p += sizeof(__le32);
+
+	for (i = 0; i < bar_count; i++) {
+		c[i].addr = readl(p);
+		c[i].size = readl(p + 4);
+
+		p += sizeof(struct chameleon_bar);
+	}
+	*base += BAR_DESC_SIZE(bar_count);
+	*cb = c;
+
+	return bar_count;
+}
+
+static bool mcb_is_lpc_bar_iomapped(struct device *dev,
+				      struct chameleon_bar *cb, int bar)
+{
+	if (cb[bar].addr & 0x01)
+		return true;
+	return false;
+}
+
+static struct chameleon_parse_ops lpc_parse_ops = {
+	.is_bar_iomapped = mcb_is_lpc_bar_iomapped,
+	.get_bars = mcb_lpc_get_bars,
+};
+
 static int mcb_lpc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -56,7 +110,7 @@ static int mcb_lpc_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->bus))
 		return PTR_ERR(priv->bus);
 
-	ret = chameleon_parse_cells(priv->bus, priv->base);
+	ret = chameleon_parse_cells(priv->bus, priv->base, &lpc_parse_ops);
 	if (ret < 0) {
 		goto out_mcb_bus;
 	}
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index 529ac7fe2ca8..f5e86b6e2e4f 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -6,7 +6,6 @@
 #include <linux/io.h>
 #include <linux/mcb.h>
 
-#include <linux/pci.h>
 #include "mcb-internal.h"
 
 #define for_each_chameleon_cell(dtype, p)	\
@@ -29,9 +28,9 @@ static int chameleon_parse_bdd(struct mcb_bus *bus,
 	return 0;
 }
 
-static int chameleon_parse_gdd(struct mcb_bus *bus,
-			struct chameleon_bar *cb,
-			void __iomem *base, int bar_count)
+static int chameleon_parse_gdd(struct mcb_bus *bus, struct chameleon_bar *cb,
+			       void __iomem *base, int bar_count,
+			       struct chameleon_parse_ops *cham_ops)
 {
 	struct chameleon_gdd __iomem *gdd =
 		(struct chameleon_gdd __iomem *) base;
@@ -77,7 +76,7 @@ static int chameleon_parse_gdd(struct mcb_bus *bus,
 		goto err;
 	}
 
-	if (dev_mapbase & 0x01) {
+	if (cham_ops->is_bar_iomapped(bus->carrier, cb, mdev->bar)) {
 		pr_info("IO mapped Device (16z%03d) not yet supported\n",
 			mdev->id);
 		ret = 0;
@@ -107,71 +106,8 @@ static int chameleon_parse_gdd(struct mcb_bus *bus,
 	return ret;
 }
 
-static void chameleon_parse_bar(void __iomem *base,
-				struct chameleon_bar *cb, int bar_count)
-{
-	char __iomem *p = base;
-	int i;
-
-	/* skip reg1 */
-	p += sizeof(__le32);
-
-	for (i = 0; i < bar_count; i++) {
-		cb[i].addr = readl(p);
-		cb[i].size = readl(p + 4);
-
-		p += sizeof(struct chameleon_bar);
-	}
-}
-
-static int chameleon_get_bar(void __iomem **base, struct chameleon_bar **cb,
-			     struct device *dev)
-{
-	struct chameleon_bar *c;
-	int bar_count;
-	__le32 reg;
-	u32 dtype;
-
-	/*
-	 * For those devices which are not connected
-	 * to the PCI Bus (e.g. LPC) there is a bar
-	 * descriptor located directly after the
-	 * chameleon header. This header is comparable
-	 * to a PCI header.
-	 */
-	dtype = get_next_dtype(*base);
-	if (dtype == CHAMELEON_DTYPE_BAR) {
-		reg = readl(*base);
-
-		bar_count = BAR_CNT(reg);
-		if (bar_count <= 0 || bar_count > CHAMELEON_BAR_MAX)
-			return -ENODEV;
-
-		c = kzalloc_objs(struct chameleon_bar, bar_count);
-		if (!c)
-			return -ENOMEM;
-
-		chameleon_parse_bar(*base, c, bar_count);
-		*base += BAR_DESC_SIZE(bar_count);
-	} else {
-		struct pci_dev *pdev = to_pci_dev(dev);
-
-		bar_count = PCI_STD_NUM_BARS;
-		c = kzalloc_objs(struct chameleon_bar, bar_count);
-		if (!c)
-			return -ENOMEM;
-		for (int i = 0; i < bar_count; ++i) {
-			c[i].addr = pci_resource_start(pdev, i);
-			c[i].size = pci_resource_len(pdev, i);
-		}
-	}
-
-	*cb = c;
-
-	return bar_count;
-}
-
-int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base)
+int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base,
+			  struct chameleon_parse_ops *cham_bus_ops)
 {
 	struct chameleon_fpga_header *header;
 	struct chameleon_bar *cb;
@@ -207,7 +143,7 @@ int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base)
 	memcpy(bus->name, header->filename, CHAMELEON_FILENAME_LEN);
 	bus->name[CHAMELEON_FILENAME_LEN] = '\0';
 
-	bar_count = chameleon_get_bar(&p, &cb, bus->carrier);
+	bar_count = cham_bus_ops->get_bars(&p, &cb, bus->carrier);
 	if (bar_count < 0) {
 		ret = bar_count;
 		goto free_header;
@@ -216,7 +152,8 @@ int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base)
 	for_each_chameleon_cell(dtype, p) {
 		switch (dtype) {
 		case CHAMELEON_DTYPE_GENERAL:
-			ret = chameleon_parse_gdd(bus, cb, p, bar_count);
+			ret = chameleon_parse_gdd(bus, cb, p, bar_count,
+						  cham_bus_ops);
 			if (ret < 0)
 				goto free_bar;
 			p += sizeof(struct chameleon_gdd);
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
index 2401c19a8830..6245714646a7 100644
--- a/drivers/mcb/mcb-pci.c
+++ b/drivers/mcb/mcb-pci.c
@@ -18,6 +18,44 @@ struct priv {
 	void __iomem *base;
 };
 
+static int pci_get_bars(void __iomem **base, struct chameleon_bar **cb,
+			struct device *dev)
+{
+	struct pci_dev *pdev;
+	struct chameleon_bar *c;
+	int bar_count;
+
+	pdev = to_pci_dev(dev);
+	bar_count = PCI_STD_NUM_BARS;
+	c = kzalloc_objs(struct chameleon_bar, bar_count);
+	if (!c)
+		return -ENOMEM;
+	for (int i = 0; i < bar_count; ++i) {
+		c[i].addr = pci_resource_start(pdev, i);
+		c[i].size = pci_resource_len(pdev, i);
+	}
+
+	*cb = c;
+
+	return bar_count;
+}
+
+static bool is_pci_bar_iomapped(struct device *dev, struct chameleon_bar *cb,
+				  int bar)
+{
+	struct pci_dev *pdev;
+
+	pdev = to_pci_dev(dev);
+	if (pci_resource_flags(pdev, bar) & IORESOURCE_IO)
+		return true;
+	return false;
+}
+
+static struct chameleon_parse_ops cham_pci_ops = {
+	.is_bar_iomapped = is_pci_bar_iomapped,
+	.get_bars = pci_get_bars,
+};
+
 static int mcb_pci_get_irq(struct mcb_device *mdev)
 {
 	struct mcb_bus *mbus = mdev->bus;
@@ -86,7 +124,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	priv->bus->get_irq = mcb_pci_get_irq;
 
-	ret = chameleon_parse_cells(priv->bus, priv->base);
+	ret = chameleon_parse_cells(priv->bus, priv->base, &cham_pci_ops);
 	if (ret < 0)
 		goto out_mcb_bus;
 
-- 
2.34.1