Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 0/4] Fix and extend uio_dmem_genirq

123 views
Skip to first unread message

Jan Viktorin

unread,
May 17, 2016, 5:32:30 AM5/17/16
to devic...@vger.kernel.org, linux-...@vger.kernel.org, Jan Viktorin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
Hello,

as a part of my work related usually to FPGAs, I was playing with the
uio_dmem_genirq. First, I've discovered a (possible) bug in the
uio_dmem_genirq in exposing the dynamic regions to userspace (patch 0001).
When specifying a number of dynamic regions, one mapping is (due to
counting IORESOURCE_IRQ) skipped:

../maps/map0/addr: 0xe000b000 <<< IORESOURCE_MEM from reg = <...>
../maps/map0/size: 0x00001000
../maps/map1/addr: 0xffffffff <<< no mapping (skipped due to IORESOURCE_IRQ)
../maps/map1/size: 0x00008000
../maps/map2/addr: 0x1e210000 <<< the first dynamic mapping
../maps/map2/size: 0x00008000
../maps/map3/addr: 0x1e218000
../maps/map3/size: 0x00008000
../maps/map4/addr: 0x1e220000
../maps/map4/size: 0x00008000

Next, I needed to do some DMA from userspace and I didn't like to change
the kernel at all. The uio_pdrv_genirq has a feature to specify of_id
when calling insmod to bind to a specific device. I've implemented this
(patches 0002-0004) for uio_dmem_genirq and added two OF properties to
specify memory allocations. The work is inspired by those commits (but
reworked):

* https://github.com/analogdevicesinc/linux/commit/757e2c54a613abed6145fcd572cf6c5d8b3fb7fc
* https://github.com/analogdevicesinc/linux/commit/45ec4148b290302c7de8e6a1de0d9f7b2833339b

Regards
Jan


Jan Viktorin (4):
uio: fix dmem_region_start computation
uio: UIO_IRQ_NONE is a valid option for uioinfo->irq
uio: introduce devicetree bindings for uio_dmem_genirq
uio: allow binding uio_pdrv_genirq.c to devices using command line
option

.../devicetree/bindings/uio/uio_dmem_genirq.txt | 16 ++++
drivers/uio/uio_dmem_genirq.c | 93 +++++++++++++++-------
2 files changed, 81 insertions(+), 28 deletions(-)
create mode 100644 Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt

--
2.8.0

Jan Viktorin

unread,
May 17, 2016, 5:32:48 AM5/17/16
to devic...@vger.kernel.org, linux-...@vger.kernel.org, Jan Viktorin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
Signed-off-by: Jan Viktorin <vikt...@rehivetech.com>
---
.../devicetree/bindings/uio/uio_dmem_genirq.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt

diff --git a/Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt b/Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt
new file mode 100644
index 0000000..5416f71
--- /dev/null
+++ b/Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt
@@ -0,0 +1,16 @@
+UIO device for dynamic memory allocation
+----------------------------------------
+
+When binding the uio_dmem_genirq via the device tree by setting
+the of_id from command line, the following OF properties are
+used for initialization:
+
+- uio,number-of-dynamic-regions
+
+ Determines the number of dynamically allocated memory regions
+ for the device.
+
+- uio,dynamic-regions-sizes
+
+ Sizes of regions to be allocated. It is expected to contain
+ at least uio,number-of-dynamic-regions sizes.
--
2.8.0

Jan Viktorin

unread,
May 17, 2016, 5:32:49 AM5/17/16
to devic...@vger.kernel.org, linux-...@vger.kernel.org, Jan Viktorin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
The variable i contains a total number of resources (including
IORESOURCE_IRQ). However, we want the dmem_region_start to point
after the last resource of type IORESOURCE_MEM. The original behaviour
leads (very likely) to skipping several UIO mapping regions and makes
them useless. Fix this by computing dmem_region_start from the uiomem
which points to the last used UIO mapping.

Fixes: 0a0c3b5a24bd ("Add new uio device for dynamic memory allocation")

Signed-off-by: Jan Viktorin <vikt...@rehivetech.com>
---
drivers/uio/uio_dmem_genirq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
index 915facb..e1134a4 100644
--- a/drivers/uio/uio_dmem_genirq.c
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -229,7 +229,7 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev)
++uiomem;
}

- priv->dmem_region_start = i;
+ priv->dmem_region_start = uiomem - &uioinfo->mem[0];
priv->num_dmem_regions = pdata->num_dynamic_regions;

for (i = 0; i < pdata->num_dynamic_regions; ++i) {
--
2.8.0

Jan Viktorin

unread,
May 17, 2016, 5:33:12 AM5/17/16
to devic...@vger.kernel.org, linux-...@vger.kernel.org, Jan Viktorin, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
The uio_dmem_genirq works in a similar way as uio_pdrv_genirq now.
It accepts the of_id module parameter to bind to a specific device.
The information about dynamic memory is obtained from OF.

This patch implements the two OF bindings:

* uio,number-of-dynamic-regions
* uio,dynamic-regions-sizes

Signed-off-by: Jan Viktorin <vikt...@rehivetech.com>
---
drivers/uio/uio_dmem_genirq.c | 76 +++++++++++++++++++++++++++++++++----------
1 file changed, 58 insertions(+), 18 deletions(-)

diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
index 945515d..ade650a 100644
--- a/drivers/uio/uio_dmem_genirq.c
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -144,29 +144,70 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
return 0;
}

+static int uio_dmem_genirq_alloc_platdata(struct platform_device *pdev)
+{
+ struct uio_dmem_genirq_pdata pdata;
+ u32 regions;
+ u32 sizes[MAX_UIO_MAPS];
+ int ret;
+
+ memset(&pdata, 0, sizeof(pdata));
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "uio,number-of-dynamic-regions", &regions);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Missing property uio,number-of-dynamic-regions\n");
+ return ret;
+ }
+
+ regions = min_t(u32, regions, MAX_UIO_MAPS);
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "uio,dynamic-regions-sizes", sizes, regions);
+ if (ret) {
+ dev_err(&pdev->dev, "Missing or invalid property "
+ "uio,dynamic-regions-sizes\n");
+ return ret;
+ }
+
+ pdata.dynamic_region_sizes = devm_kzalloc(&pdev->dev,
+ sizeof(*pdata.dynamic_region_sizes) *
+ pdata.num_dynamic_regions, GFP_KERNEL);
+ if (!pdata.dynamic_region_sizes) {
+ dev_err(&pdev->dev, "Unable to alloc dynamic_region_sizes\n");
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ pdata.num_dynamic_regions = regions;
+ while (regions--)
+ pdata.dynamic_region_sizes[regions] = sizes[regions];
+
+ pdata.uioinfo.name = pdev->dev.of_node->name;
+ pdata.uioinfo.version = "devicetree";
+
+ return platform_device_add_data(pdev, &pdata, sizeof(pdata));
+}
+
static int uio_dmem_genirq_probe(struct platform_device *pdev)
{
- struct uio_dmem_genirq_pdata *pdata = dev_get_platdata(&pdev->dev);
- struct uio_info *uioinfo = &pdata->uioinfo;
+ struct uio_dmem_genirq_pdata *pdata;
+ struct uio_info *uioinfo;
struct uio_dmem_genirq_platdata *priv;
struct uio_mem *uiomem;
int ret = -EINVAL;
int i;

if (pdev->dev.of_node) {
- int irq;
-
- /* alloc uioinfo for one device */
- uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
- if (!uioinfo) {
- ret = -ENOMEM;
- dev_err(&pdev->dev, "unable to kmalloc\n");
+ ret = uio_dmem_genirq_alloc_platdata(pdev);
+ if (ret)
goto bad2;
- }
- uioinfo->name = pdev->dev.of_node->name;
- uioinfo->version = "devicetree";
}

+ pdata = dev_get_platdata(&pdev->dev);
+ uioinfo = &pdata->uioinfo;
+
if (!uioinfo || !uioinfo->name || !uioinfo->version) {
dev_err(&pdev->dev, "missing platform_data\n");
goto bad0;
@@ -298,10 +339,6 @@ static int uio_dmem_genirq_remove(struct platform_device *pdev)
priv->uioinfo->handler = NULL;
priv->uioinfo->irqcontrol = NULL;

- /* kfree uioinfo for OF */
- if (pdev->dev.of_node)
- kfree(priv->uioinfo);
-
kfree(priv);
return 0;
}
@@ -329,10 +366,13 @@ static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = {
};

#ifdef CONFIG_OF
-static const struct of_device_id uio_of_genirq_match[] = {
- { /* empty for now */ },
+static struct of_device_id uio_of_genirq_match[] = {
+ { /* This is filled with module_parm */ },
+ { /* end of list */ },
};
MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
+module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0);
+MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio");
#endif

static struct platform_driver uio_dmem_genirq = {
--
2.8.0

Rob Herring

unread,
May 18, 2016, 1:01:29 PM5/18/16
to Jan Viktorin, devic...@vger.kernel.org, linux-...@vger.kernel.org, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
On Tue, May 17, 2016 at 11:22:19AM +0200, Jan Viktorin wrote:
> Signed-off-by: Jan Viktorin <vikt...@rehivetech.com>
> ---
> .../devicetree/bindings/uio/uio_dmem_genirq.txt | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt

DT describes h/w. UIO is not a h/w block, so this does not belong in DT.
A UIO vs. kernel driver is purely a kernel decision which shouldn't
require a DT change.

The properties should be part of match data for a compatible string that
needs them set. Or if they can be defined in a way that is actually a
property of the h/w, then it would be acceptible. You'd still need to
define compatible strings that the properties apply to.

Rob

Jan Viktorin

unread,
May 19, 2016, 4:47:53 AM5/19/16
to Rob Herring, devic...@vger.kernel.org, linux-...@vger.kernel.org, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
Hello Rob,

thank you for your opinion...

On Wed, 18 May 2016 12:01:05 -0500
Rob Herring <ro...@kernel.org> wrote:

> On Tue, May 17, 2016 at 11:22:19AM +0200, Jan Viktorin wrote:
> > Signed-off-by: Jan Viktorin <vikt...@rehivetech.com>
> > ---
> > .../devicetree/bindings/uio/uio_dmem_genirq.txt | 16 ++++++++++++++++
> > 1 file changed, 16 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt
>
> DT describes h/w. UIO is not a h/w block, so this does not belong in DT.
> A UIO vs. kernel driver is purely a kernel decision which shouldn't
> require a DT change.

I mostly agree and I don't say this is the very best solution... however,
it is quite a straightforward one.

>
> The properties should be part of match data for a compatible string that

True. But in case of probing from DT, where can I obtain those match data
from? I have to patch the kernel... and that is what I tried to avoid.

With this patch set, you only modify your current device-tree (extend the
appropriate devices by "uio,...") and reboot with this new one.

> needs them set. Or if they can be defined in a way that is actually a
> property of the h/w, then it would be acceptible. You'd still need to
> define compatible strings that the properties apply to.

If you look at uio_pdrv_genirq you can see that it has already been extended by
the module param "of_id". I.e. it is possible to specify the compatible property
it would match when doing insmod. So, it is possible to bind it to any platform
device described by the device tree. And thus, there is no way how to define a
list of compatible strings for it... (quite a long list, isn't it?)

The same (of_id) can be done for uio_dmem_genirq, however, there is no way how to
specify the amount of dynamic memory to be used for a specific device. For me, it
makes sense to use DT to obtain those two properties saying "those devices would
use this amount of memory and not more".

Perhaps, another module param is a way to go here. Something like of_dmem_count=2,
of_dmem_sizes=32k. Less flexible solution, however, if it is acceptable I'll rewrite
the current one.

Jan

>
> Rob

Rob Herring

unread,
May 23, 2016, 4:36:40 PM5/23/16
to Jan Viktorin, devic...@vger.kernel.org, linux-...@vger.kernel.org, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman
On Thu, May 19, 2016 at 10:45:56AM +0200, Jan Viktorin wrote:
> Hello Rob,
>
> thank you for your opinion...
>
> On Wed, 18 May 2016 12:01:05 -0500
> Rob Herring <ro...@kernel.org> wrote:
>
> > On Tue, May 17, 2016 at 11:22:19AM +0200, Jan Viktorin wrote:
> > > Signed-off-by: Jan Viktorin <vikt...@rehivetech.com>
> > > ---
> > > .../devicetree/bindings/uio/uio_dmem_genirq.txt | 16 ++++++++++++++++
> > > 1 file changed, 16 insertions(+)
> > > create mode 100644 Documentation/devicetree/bindings/uio/uio_dmem_genirq.txt
> >
> > DT describes h/w. UIO is not a h/w block, so this does not belong in DT.
> > A UIO vs. kernel driver is purely a kernel decision which shouldn't
> > require a DT change.
>
> I mostly agree and I don't say this is the very best solution... however,
> it is quite a straightforward one.
>
> >
> > The properties should be part of match data for a compatible string that
>
> True. But in case of probing from DT, where can I obtain those match data
> from? I have to patch the kernel... and that is what I tried to avoid.

spi-dev is a similar situation and we put compatible strings (and
therefore potentially match data) in the kernel.

> With this patch set, you only modify your current device-tree (extend the
> appropriate devices by "uio,...") and reboot with this new one.

Generally speaking changing your kernel is as easy or easier than
changing the DT.

Rebooting is not a very good choice either when it could easily be a
module unload/reload instead.

> > needs them set. Or if they can be defined in a way that is actually a
> > property of the h/w, then it would be acceptible. You'd still need to
> > define compatible strings that the properties apply to.
>
> If you look at uio_pdrv_genirq you can see that it has already been extended by
> the module param "of_id". I.e. it is possible to specify the compatible property
> it would match when doing insmod. So, it is possible to bind it to any platform
> device described by the device tree. And thus, there is no way how to define a
> list of compatible strings for it... (quite a long list, isn't it?)
>
> The same (of_id) can be done for uio_dmem_genirq, however, there is no way how to
> specify the amount of dynamic memory to be used for a specific device. For me, it
> makes sense to use DT to obtain those two properties saying "those devices would
> use this amount of memory and not more".
>
> Perhaps, another module param is a way to go here. Something like of_dmem_count=2,
> of_dmem_sizes=32k. Less flexible solution, however, if it is acceptable I'll rewrite
> the current one.

No issue with doing that, though they are not OF parameters at that
point.

Rob

Anup Patel

unread,
Jun 23, 2016, 4:31:15 AM6/23/16
to Rob Herring, Jan Viktorin, Device Tree, Linux Kernel, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Hans J. Koch, Greg Kroah-Hartman, BCM Kernel Feedback
Sorry for jumping-in late ...
We can pass name of the DT attributes as kernel parameters. This will
not require any DT bindings change.

The main advantage in having DT attributes for UIO dmem is that we can
have two different UIO dmem DT nodes with different number of dynamic
regions.

In fact, we can pass UIO dmem compatible string also as kernel parameter
just like UIO pdrv driver but this feature is missing current UIO dmem driver.

>
>> > needs them set. Or if they can be defined in a way that is actually a
>> > property of the h/w, then it would be acceptible. You'd still need to
>> > define compatible strings that the properties apply to.
>>
>> If you look at uio_pdrv_genirq you can see that it has already been extended by
>> the module param "of_id". I.e. it is possible to specify the compatible property
>> it would match when doing insmod. So, it is possible to bind it to any platform
>> device described by the device tree. And thus, there is no way how to define a
>> list of compatible strings for it... (quite a long list, isn't it?)
>>
>> The same (of_id) can be done for uio_dmem_genirq, however, there is no way how to
>> specify the amount of dynamic memory to be used for a specific device. For me, it
>> makes sense to use DT to obtain those two properties saying "those devices would
>> use this amount of memory and not more".
>>
>> Perhaps, another module param is a way to go here. Something like of_dmem_count=2,
>> of_dmem_sizes=32k. Less flexible solution, however, if it is acceptable I'll rewrite
>> the current one.
>
> No issue with doing that, though they are not OF parameters at that
> point.
>
> Rob
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majo...@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html

Regards,
Anup
0 new messages