[PATCH v2 2/2] mcb: refactor the bus operations out of the common code
From: Filip Jensen
Date: Mon Mar 02 2026 - 08:51:10 EST
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@xxxxxxxxxx>
Signed-off-by: Filip Jensen <dev-Felipe.Jensen@xxxxxxxxxx>
---
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
V1: https://lore.kernel.org/lkml/20260226151339.48800-3-dev-Felipe.Jensen@xxxxxxxxxx/
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 806be67b960d..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;
- struct pci_dev *pdev;
-
- /*
- * 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 {
- 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