Currently, three types of mem regions are supported: UIO_MEM_PHYS,
UIO_MEM_LOGICAL and UIO_MEM_VIRTUAL. Among these UIO_MEM_PHYS helps
UIO driver export physcial memory to user space as non-cacheable
user memory. Typcially memory-mapped registers of a device are exported
to user space as UIO_MEM_PHYS type mem region. The UIO_MEM_PHYS type
is not useful if dma-capable devices are capable of maintaining coherency
with CPU caches becasue we can allow cacheable access to memory shared
between such devices and user space.
This patch adds new type UIO_MEM_PHYS_CACHE for mem regions to enable
cacheable access to physical memory from user space.
Signed-off-by: Ankit Jindal <redacted>
Signed-off-by: Tushar Jagad <redacted>
---
drivers/uio/uio.c | 22 +++++++++++++---------
include/linux/uio_driver.h | 7 ++++---
2 files changed, 17 insertions(+), 12 deletions(-)
On Tue, Sep 09, 2014 at 03:26:55PM +0530, Ankit Jindal wrote:
quoted hunk
Currently, three types of mem regions are supported: UIO_MEM_PHYS,
UIO_MEM_LOGICAL and UIO_MEM_VIRTUAL. Among these UIO_MEM_PHYS helps
UIO driver export physcial memory to user space as non-cacheable
user memory. Typcially memory-mapped registers of a device are exported
to user space as UIO_MEM_PHYS type mem region. The UIO_MEM_PHYS type
is not useful if dma-capable devices are capable of maintaining coherency
with CPU caches becasue we can allow cacheable access to memory shared
between such devices and user space.
This patch adds new type UIO_MEM_PHYS_CACHE for mem regions to enable
cacheable access to physical memory from user space.
Signed-off-by: Ankit Jindal <redacted>
Signed-off-by: Tushar Jagad <redacted>
---
drivers/uio/uio.c | 22 +++++++++++++---------
include/linux/uio_driver.h | 7 ++++---
2 files changed, 17 insertions(+), 12 deletions(-)
On 10 September 2014 00:59, Greg Kroah-Hartman
[off-list ref] wrote:
On Tue, Sep 09, 2014 at 03:26:55PM +0530, Ankit Jindal wrote:
quoted
Currently, three types of mem regions are supported: UIO_MEM_PHYS,
UIO_MEM_LOGICAL and UIO_MEM_VIRTUAL. Among these UIO_MEM_PHYS helps
UIO driver export physcial memory to user space as non-cacheable
user memory. Typcially memory-mapped registers of a device are exported
to user space as UIO_MEM_PHYS type mem region. The UIO_MEM_PHYS type
is not useful if dma-capable devices are capable of maintaining coherency
with CPU caches becasue we can allow cacheable access to memory shared
between such devices and user space.
This patch adds new type UIO_MEM_PHYS_CACHE for mem regions to enable
cacheable access to physical memory from user space.
Signed-off-by: Ankit Jindal <redacted>
Signed-off-by: Tushar Jagad <redacted>
---
drivers/uio/uio.c | 22 +++++++++++++---------
include/linux/uio_driver.h | 7 ++++---
2 files changed, 17 insertions(+), 12 deletions(-)
@@ -530,7 +530,8 @@ the memory region, it will show up in the corresponding sysfs node.<varname>UIO_MEM_PHYS</varname> if you you have physical memory on yourcard to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logicalmemory (e.g. allocated with <function>kmalloc()</function>). There's also-<varname>UIO_MEM_VIRTUAL</varname> for virtual memory.+<varname>UIO_MEM_VIRTUAL</varname> for virtual memory and+<varname>UIO_MEM_PHYS_CACHE</varname> for physical cacheable memory.</para></listitem><listitem><para>
@@ -530,7 +530,8 @@ the memory region, it will show up in the corresponding sysfs node.<varname>UIO_MEM_PHYS</varname> if you you have physical memory on yourcard to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logicalmemory (e.g. allocated with <function>kmalloc()</function>). There's also-<varname>UIO_MEM_VIRTUAL</varname> for virtual memory.+<varname>UIO_MEM_VIRTUAL</varname> for virtual memory and+<varname>UIO_MEM_PHYS_CACHE</varname> for physical cacheable memory.
When I read this, I wondered what "physical cacheable memory" was.
Then I found that what you're doing with this is mapping physical
memory into userspace with cacheable attributes.
So, to avoid confusion, this should be "for physical memory, which
will be cacheably mapped" or similar.
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
@@ -530,7 +530,8 @@ the memory region, it will show up in the corresponding sysfs node.<varname>UIO_MEM_PHYS</varname> if you you have physical memory on yourcard to be mapped. Use <varname>UIO_MEM_LOGICAL</varname> for logicalmemory (e.g. allocated with <function>kmalloc()</function>). There's also-<varname>UIO_MEM_VIRTUAL</varname> for virtual memory.+<varname>UIO_MEM_VIRTUAL</varname> for virtual memory and+<varname>UIO_MEM_PHYS_CACHE</varname> for physical cacheable memory.
When I read this, I wondered what "physical cacheable memory" was.
Then I found that what you're doing with this is mapping physical
memory into userspace with cacheable attributes.
So, to avoid confusion, this should be "for physical memory, which
will be cacheably mapped" or similar.
Thanks, will frame better in next version.
Thanks,
Ankit
The Applied Micro X-Gene SOC has on-chip QMTM (Queue manager
and Traffic manager) which is hardware based Queue or Ring
manager. This QMTM devices can be used in conjuction with
other devices such as DMA Engine, Ethernet, Security Engine,
etc to assign work to based on Queues or Rings.
This patch allows user space access to Xgene QMTM device.
Signed-off-by: Ankit Jindal <redacted>
Signed-off-by: Tushar Jagad <redacted>
---
drivers/uio/Kconfig | 8 ++
drivers/uio/Makefile | 1 +
drivers/uio/uio_xgene_qmtm.c | 289 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 298 insertions(+)
create mode 100644 drivers/uio/uio_xgene_qmtm.c
@@ -0,0 +1,289 @@+/*+*XgeneQueueManagerTrafficManager(QMTM)UIOdriver(uio_xgene_qmtm)+*+*ThisdriverexportsQMTMCSRs,Fabricandmemoryforqueuestouser-space+*+*Copyright(C)2014AppliedMicro-http://www.apm.com/+*Copyright(C)2014LinaroLtd.+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicenseas+*publishedbytheFreeSoftwareFoundationversion2.+*+*Thisprogramisdistributed"as is"WITHOUTANYWARRANTYofany+*kind,whetherexpressorimplied;withouteventheimpliedwarranty+*ofMERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*/++#include<linux/device.h>+#include<linux/delay.h>+#include<linux/module.h>+#include<linux/moduleparam.h>+#include<linux/platform_device.h>+#include<linux/uio_driver.h>+#include<linux/io.h>+#include<linux/clk.h>+#include<linux/slab.h>+#include<linux/of_platform.h>++#define DRV_NAME "qmtm_uio"+#define DRV_VERSION "1.0"++#define QMTM_CONFIG 0x00000004+#define QMTM_SRST 0x0000c200+#define QMTM_CLKEN 0x0000c208+#define QMTM_CFG_MEM_RAM_SHUTDOWN 0x0000d070++#define QMTM_DEFAULT_QSIZE 0x00010000++structuio_qmtm_dev{+structuio_info*info;+structclk*qmtm_clk;+};++/* QMTM CSR read/write routine */+staticinlinevoidqmtm_csr_write(structuio_qmtm_dev*qmtm_dev,u32offset,+u32data)+{+void__iomem*addr=(u8*)qmtm_dev->info->mem[0].internal_addr++offset;++writel(data,addr);+}++staticinlineu32qmtm_csr_read(structuio_qmtm_dev*qmtm_dev,u32offset)+{+void__iomem*addr=(u8*)qmtm_dev->info->mem[0].internal_addr++offset;++returnreadl(addr);+}++staticintqmtm_reset(structuio_qmtm_dev*qmtm_dev)+{+u32val;+intwait=1000;++/* get device out of reset */+qmtm_csr_write(qmtm_dev,QMTM_CLKEN,3);+qmtm_csr_write(qmtm_dev,QMTM_SRST,3);+udelay(1000);+qmtm_csr_write(qmtm_dev,QMTM_SRST,0);+qmtm_csr_write(qmtm_dev,QMTM_CFG_MEM_RAM_SHUTDOWN,0);++/* check whether device is out of reset or not */+do{+val=qmtm_csr_read(qmtm_dev,QMTM_CFG_MEM_RAM_SHUTDOWN);++if(!wait--)+return-1;+udelay(1);+}while(val==0xffffffff);++return0;+}++staticintqmtm_open(structuio_info*info,structinode*inode)+{+structuio_qmtm_dev*qmtm_dev=info->priv;++/* Enable QPcore */+qmtm_csr_write(qmtm_dev,QMTM_CONFIG,0x80000000);++return0;+}++staticintqmtm_release(structuio_info*info,structinode*inode)+{+structuio_qmtm_dev*qmtm_dev=info->priv;++/* Disable QPcore */+qmtm_csr_write(qmtm_dev,QMTM_CONFIG,0);++return0;+}++staticvoidqmtm_cleanup(structplatform_device*pdev,+structuio_qmtm_dev*qmtm_dev)+{+structuio_info*info=qmtm_dev->info;++uio_unregister_device(info);++kfree(info->name);++if(!IS_ERR(info->mem[0].internal_addr))+devm_iounmap(&pdev->dev,info->mem[0].internal_addr);++kfree(info);+clk_put(qmtm_dev->qmtm_clk);+kfree(qmtm_dev);+}++staticintqmtm_probe(structplatform_device*pdev)+{+structuio_info*info;+structuio_qmtm_dev*qmtm_dev;+structresource*csr;+structresource*fabric;+structresource*qpool;+unsignedintnum_queues;+unsignedintdevid;+intret=-ENODEV;++qmtm_dev=kzalloc(sizeof(structuio_qmtm_dev),GFP_KERNEL);+if(!qmtm_dev)+return-ENOMEM;++qmtm_dev->info=kzalloc(sizeof(*info),GFP_KERNEL);+if(!qmtm_dev->info){+kfree(qmtm_dev);+return-ENOMEM;+}++/* Power on qmtm in case its not done as part of boot-loader */+qmtm_dev->qmtm_clk=clk_get(&pdev->dev,NULL);+if(IS_ERR(qmtm_dev->qmtm_clk)){+dev_err(&pdev->dev,"Failed to get clock\n");+ret=PTR_ERR(qmtm_dev->qmtm_clk);+kfree(qmtm_dev->info);+kfree(qmtm_dev);+returnret;+}else{+clk_prepare_enable(qmtm_dev->qmtm_clk);+}++csr=platform_get_resource(pdev,IORESOURCE_MEM,0);+if(!csr){+dev_err(&pdev->dev,"No QMTM CSR resource specified\n");+gotoout_free;+}++if(!csr->start){+dev_err(&pdev->dev,"Invalid CSR resource\n");+gotoout_free;+}++fabric=platform_get_resource(pdev,IORESOURCE_MEM,1);+if(!fabric){+dev_err(&pdev->dev,"No QMTM Fabric resource specified\n");+gotoout_free;+}++if(!fabric->start){+dev_err(&pdev->dev,"Invalid Fabric resource\n");+gotoout_free;+}++qpool=platform_get_resource(pdev,IORESOURCE_MEM,2);+if(!qpool){+dev_err(&pdev->dev,"No QMTM Qpool resource specified\n");+gotoout_free;+}++if(!qpool->start){+dev_err(&pdev->dev,"Invalid Qpool resource\n");+gotoout_free;+}++ret=of_property_read_u32(pdev->dev.of_node,"num_queues",+&num_queues);++if(ret<0){+dev_err(&pdev->dev,"No num_queues resource specified\n");+gotoout_free;+}++/* check whether sufficient memory is provided for the given queues */+if(!((num_queues*QMTM_DEFAULT_QSIZE)<=resource_size(qpool))){+dev_err(&pdev->dev,"Insufficient Qpool for the given queues\n");+gotoout_free;+}++ret=of_property_read_u32(pdev->dev.of_node,"devid",&devid);+if(ret<0){+dev_err(&pdev->dev,"No devid resource specified\n");+gotoout_free;+}++info=qmtm_dev->info;+info->mem[0].name="csr";+info->mem[0].addr=csr->start;+info->mem[0].size=resource_size(csr);+info->mem[0].memtype=UIO_MEM_PHYS;+info->mem[0].internal_addr=devm_ioremap_resource(&pdev->dev,csr);++if(IS_ERR(info->mem[0].internal_addr)){+dev_err(&pdev->dev,"Failed to ioremap CSR region\n");+gotoout_free;+}++info->mem[1].name="fabric";+info->mem[1].addr=fabric->start;+info->mem[1].size=resource_size(fabric);+info->mem[1].memtype=UIO_MEM_PHYS;++info->mem[2].name="qpool";+info->mem[2].addr=qpool->start;+info->mem[2].size=resource_size(qpool);+info->mem[2].memtype=UIO_MEM_PHYS_CACHE;++info->name=kasprintf(GFP_KERNEL,"qmtm%d",devid);+info->version=DRV_VERSION;++info->priv=qmtm_dev;+info->open=qmtm_open;+info->release=qmtm_release;++/* get the qmtm out of reset */+ret=qmtm_reset(qmtm_dev);+if(ret<0)+gotoout_free;++/* register with uio framework */+ret=uio_register_device(&pdev->dev,info);+if(ret<0)+gotoout_free;++dev_info(&pdev->dev,"%s registered as UIO device.\n",info->name);++platform_set_drvdata(pdev,qmtm_dev);+return0;++out_free:+qmtm_cleanup(pdev,qmtm_dev);+returnret;+}++staticintqmtm_remove(structplatform_device*pdev)+{+structuio_qmtm_dev*qmtm_dev=platform_get_drvdata(pdev);++qmtm_cleanup(pdev,qmtm_dev);+return0;+}++staticstructof_device_idqmtm_match[]={+{.compatible="apm,xgene-qmtm-uio",},+{},+};++MODULE_DEVICE_TABLE(of,qmtm_match);++staticstructplatform_driverqmtm_driver={+.driver={+.name=DRV_NAME,+.owner=THIS_MODULE,+.of_match_table=qmtm_match,+},+.probe=qmtm_probe,+.remove=qmtm_remove,+};++module_platform_driver(qmtm_driver);++MODULE_LICENSE("GPL v2");+MODULE_VERSION(DRV_VERSION);+MODULE_AUTHOR("Ankit Jindal <ankit.jindal@linaro.org>");+MODULE_AUTHOR("Tushar Jagad <tushar.jagad@linaro.org>");
Why not...
void __iomem *base = qmtm_dev->info->mem[0].internal_addr;
writel(data, addr + offset);
We permit void pointer arithmetic in the kernel.
+static int qmtm_reset(struct uio_qmtm_dev *qmtm_dev)
+{
...
+ /* check whether device is out of reset or not */
+ do {
+ val = qmtm_csr_read(qmtm_dev, QMTM_CFG_MEM_RAM_SHUTDOWN);
+
+ if (!wait--)
+ return -1;
+ udelay(1);
+ } while (val == 0xffffffff);
There's two points about the above:
1. The loop is buggy. A correct implementation would:
- test for the success condition
- on success, break out of the loop
- decrement the timeout, and break out of the loop if we have timed out
- delay the required delay
- repeat
Note that this means that we will always check for success before
deciding whether we've failed or not, /and/ without penalty of an
unnecessary delay (as you have.)
2. returning -1 here is not on. This value can (via your probe
function) be propagated to userspace, where it will be interpreted
as an -EPERM error. Wouldn't a proper errno be better?
So what if we hit a failure at
platform_get_resource(pdev, IORESOURCE_MEM, 0);
in the probe function below, and call this function. The purpose of the
devm_* stuff is to avoid these kinds of error-cleanup errors by automating
that stuff. devm_* APIs record the resource allocations against the
device, and when the probe function fails, or the driver is unbound, the
devm_* resources claimed in the probe function are freed.
All of the above, with the exception of uio_unregister_device() and the
missing clk_unprepare_disable() can be left to the devm_* stuff to deal
with, if you'd used the devm_* functions in the probe function.
+}
+
+static int qmtm_probe(struct platform_device *pdev)
+{
+ struct uio_info *info;
+ struct uio_qmtm_dev *qmtm_dev;
+ struct resource *csr;
+ struct resource *fabric;
+ struct resource *qpool;
+ unsigned int num_queues;
+ unsigned int devid;
+ int ret = -ENODEV;
Probably a bad idea to use a standard value. You probably have some
error codes you've forgotten to propagate.
+ return -ENOMEM;
+ }
+
+ /* Power on qmtm in case its not done as part of boot-loader */
+ qmtm_dev->qmtm_clk = clk_get(&pdev->dev, NULL);
devm_clk_get
+ if (IS_ERR(qmtm_dev->qmtm_clk)) {
+ dev_err(&pdev->dev, "Failed to get clock\n");
+ ret = PTR_ERR(qmtm_dev->qmtm_clk);
+ kfree(qmtm_dev->info);
+ kfree(qmtm_dev);
+ info->version = DRV_VERSION;
+
+ info->priv = qmtm_dev;
+ info->open = qmtm_open;
+ info->release = qmtm_release;
+
+ /* get the qmtm out of reset */
+ ret = qmtm_reset(qmtm_dev);
+ if (ret < 0)
+ goto out_free;
Here you propagate that -1 value out of your probe function to userspace.
If you want to do this, please choose a reasonable error code, rather
than -EPERM.
+
+ /* register with uio framework */
+ ret = uio_register_device(&pdev->dev, info);
+ if (ret < 0)
+ goto out_free;
+
+ dev_info(&pdev->dev, "%s registered as UIO device.\n", info->name);
Does this printk serve a useful purpose? Most other UIO drivers don't
bother printing anything, though if you do print something, it may be
useful to mention which uio device it is associated with.
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
Why not...
void __iomem *base = qmtm_dev->info->mem[0].internal_addr;
writel(data, addr + offset);
We permit void pointer arithmetic in the kernel.
quoted
+static int qmtm_reset(struct uio_qmtm_dev *qmtm_dev)
+{
...
quoted
+ /* check whether device is out of reset or not */
+ do {
+ val = qmtm_csr_read(qmtm_dev, QMTM_CFG_MEM_RAM_SHUTDOWN);
+
+ if (!wait--)
+ return -1;
+ udelay(1);
+ } while (val == 0xffffffff);
There's two points about the above:
1. The loop is buggy. A correct implementation would:
- test for the success condition
- on success, break out of the loop
- decrement the timeout, and break out of the loop if we have timed out
- delay the required delay
- repeat
Note that this means that we will always check for success before
deciding whether we've failed or not, /and/ without penalty of an
unnecessary delay (as you have.)
2. returning -1 here is not on. This value can (via your probe
function) be propagated to userspace, where it will be interpreted
as an -EPERM error. Wouldn't a proper errno be better?
So what if we hit a failure at
platform_get_resource(pdev, IORESOURCE_MEM, 0);
in the probe function below, and call this function. The purpose of the
devm_* stuff is to avoid these kinds of error-cleanup errors by automating
that stuff. devm_* APIs record the resource allocations against the
device, and when the probe function fails, or the driver is unbound, the
devm_* resources claimed in the probe function are freed.
All of the above, with the exception of uio_unregister_device() and the
missing clk_unprepare_disable() can be left to the devm_* stuff to deal
with, if you'd used the devm_* functions in the probe function.
quoted
+}
+
+static int qmtm_probe(struct platform_device *pdev)
+{
+ struct uio_info *info;
+ struct uio_qmtm_dev *qmtm_dev;
+ struct resource *csr;
+ struct resource *fabric;
+ struct resource *qpool;
+ unsigned int num_queues;
+ unsigned int devid;
+ int ret = -ENODEV;
Probably a bad idea to use a standard value. You probably have some
error codes you've forgotten to propagate.
+ return -ENOMEM;
+ }
+
+ /* Power on qmtm in case its not done as part of boot-loader */
+ qmtm_dev->qmtm_clk = clk_get(&pdev->dev, NULL);
devm_clk_get
quoted
+ if (IS_ERR(qmtm_dev->qmtm_clk)) {
+ dev_err(&pdev->dev, "Failed to get clock\n");
+ ret = PTR_ERR(qmtm_dev->qmtm_clk);
+ kfree(qmtm_dev->info);
+ kfree(qmtm_dev);
+ info->version = DRV_VERSION;
+
+ info->priv = qmtm_dev;
+ info->open = qmtm_open;
+ info->release = qmtm_release;
+
+ /* get the qmtm out of reset */
+ ret = qmtm_reset(qmtm_dev);
+ if (ret < 0)
+ goto out_free;
Here you propagate that -1 value out of your probe function to userspace.
If you want to do this, please choose a reasonable error code, rather
than -EPERM.
quoted
+
+ /* register with uio framework */
+ ret = uio_register_device(&pdev->dev, info);
+ if (ret < 0)
+ goto out_free;
+
+ dev_info(&pdev->dev, "%s registered as UIO device.\n", info->name);
Does this printk serve a useful purpose? Most other UIO drivers don't
bother printing anything, though if you do print something, it may be
useful to mention which uio device it is associated with.
Thanks, will incorporate all the suggested changes in next version.
Thanks,
Ankit
@@ -0,0 +1,45 @@+APM X-Gene QMTM UIO nodes++QMTM UIO nodes are defined for user space access to on-chip QMTM device+on APM X-Gene SOC using UIO framework.++Required properties:+- compatible: Should be "apm,xgene-qmtm-uio"+- reg: Address and length of the register set for the device. It contains the+ information of registers in the same order as described by reg-names.+- reg-names: Should contain the register set names+ - "csr": QMTM control and status register address space.+ - "fabric": QMTM memory mapped access to queue states.+ - "qpool": Memory location for creating QMTM queues. This could be some+ SRAM or reserved portion of RAM. It is expected that size and location+ of qpool memory will be configurable via bootloader.+- clocks: Reference to the clock entry.+- num_queues: Number of queues under this QMTM device.+- devid: QMTM identification number for the system having multiple QMTM devices++Optional properties:+- status: Should be "ok" or "disabled" for enabled/disabled. Default is "ok".++Example:+ qmtm1clk: qmtmclk at 1f20c000 {+ compatible = "apm,xgene-device-clock";+ clock-output-names = "qmtm1clk";+ status = "ok";+ };++ qmtm1_uio: qmtm_uio at 1f200000 {+ compatible = "apm,xgene-qmtm-uio";+ status = "disabled";+ reg = <0x0 0x1f200000 0x0 0x10000+ 0x0 0x1b000000 0x0 0x400000+ 0x0 0x00000000 0x0 0x0>;/* filled by bootloader */+ reg-names = "csr", "fabric", "qpool";+ clocks = <&qmtm1clk 0>;+ num_queues = <0x400>;+ devid = <1>;+ };++ /* Board-specific peripheral configurations */+ &qmtm1_uio {+ status = "ok";+ };
@@ -0,0 +1,45 @@+APM X-Gene QMTM UIO nodes++QMTM UIO nodes are defined for user space access to on-chip QMTM device+on APM X-Gene SOC using UIO framework.+
Userspace vs kernel space has precisely _nothing_ to do with a HW
description.
This doesn't describe at all what the device is (e.g. what does QMTM
stand for, what is it used for?).
NAK.
Please ensure you Cc the devicetree list (devicetree at vger.kernel.org) in
future.
+Required properties:
+- compatible: Should be "apm,xgene-qmtm-uio"
This should definitely not have "uio" in the name.
+- reg: Address and length of the register set for the device. It contains the
+ information of registers in the same order as described by reg-names.
+- reg-names: Should contain the register set names
+ - "csr": QMTM control and status register address space.
+ - "fabric": QMTM memory mapped access to queue states.
These look ok, I guess.
+ - "qpool": Memory location for creating QMTM queues. This could be some
+ SRAM or reserved portion of RAM. It is expected that size and location
+ of qpool memory will be configurable via bootloader.
I don't follow why this should be described in a reg entry. This is not
a property of the device; this is a separate resource being assigned to
the device.
Why can the kernel not allocate this dynamically?
If you need a specific fixed pool, use the reserved-memory bindings.
+- clocks: Reference to the clock entry.
There is only one clock input to the IP block?
+- num_queues: Number of queues under this QMTM device.
s/_/-/, property names should use '-' rather than '_'.
+- devid: QMTM identification number for the system having multiple QMTM devices
What exactly is this used for? Why is the reg entry not sufficient?
+Optional properties:
+- status: Should be "ok" or "disabled" for enabled/disabled. Default is "ok".
This is so standard I don't see the point in documenting it.
Mark.
@@ -0,0 +1,45 @@+APM X-Gene QMTM UIO nodes++QMTM UIO nodes are defined for user space access to on-chip QMTM device+on APM X-Gene SOC using UIO framework.+
Userspace vs kernel space has precisely _nothing_ to do with a HW
description.
This doesn't describe at all what the device is (e.g. what does QMTM
stand for, what is it used for?).
NAK.
QMTM stands for queue manager and traffic manager. It is device managing
the hardware queues. It also implements QoS among hardware queues hence
term "traffic" manager is present in its name.
Sure, I will add more info about the device in the next revision.
The primary purpose of QMTM UIO driver is to expose QMTM HW to
user space so that frameworks like ODP (OpenDataPlane) can use
this from user space.
Please ensure you Cc the devicetree list (devicetree at vger.kernel.org) in
future.
Sure, will do.
quoted
+Required properties:
+- compatible: Should be "apm,xgene-qmtm-uio"
This should definitely not have "uio" in the name.
I added "uio" in compatible string because in future APM might
add separate driver for accessing QMTM from kernel space.
Can you suggest better compatible strings for this UIO driver?
quoted
+- reg: Address and length of the register set for the device. It contains the
+ information of registers in the same order as described by reg-names.
+- reg-names: Should contain the register set names
+ - "csr": QMTM control and status register address space.
+ - "fabric": QMTM memory mapped access to queue states.
These look ok, I guess.
quoted
+ - "qpool": Memory location for creating QMTM queues. This could be some
+ SRAM or reserved portion of RAM. It is expected that size and location
+ of qpool memory will be configurable via bootloader.
I don't follow why this should be described in a reg entry. This is not
a property of the device; this is a separate resource being assigned to
the device.
Ok, I will remove it from reg and add "qpool-addr" and "qpool-size"
attributes to
point the location of qpool.
Why can the kernel not allocate this dynamically?
For faster access, this can be on-chip memory as well.
If you need a specific fixed pool, use the reserved-memory bindings.
reserved-memory only apply to RAM, it does not apply to on-chip
SRAMs. Right ?
quoted
+- clocks: Reference to the clock entry.
There is only one clock input to the IP block?
Yes.
quoted
+- num_queues: Number of queues under this QMTM device.
s/_/-/, property names should use '-' rather than '_'.
Sure, will rename it in next revision.
quoted
+- devid: QMTM identification number for the system having multiple QMTM devices
What exactly is this used for? Why is the reg entry not sufficient?
When there are multiple QMTM devices, the devid is used to form a
unique id (a tuple of queue number and device id) for the queues
belonging to this device. Unfortunately, we don't have any register
providing the devid of the device.
quoted
+Optional properties:
+- status: Should be "ok" or "disabled" for enabled/disabled. Default is "ok".
This is so standard I don't see the point in documenting it.