* [PATCH v2 0/2] mcb: enable register PCI devices using any BAR
@ 2026-03-02 13:47 Filip Jensen
2026-03-02 13:47 ` [PATCH v2 1/2] mcb: Use more than the first bar in pci devices Filip Jensen
2026-03-02 13:47 ` [PATCH v2 2/2] mcb: refactor the bus operations out of the common code Filip Jensen
0 siblings, 2 replies; 4+ messages in thread
From: Filip Jensen @ 2026-03-02 13:47 UTC (permalink / raw)
To: morbidrsa; +Cc: linux-kernel, Filip Jensen, Jose Javier Rodriguez Barbarin
V1 -> V2: Thanks to the review from Johannes Thumshirn, the patch 2/3 of
the first version has been removed and the cleaner solution from patch 3/3
is then kept.
The PCI mcb driver is currently only able to register devices that use
the first PCI BAR. That is hardcoded in mcb-parse.c in lines 156-161:
c = kzalloc_obj(struct chameleon_bar);
if (!c)
return -ENOMEM;
bar_count = 1;
c->addr = mapbase;
However, mcb devices can use other indexes of the 6 PCI BARs. This serie of
patches allows to use these devices by adding the relevant PCI BAR info to
the chameleon table. As this code must also work for lpc devices, it has
been done a refactoring in order to keep the two buses dependent operations
regarding bars (get_bar and is_io_mapped_bar) outside of the common parsing
code. These callback operations are stored in a structure and passed over
to the parser, thus rendering each module, the mcb-lpc and mcb-pci, only
with their own bus relevant logic.
This patch depends on the previously accepted patch:
Link: https://lore.kernel.org/lkml/20260217075124.10052-1-dev-Felipe.Jensen@duagon.com/
Reviewed-by: Jose Javier Rodriguez Barbarin <dev-josejavier.rodriguez@duagon.com>
Filip Jensen (2):
mcb: Use more than the first bar in pci devices
mcb: refactor the bus operations out of the common code
drivers/mcb/mcb-internal.h | 10 ++++-
drivers/mcb/mcb-lpc.c | 56 ++++++++++++++++++++++++++-
drivers/mcb/mcb-parse.c | 77 +++++---------------------------------
drivers/mcb/mcb-pci.c | 40 +++++++++++++++++++-
4 files changed, 111 insertions(+), 72 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/2] mcb: Use more than the first bar in pci devices
2026-03-02 13:47 [PATCH v2 0/2] mcb: enable register PCI devices using any BAR Filip Jensen
@ 2026-03-02 13:47 ` Filip Jensen
2026-03-03 17:12 ` Johannes Thumshirn
2026-03-02 13:47 ` [PATCH v2 2/2] mcb: refactor the bus operations out of the common code Filip Jensen
1 sibling, 1 reply; 4+ messages in thread
From: Filip Jensen @ 2026-03-02 13:47 UTC (permalink / raw)
To: morbidrsa; +Cc: linux-kernel, Filip Jensen, Jose Javier Rodriguez Barbarin
Currently The mcb driver in a PCI bus only uses the first BAR when
parsing the table of attached devices and thus cannot map devices
using other BARS («No BAR for 16z» error will be thrown in method
chameleon_parse_gdd if assigned to a bar higher than the first).
This patch allows the parsing of devices in BARS other than the first
using the standard PCI helpers for accessing PCI BAR info as described
in pci.h
Reviewed-by: Jose Javier Rodriguez Barbarin <dev-josejavier.rodriguez@duagon.com>
Signed-off-by: Filip Jensen <dev-Felipe.Jensen@duagon.com>
---
V1 -> V2: No changes in this patch
V1: https://lore.kernel.org/lkml/20260226151339.48800-2-dev-Felipe.Jensen@duagon.com/
drivers/mcb/mcb-internal.h | 3 +--
drivers/mcb/mcb-lpc.c | 2 +-
drivers/mcb/mcb-parse.c | 22 +++++++++++++---------
drivers/mcb/mcb-pci.c | 2 +-
4 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/drivers/mcb/mcb-internal.h b/drivers/mcb/mcb-internal.h
index 3602cb3b2021..180ba97cfc08 100644
--- a/drivers/mcb/mcb-internal.h
+++ b/drivers/mcb/mcb-internal.h
@@ -122,7 +122,6 @@ 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, phys_addr_t mapbase,
- void __iomem *base);
+int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base);
#endif
diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c
index 070aa787abc6..d3f48e1ea08b 100644
--- a/drivers/mcb/mcb-lpc.c
+++ b/drivers/mcb/mcb-lpc.c
@@ -56,7 +56,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->mem->start, priv->base);
+ ret = chameleon_parse_cells(priv->bus, priv->base);
if (ret < 0) {
goto out_mcb_bus;
}
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index 2b115cb0e5d9..806be67b960d 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -6,6 +6,7 @@
#include <linux/io.h>
#include <linux/mcb.h>
+#include <linux/pci.h>
#include "mcb-internal.h"
#define for_each_chameleon_cell(dtype, p) \
@@ -123,13 +124,14 @@ static void chameleon_parse_bar(void __iomem *base,
}
}
-static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase,
- struct chameleon_bar **cb)
+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
@@ -153,12 +155,15 @@ static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase,
chameleon_parse_bar(*base, c, bar_count);
*base += BAR_DESC_SIZE(bar_count);
} else {
- c = kzalloc_obj(struct chameleon_bar);
+ pdev = to_pci_dev(dev);
+ bar_count = PCI_STD_NUM_BARS;
+ c = kzalloc_objs(struct chameleon_bar, bar_count);
if (!c)
return -ENOMEM;
-
- bar_count = 1;
- c->addr = mapbase;
+ 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;
@@ -166,8 +171,7 @@ static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase,
return bar_count;
}
-int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
- void __iomem *base)
+int chameleon_parse_cells(struct mcb_bus *bus, void __iomem *base)
{
struct chameleon_fpga_header *header;
struct chameleon_bar *cb;
@@ -203,7 +207,7 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
memcpy(bus->name, header->filename, CHAMELEON_FILENAME_LEN);
bus->name[CHAMELEON_FILENAME_LEN] = '\0';
- bar_count = chameleon_get_bar(&p, mapbase, &cb);
+ bar_count = chameleon_get_bar(&p, &cb, bus->carrier);
if (bar_count < 0) {
ret = bar_count;
goto free_header;
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
index f1353da6ef4f..2401c19a8830 100644
--- a/drivers/mcb/mcb-pci.c
+++ b/drivers/mcb/mcb-pci.c
@@ -86,7 +86,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->mapbase, priv->base);
+ ret = chameleon_parse_cells(priv->bus, priv->base);
if (ret < 0)
goto out_mcb_bus;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] mcb: refactor the bus operations out of the common code
2026-03-02 13:47 [PATCH v2 0/2] mcb: enable register PCI devices using any BAR Filip Jensen
2026-03-02 13:47 ` [PATCH v2 1/2] mcb: Use more than the first bar in pci devices Filip Jensen
@ 2026-03-02 13:47 ` Filip Jensen
1 sibling, 0 replies; 4+ messages in thread
From: Filip Jensen @ 2026-03-02 13:47 UTC (permalink / raw)
To: morbidrsa; +Cc: linux-kernel, Filip Jensen, Jose Javier Rodriguez Barbarin
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>
---
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@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 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
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] mcb: Use more than the first bar in pci devices
2026-03-02 13:47 ` [PATCH v2 1/2] mcb: Use more than the first bar in pci devices Filip Jensen
@ 2026-03-03 17:12 ` Johannes Thumshirn
0 siblings, 0 replies; 4+ messages in thread
From: Johannes Thumshirn @ 2026-03-03 17:12 UTC (permalink / raw)
To: Filip Jensen; +Cc: linux-kernel, Jose Javier Rodriguez Barbarin
Filip Jensen @ 2026-03-02 14:47 :
> +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;
Sorry for not having noticed this in v1 but this...
> /*
> * For those devices which are not connected
> @@ -153,12 +155,15 @@ static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase,
> chameleon_parse_bar(*base, c, bar_count);
> *base += BAR_DESC_SIZE(bar_count);
> } else {
can be declared here, as it's not used outside of this block.
> - c = kzalloc_obj(struct chameleon_bar);
> + pdev = to_pci_dev(dev);
> + bar_count = PCI_STD_NUM_BARS;
> + c = kzalloc_objs(struct chameleon_bar, bar_count);
> if (!c)
> return -ENOMEM;
> -
> - bar_count = 1;
> - c->addr = mapbase;
> + for (int i = 0; i < bar_count; ++i) {
> + c[i].addr = pci_resource_start(pdev, i);
> + c[i].size = pci_resource_len(pdev, i);
> + }
> }
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-03 17:12 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-02 13:47 [PATCH v2 0/2] mcb: enable register PCI devices using any BAR Filip Jensen
2026-03-02 13:47 ` [PATCH v2 1/2] mcb: Use more than the first bar in pci devices Filip Jensen
2026-03-03 17:12 ` Johannes Thumshirn
2026-03-02 13:47 ` [PATCH v2 2/2] mcb: refactor the bus operations out of the common code Filip Jensen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox