* [PATCH V4 01/10] Documentation: DT: qcom_hidma: update binding for MSI
2016-09-29 2:12 ` Sinan Kaya
(?)
@ 2016-09-29 2:12 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, jcm-H+wXaHxf7aLQT0dZR+AlfA
Cc: agross-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sinan Kaya,
Rob Herring, Mark Rutland, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Adding a new binding for qcom,hidma-1.1 to distinguish HW supporting
MSI interrupts from the older revision.
Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
index fd5618b..2c5e4b8 100644
--- a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
+++ b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
@@ -47,12 +47,18 @@ When the OS is not in control of the management interface (i.e. it's a guest),
the channel nodes appear on their own, not under a management node.
Required properties:
-- compatible: must contain "qcom,hidma-1.0"
+- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
+for MSI capable HW.
- reg: Addresses for the transfer and event channel
- interrupts: Should contain the event interrupt
- desc-count: Number of asynchronous requests this channel can handle
- iommus: required a iommu node
+Optional properties for MSI:
+- msi-parent : See the generic MSI binding described in
+ devicetree/bindings/interrupt-controller/msi.txt for a description of the
+ msi-parent property.
+
Example:
Hypervisor OS configuration:
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 01/10] Documentation: DT: qcom_hidma: update binding for MSI
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: linux-arm-kernel
Adding a new binding for qcom,hidma-1.1 to distinguish HW supporting
MSI interrupts from the older revision.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
index fd5618b..2c5e4b8 100644
--- a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
+++ b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
@@ -47,12 +47,18 @@ When the OS is not in control of the management interface (i.e. it's a guest),
the channel nodes appear on their own, not under a management node.
Required properties:
-- compatible: must contain "qcom,hidma-1.0"
+- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
+for MSI capable HW.
- reg: Addresses for the transfer and event channel
- interrupts: Should contain the event interrupt
- desc-count: Number of asynchronous requests this channel can handle
- iommus: required a iommu node
+Optional properties for MSI:
+- msi-parent : See the generic MSI binding described in
+ devicetree/bindings/interrupt-controller/msi.txt for a description of the
+ msi-parent property.
+
Example:
Hypervisor OS configuration:
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 01/10] Documentation: DT: qcom_hidma: update binding for MSI
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine, timur, devicetree, cov, vinod.koul, jcm
Cc: agross, arnd, linux-arm-msm, linux-arm-kernel, Sinan Kaya,
Rob Herring, Mark Rutland, linux-kernel
Adding a new binding for qcom,hidma-1.1 to distinguish HW supporting
MSI interrupts from the older revision.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
index fd5618b..2c5e4b8 100644
--- a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
+++ b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
@@ -47,12 +47,18 @@ When the OS is not in control of the management interface (i.e. it's a guest),
the channel nodes appear on their own, not under a management node.
Required properties:
-- compatible: must contain "qcom,hidma-1.0"
+- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
+for MSI capable HW.
- reg: Addresses for the transfer and event channel
- interrupts: Should contain the event interrupt
- desc-count: Number of asynchronous requests this channel can handle
- iommus: required a iommu node
+Optional properties for MSI:
+- msi-parent : See the generic MSI binding described in
+ devicetree/bindings/interrupt-controller/msi.txt for a description of the
+ msi-parent property.
+
Example:
Hypervisor OS configuration:
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 03/10] of: irq: make of_msi_configure accessible from modules
2016-09-29 2:12 ` Sinan Kaya
(?)
@ 2016-09-29 2:12 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, jcm-H+wXaHxf7aLQT0dZR+AlfA
Cc: agross-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sinan Kaya,
Rob Herring, Frank Rowand, linux-kernel-u79uwXL29TY76Z2rM5mHXA
The of_msi_configure routine is only accessible by the built-in
kernel drivers. Export this function so that modules can use it
too.
This function is useful for configuring MSI on child device tree
nodes on hierarchical objects.
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/of/irq.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a2e68f7..20c09e0 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -767,3 +767,4 @@ void of_msi_configure(struct device *dev, struct device_node *np)
dev_set_msi_domain(dev,
of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI));
}
+EXPORT_SYMBOL_GPL(of_msi_configure);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 03/10] of: irq: make of_msi_configure accessible from modules
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: linux-arm-kernel
The of_msi_configure routine is only accessible by the built-in
kernel drivers. Export this function so that modules can use it
too.
This function is useful for configuring MSI on child device tree
nodes on hierarchical objects.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/of/irq.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a2e68f7..20c09e0 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -767,3 +767,4 @@ void of_msi_configure(struct device *dev, struct device_node *np)
dev_set_msi_domain(dev,
of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI));
}
+EXPORT_SYMBOL_GPL(of_msi_configure);
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 03/10] of: irq: make of_msi_configure accessible from modules
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine, timur, devicetree, cov, vinod.koul, jcm
Cc: agross, arnd, linux-arm-msm, linux-arm-kernel, Sinan Kaya,
Rob Herring, Frank Rowand, linux-kernel
The of_msi_configure routine is only accessible by the built-in
kernel drivers. Export this function so that modules can use it
too.
This function is useful for configuring MSI on child device tree
nodes on hierarchical objects.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/of/irq.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a2e68f7..20c09e0 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -767,3 +767,4 @@ void of_msi_configure(struct device *dev, struct device_node *np)
dev_set_msi_domain(dev,
of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI));
}
+EXPORT_SYMBOL_GPL(of_msi_configure);
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
2016-09-29 2:12 ` Sinan Kaya
(?)
@ 2016-09-29 2:12 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, jcm-H+wXaHxf7aLQT0dZR+AlfA
Cc: agross-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sinan Kaya,
Dan Williams, Wei Yongjun, Andy Shevchenko,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Configure the DMA bindings for the device tree based firmware.
Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
index 82f36e4..e8f6b84 100644
--- a/drivers/dma/qcom/hidma_mgmt.c
+++ b/drivers/dma/qcom/hidma_mgmt.c
@@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
ret = PTR_ERR(new_pdev);
goto out;
}
+ of_node_get(child);
+ new_pdev->dev.of_node = child;
of_dma_configure(&new_pdev->dev, child);
-
+ of_msi_configure(&new_pdev->dev, child);
+ of_node_put(child);
kfree(res);
res = NULL;
}
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: linux-arm-kernel
Configure the DMA bindings for the device tree based firmware.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
index 82f36e4..e8f6b84 100644
--- a/drivers/dma/qcom/hidma_mgmt.c
+++ b/drivers/dma/qcom/hidma_mgmt.c
@@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
ret = PTR_ERR(new_pdev);
goto out;
}
+ of_node_get(child);
+ new_pdev->dev.of_node = child;
of_dma_configure(&new_pdev->dev, child);
-
+ of_msi_configure(&new_pdev->dev, child);
+ of_node_put(child);
kfree(res);
res = NULL;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine, timur, devicetree, cov, vinod.koul, jcm
Cc: agross, arnd, linux-arm-msm, linux-arm-kernel, Sinan Kaya,
Dan Williams, Wei Yongjun, Andy Shevchenko, linux-kernel
Configure the DMA bindings for the device tree based firmware.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
index 82f36e4..e8f6b84 100644
--- a/drivers/dma/qcom/hidma_mgmt.c
+++ b/drivers/dma/qcom/hidma_mgmt.c
@@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
ret = PTR_ERR(new_pdev);
goto out;
}
+ of_node_get(child);
+ new_pdev->dev.of_node = child;
of_dma_configure(&new_pdev->dev, child);
-
+ of_msi_configure(&new_pdev->dev, child);
+ of_node_put(child);
kfree(res);
res = NULL;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
2016-09-29 2:12 ` Sinan Kaya
@ 2016-10-01 6:17 ` Vinod Koul
-1 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-01 6:17 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Wei Yongjun,
Andy Shevchenko, linux-kernel
On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
> Configure the DMA bindings for the device tree based firmware.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
> index 82f36e4..e8f6b84 100644
> --- a/drivers/dma/qcom/hidma_mgmt.c
> +++ b/drivers/dma/qcom/hidma_mgmt.c
> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
> ret = PTR_ERR(new_pdev);
> goto out;
> }
> + of_node_get(child);
> + new_pdev->dev.of_node = child;
> of_dma_configure(&new_pdev->dev, child);
> -
> + of_msi_configure(&new_pdev->dev, child);
> + of_node_put(child);
should this be done unconditionally? Dont we needto call this only for
platforms with msi?
> kfree(res);
> res = NULL;
> }
> --
> 1.9.1
>
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-10-01 6:17 ` Vinod Koul
0 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-01 6:17 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
> Configure the DMA bindings for the device tree based firmware.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
> index 82f36e4..e8f6b84 100644
> --- a/drivers/dma/qcom/hidma_mgmt.c
> +++ b/drivers/dma/qcom/hidma_mgmt.c
> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
> ret = PTR_ERR(new_pdev);
> goto out;
> }
> + of_node_get(child);
> + new_pdev->dev.of_node = child;
> of_dma_configure(&new_pdev->dev, child);
> -
> + of_msi_configure(&new_pdev->dev, child);
> + of_node_put(child);
should this be done unconditionally? Dont we needto call this only for
platforms with msi?
> kfree(res);
> res = NULL;
> }
> --
> 1.9.1
>
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
2016-10-01 6:17 ` Vinod Koul
@ 2016-10-01 15:15 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-01 15:15 UTC (permalink / raw)
To: Vinod Koul
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Wei Yongjun,
Andy Shevchenko, linux-kernel
On 10/1/2016 2:17 AM, Vinod Koul wrote:
> On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
>> Configure the DMA bindings for the device tree based firmware.
>>
>> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>> ---
>> drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
>> index 82f36e4..e8f6b84 100644
>> --- a/drivers/dma/qcom/hidma_mgmt.c
>> +++ b/drivers/dma/qcom/hidma_mgmt.c
>> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
>> ret = PTR_ERR(new_pdev);
>> goto out;
>> }
>> + of_node_get(child);
>> + new_pdev->dev.of_node = child;
>> of_dma_configure(&new_pdev->dev, child);
>> -
>> + of_msi_configure(&new_pdev->dev, child);
>> + of_node_put(child);
>
> should this be done unconditionally? Dont we needto call this only for
> platforms with msi?
I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
side effects on my testing either.
>
>> kfree(res);
>> res = NULL;
>> }
>> --
>> 1.9.1
>>
>
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-10-01 15:15 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-01 15:15 UTC (permalink / raw)
To: linux-arm-kernel
On 10/1/2016 2:17 AM, Vinod Koul wrote:
> On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
>> Configure the DMA bindings for the device tree based firmware.
>>
>> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>> ---
>> drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
>> index 82f36e4..e8f6b84 100644
>> --- a/drivers/dma/qcom/hidma_mgmt.c
>> +++ b/drivers/dma/qcom/hidma_mgmt.c
>> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
>> ret = PTR_ERR(new_pdev);
>> goto out;
>> }
>> + of_node_get(child);
>> + new_pdev->dev.of_node = child;
>> of_dma_configure(&new_pdev->dev, child);
>> -
>> + of_msi_configure(&new_pdev->dev, child);
>> + of_node_put(child);
>
> should this be done unconditionally? Dont we needto call this only for
> platforms with msi?
I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
side effects on my testing either.
>
>> kfree(res);
>> res = NULL;
>> }
>> --
>> 1.9.1
>>
>
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
2016-10-01 15:15 ` Sinan Kaya
@ 2016-10-03 3:38 ` Vinod Koul
-1 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-03 3:38 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Wei Yongjun,
Andy Shevchenko, linux-kernel
On Sat, Oct 01, 2016 at 11:15:00AM -0400, Sinan Kaya wrote:
> On 10/1/2016 2:17 AM, Vinod Koul wrote:
> > On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
> >> Configure the DMA bindings for the device tree based firmware.
> >>
> >> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> >> ---
> >> drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
> >> 1 file changed, 4 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
> >> index 82f36e4..e8f6b84 100644
> >> --- a/drivers/dma/qcom/hidma_mgmt.c
> >> +++ b/drivers/dma/qcom/hidma_mgmt.c
> >> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
> >> ret = PTR_ERR(new_pdev);
> >> goto out;
> >> }
> >> + of_node_get(child);
> >> + new_pdev->dev.of_node = child;
> >> of_dma_configure(&new_pdev->dev, child);
> >> -
> >> + of_msi_configure(&new_pdev->dev, child);
> >> + of_node_put(child);
> >
> > should this be done unconditionally? Dont we needto call this only for
> > platforms with msi?
>
> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
> nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
> side effects on my testing either.
yeah later on I did look up the of_msi_configure() and I suspected this. I
think it would be worthwhile to document this assumption here.
Thanks
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-10-03 3:38 ` Vinod Koul
0 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-03 3:38 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Oct 01, 2016 at 11:15:00AM -0400, Sinan Kaya wrote:
> On 10/1/2016 2:17 AM, Vinod Koul wrote:
> > On Wed, Sep 28, 2016 at 10:12:41PM -0400, Sinan Kaya wrote:
> >> Configure the DMA bindings for the device tree based firmware.
> >>
> >> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> >> ---
> >> drivers/dma/qcom/hidma_mgmt.c | 5 ++++-
> >> 1 file changed, 4 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
> >> index 82f36e4..e8f6b84 100644
> >> --- a/drivers/dma/qcom/hidma_mgmt.c
> >> +++ b/drivers/dma/qcom/hidma_mgmt.c
> >> @@ -375,8 +375,11 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
> >> ret = PTR_ERR(new_pdev);
> >> goto out;
> >> }
> >> + of_node_get(child);
> >> + new_pdev->dev.of_node = child;
> >> of_dma_configure(&new_pdev->dev, child);
> >> -
> >> + of_msi_configure(&new_pdev->dev, child);
> >> + of_node_put(child);
> >
> > should this be done unconditionally? Dont we needto call this only for
> > platforms with msi?
>
> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
> nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
> side effects on my testing either.
yeah later on I did look up the of_msi_configure() and I suspected this. I
think it would be worthwhile to document this assumption here.
Thanks
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
2016-10-03 3:38 ` Vinod Koul
(?)
@ 2016-10-03 13:39 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-03 13:39 UTC (permalink / raw)
To: Vinod Koul
Cc: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
jcm-H+wXaHxf7aLQT0dZR+AlfA, agross-sgV2jX0FEOL9JmXXK+q4OQ,
arnd-r2nGTMty4D4, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Dan Williams,
Wei Yongjun, Andy Shevchenko,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 10/2/2016 11:38 PM, Vinod Koul wrote:
>> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
>> > nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
>> > side effects on my testing either.
> yeah later on I did look up the of_msi_configure() and I suspected this. I
> think it would be worthwhile to document this assumption here.
Sure, let me do that.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-10-03 13:39 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-03 13:39 UTC (permalink / raw)
To: linux-arm-kernel
On 10/2/2016 11:38 PM, Vinod Koul wrote:
>> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
>> > nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
>> > side effects on my testing either.
> yeah later on I did look up the of_msi_configure() and I suspected this. I
> think it would be worthwhile to document this assumption here.
Sure, let me do that.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH V4 04/10] dmaengine: qcom_hidma: configure DMA and MSI for OF
@ 2016-10-03 13:39 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-03 13:39 UTC (permalink / raw)
To: Vinod Koul
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Wei Yongjun,
Andy Shevchenko, linux-kernel
On 10/2/2016 11:38 PM, Vinod Koul wrote:
>> I followed the pattern in of_platform_device_create_pdata function. of_msi_configure does
>> > nothing if MSI is not enabled as irq_find_matching_host returns NULL. It didn't have any
>> > side effects on my testing either.
> yeah later on I did look up the of_msi_configure() and I suspected this. I
> think it would be worthwhile to document this assumption here.
Sure, let me do that.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
2016-09-29 2:12 ` Sinan Kaya
(?)
@ 2016-09-29 2:12 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, jcm-H+wXaHxf7aLQT0dZR+AlfA
Cc: agross-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sinan Kaya,
Dan Williams, Andy Shevchenko,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Getting ready for the MSI interrupts. The pending_tre_count is used
in the interrupt handler to make sure all outstanding requests are
serviced.
Making it atomic so that it can be updated from multiple contexts.
Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/dma/qcom/hidma.h | 2 +-
drivers/dma/qcom/hidma_dbg.c | 3 ++-
drivers/dma/qcom/hidma_ll.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
index e52e207..3f2ddd4 100644
--- a/drivers/dma/qcom/hidma.h
+++ b/drivers/dma/qcom/hidma.h
@@ -58,7 +58,7 @@ struct hidma_lldev {
void __iomem *evca; /* Event Channel address */
struct hidma_tre
**pending_tre_list; /* Pointers to pending TREs */
- s32 pending_tre_count; /* Number of TREs pending */
+ atomic_t pending_tre_count; /* Number of TREs pending */
void *tre_ring; /* TRE ring */
dma_addr_t tre_dma; /* TRE ring to be shared with HW */
diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c
index fa827e5..87db285 100644
--- a/drivers/dma/qcom/hidma_dbg.c
+++ b/drivers/dma/qcom/hidma_dbg.c
@@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
- seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
+ seq_printf(s, "pending_tre_count=%d\n",
+ atomic_read(&lldev->pending_tre_count));
seq_printf(s, "evca=%p\n", lldev->evca);
seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 3224f24..29fef4f 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
* Keep track of pending TREs that SW is expecting to receive
* from HW. We got one now. Decrement our counter.
*/
- lldev->pending_tre_count--;
- if (lldev->pending_tre_count < 0) {
+ if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
dev_warn(lldev->dev, "tre count mismatch on completion");
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
}
spin_unlock_irqrestore(&lldev->lock, flags);
@@ -321,7 +320,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
u32 tre_read_off;
tre_iterator = lldev->tre_processed_off;
- while (lldev->pending_tre_count) {
+ while (atomic_read(&lldev->pending_tre_count)) {
if (hidma_post_completed(lldev, tre_iterator, err_info,
err_code))
break;
@@ -548,7 +547,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
tre->err_code = 0;
tre->err_info = 0;
tre->queued = 1;
- lldev->pending_tre_count++;
+ atomic_inc(&lldev->pending_tre_count);
lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
% lldev->tre_ring_size;
spin_unlock_irqrestore(&lldev->lock, flags);
@@ -654,7 +653,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
u32 val;
u32 nr_tres = lldev->nr_tres;
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
lldev->tre_processed_off = 0;
lldev->evre_processed_off = 0;
lldev->tre_write_offset = 0;
@@ -816,7 +815,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev)
tasklet_kill(&lldev->task);
memset(lldev->trepool, 0, required_bytes);
lldev->trepool = NULL;
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
lldev->tre_write_offset = 0;
rc = hidma_ll_reset(lldev);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: linux-arm-kernel
Getting ready for the MSI interrupts. The pending_tre_count is used
in the interrupt handler to make sure all outstanding requests are
serviced.
Making it atomic so that it can be updated from multiple contexts.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma.h | 2 +-
drivers/dma/qcom/hidma_dbg.c | 3 ++-
drivers/dma/qcom/hidma_ll.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
index e52e207..3f2ddd4 100644
--- a/drivers/dma/qcom/hidma.h
+++ b/drivers/dma/qcom/hidma.h
@@ -58,7 +58,7 @@ struct hidma_lldev {
void __iomem *evca; /* Event Channel address */
struct hidma_tre
**pending_tre_list; /* Pointers to pending TREs */
- s32 pending_tre_count; /* Number of TREs pending */
+ atomic_t pending_tre_count; /* Number of TREs pending */
void *tre_ring; /* TRE ring */
dma_addr_t tre_dma; /* TRE ring to be shared with HW */
diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c
index fa827e5..87db285 100644
--- a/drivers/dma/qcom/hidma_dbg.c
+++ b/drivers/dma/qcom/hidma_dbg.c
@@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
- seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
+ seq_printf(s, "pending_tre_count=%d\n",
+ atomic_read(&lldev->pending_tre_count));
seq_printf(s, "evca=%p\n", lldev->evca);
seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 3224f24..29fef4f 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
* Keep track of pending TREs that SW is expecting to receive
* from HW. We got one now. Decrement our counter.
*/
- lldev->pending_tre_count--;
- if (lldev->pending_tre_count < 0) {
+ if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
dev_warn(lldev->dev, "tre count mismatch on completion");
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
}
spin_unlock_irqrestore(&lldev->lock, flags);
@@ -321,7 +320,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
u32 tre_read_off;
tre_iterator = lldev->tre_processed_off;
- while (lldev->pending_tre_count) {
+ while (atomic_read(&lldev->pending_tre_count)) {
if (hidma_post_completed(lldev, tre_iterator, err_info,
err_code))
break;
@@ -548,7 +547,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
tre->err_code = 0;
tre->err_info = 0;
tre->queued = 1;
- lldev->pending_tre_count++;
+ atomic_inc(&lldev->pending_tre_count);
lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
% lldev->tre_ring_size;
spin_unlock_irqrestore(&lldev->lock, flags);
@@ -654,7 +653,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
u32 val;
u32 nr_tres = lldev->nr_tres;
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
lldev->tre_processed_off = 0;
lldev->evre_processed_off = 0;
lldev->tre_write_offset = 0;
@@ -816,7 +815,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev)
tasklet_kill(&lldev->task);
memset(lldev->trepool, 0, required_bytes);
lldev->trepool = NULL;
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
lldev->tre_write_offset = 0;
rc = hidma_ll_reset(lldev);
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine, timur, devicetree, cov, vinod.koul, jcm
Cc: agross, arnd, linux-arm-msm, linux-arm-kernel, Sinan Kaya,
Dan Williams, Andy Shevchenko, linux-kernel
Getting ready for the MSI interrupts. The pending_tre_count is used
in the interrupt handler to make sure all outstanding requests are
serviced.
Making it atomic so that it can be updated from multiple contexts.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma.h | 2 +-
drivers/dma/qcom/hidma_dbg.c | 3 ++-
drivers/dma/qcom/hidma_ll.c | 13 ++++++-------
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
index e52e207..3f2ddd4 100644
--- a/drivers/dma/qcom/hidma.h
+++ b/drivers/dma/qcom/hidma.h
@@ -58,7 +58,7 @@ struct hidma_lldev {
void __iomem *evca; /* Event Channel address */
struct hidma_tre
**pending_tre_list; /* Pointers to pending TREs */
- s32 pending_tre_count; /* Number of TREs pending */
+ atomic_t pending_tre_count; /* Number of TREs pending */
void *tre_ring; /* TRE ring */
dma_addr_t tre_dma; /* TRE ring to be shared with HW */
diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c
index fa827e5..87db285 100644
--- a/drivers/dma/qcom/hidma_dbg.c
+++ b/drivers/dma/qcom/hidma_dbg.c
@@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
- seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
+ seq_printf(s, "pending_tre_count=%d\n",
+ atomic_read(&lldev->pending_tre_count));
seq_printf(s, "evca=%p\n", lldev->evca);
seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 3224f24..29fef4f 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
* Keep track of pending TREs that SW is expecting to receive
* from HW. We got one now. Decrement our counter.
*/
- lldev->pending_tre_count--;
- if (lldev->pending_tre_count < 0) {
+ if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
dev_warn(lldev->dev, "tre count mismatch on completion");
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
}
spin_unlock_irqrestore(&lldev->lock, flags);
@@ -321,7 +320,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
u32 tre_read_off;
tre_iterator = lldev->tre_processed_off;
- while (lldev->pending_tre_count) {
+ while (atomic_read(&lldev->pending_tre_count)) {
if (hidma_post_completed(lldev, tre_iterator, err_info,
err_code))
break;
@@ -548,7 +547,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
tre->err_code = 0;
tre->err_info = 0;
tre->queued = 1;
- lldev->pending_tre_count++;
+ atomic_inc(&lldev->pending_tre_count);
lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
% lldev->tre_ring_size;
spin_unlock_irqrestore(&lldev->lock, flags);
@@ -654,7 +653,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
u32 val;
u32 nr_tres = lldev->nr_tres;
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
lldev->tre_processed_off = 0;
lldev->evre_processed_off = 0;
lldev->tre_write_offset = 0;
@@ -816,7 +815,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev)
tasklet_kill(&lldev->task);
memset(lldev->trepool, 0, required_bytes);
lldev->trepool = NULL;
- lldev->pending_tre_count = 0;
+ atomic_set(&lldev->pending_tre_count, 0);
lldev->tre_write_offset = 0;
rc = hidma_ll_reset(lldev);
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
2016-09-29 2:12 ` Sinan Kaya
@ 2016-10-01 6:19 ` Vinod Koul
-1 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-01 6:19 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Andy Shevchenko,
linux-kernel
On Wed, Sep 28, 2016 at 10:12:42PM -0400, Sinan Kaya wrote:
> Getting ready for the MSI interrupts. The pending_tre_count is used
> in the interrupt handler to make sure all outstanding requests are
> serviced.
>
> Making it atomic so that it can be updated from multiple contexts.
How is it multiple contexts? It's either existing context of MSI, not both!
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/dma/qcom/hidma.h | 2 +-
> drivers/dma/qcom/hidma_dbg.c | 3 ++-
> drivers/dma/qcom/hidma_ll.c | 13 ++++++-------
> 3 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
> index e52e207..3f2ddd4 100644
> --- a/drivers/dma/qcom/hidma.h
> +++ b/drivers/dma/qcom/hidma.h
> @@ -58,7 +58,7 @@ struct hidma_lldev {
> void __iomem *evca; /* Event Channel address */
> struct hidma_tre
> **pending_tre_list; /* Pointers to pending TREs */
> - s32 pending_tre_count; /* Number of TREs pending */
> + atomic_t pending_tre_count; /* Number of TREs pending */
>
> void *tre_ring; /* TRE ring */
> dma_addr_t tre_dma; /* TRE ring to be shared with HW */
> diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c
> index fa827e5..87db285 100644
> --- a/drivers/dma/qcom/hidma_dbg.c
> +++ b/drivers/dma/qcom/hidma_dbg.c
> @@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
> seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
> seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
> seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
> - seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
> + seq_printf(s, "pending_tre_count=%d\n",
> + atomic_read(&lldev->pending_tre_count));
> seq_printf(s, "evca=%p\n", lldev->evca);
> seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
> seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
> diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
> index 3224f24..29fef4f 100644
> --- a/drivers/dma/qcom/hidma_ll.c
> +++ b/drivers/dma/qcom/hidma_ll.c
> @@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
> * Keep track of pending TREs that SW is expecting to receive
> * from HW. We got one now. Decrement our counter.
> */
> - lldev->pending_tre_count--;
> - if (lldev->pending_tre_count < 0) {
> + if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
> dev_warn(lldev->dev, "tre count mismatch on completion");
> - lldev->pending_tre_count = 0;
> + atomic_set(&lldev->pending_tre_count, 0);
> }
>
> spin_unlock_irqrestore(&lldev->lock, flags);
> @@ -321,7 +320,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
> u32 tre_read_off;
>
> tre_iterator = lldev->tre_processed_off;
> - while (lldev->pending_tre_count) {
> + while (atomic_read(&lldev->pending_tre_count)) {
> if (hidma_post_completed(lldev, tre_iterator, err_info,
> err_code))
> break;
> @@ -548,7 +547,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
> tre->err_code = 0;
> tre->err_info = 0;
> tre->queued = 1;
> - lldev->pending_tre_count++;
> + atomic_inc(&lldev->pending_tre_count);
> lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
> % lldev->tre_ring_size;
> spin_unlock_irqrestore(&lldev->lock, flags);
> @@ -654,7 +653,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
> u32 val;
> u32 nr_tres = lldev->nr_tres;
>
> - lldev->pending_tre_count = 0;
> + atomic_set(&lldev->pending_tre_count, 0);
> lldev->tre_processed_off = 0;
> lldev->evre_processed_off = 0;
> lldev->tre_write_offset = 0;
> @@ -816,7 +815,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev)
> tasklet_kill(&lldev->task);
> memset(lldev->trepool, 0, required_bytes);
> lldev->trepool = NULL;
> - lldev->pending_tre_count = 0;
> + atomic_set(&lldev->pending_tre_count, 0);
> lldev->tre_write_offset = 0;
>
> rc = hidma_ll_reset(lldev);
> --
> 1.9.1
>
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
@ 2016-10-01 6:19 ` Vinod Koul
0 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-01 6:19 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Sep 28, 2016 at 10:12:42PM -0400, Sinan Kaya wrote:
> Getting ready for the MSI interrupts. The pending_tre_count is used
> in the interrupt handler to make sure all outstanding requests are
> serviced.
>
> Making it atomic so that it can be updated from multiple contexts.
How is it multiple contexts? It's either existing context of MSI, not both!
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/dma/qcom/hidma.h | 2 +-
> drivers/dma/qcom/hidma_dbg.c | 3 ++-
> drivers/dma/qcom/hidma_ll.c | 13 ++++++-------
> 3 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
> index e52e207..3f2ddd4 100644
> --- a/drivers/dma/qcom/hidma.h
> +++ b/drivers/dma/qcom/hidma.h
> @@ -58,7 +58,7 @@ struct hidma_lldev {
> void __iomem *evca; /* Event Channel address */
> struct hidma_tre
> **pending_tre_list; /* Pointers to pending TREs */
> - s32 pending_tre_count; /* Number of TREs pending */
> + atomic_t pending_tre_count; /* Number of TREs pending */
>
> void *tre_ring; /* TRE ring */
> dma_addr_t tre_dma; /* TRE ring to be shared with HW */
> diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c
> index fa827e5..87db285 100644
> --- a/drivers/dma/qcom/hidma_dbg.c
> +++ b/drivers/dma/qcom/hidma_dbg.c
> @@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
> seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
> seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
> seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
> - seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
> + seq_printf(s, "pending_tre_count=%d\n",
> + atomic_read(&lldev->pending_tre_count));
> seq_printf(s, "evca=%p\n", lldev->evca);
> seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
> seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
> diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
> index 3224f24..29fef4f 100644
> --- a/drivers/dma/qcom/hidma_ll.c
> +++ b/drivers/dma/qcom/hidma_ll.c
> @@ -218,10 +218,9 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
> * Keep track of pending TREs that SW is expecting to receive
> * from HW. We got one now. Decrement our counter.
> */
> - lldev->pending_tre_count--;
> - if (lldev->pending_tre_count < 0) {
> + if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
> dev_warn(lldev->dev, "tre count mismatch on completion");
> - lldev->pending_tre_count = 0;
> + atomic_set(&lldev->pending_tre_count, 0);
> }
>
> spin_unlock_irqrestore(&lldev->lock, flags);
> @@ -321,7 +320,7 @@ void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
> u32 tre_read_off;
>
> tre_iterator = lldev->tre_processed_off;
> - while (lldev->pending_tre_count) {
> + while (atomic_read(&lldev->pending_tre_count)) {
> if (hidma_post_completed(lldev, tre_iterator, err_info,
> err_code))
> break;
> @@ -548,7 +547,7 @@ void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
> tre->err_code = 0;
> tre->err_info = 0;
> tre->queued = 1;
> - lldev->pending_tre_count++;
> + atomic_inc(&lldev->pending_tre_count);
> lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
> % lldev->tre_ring_size;
> spin_unlock_irqrestore(&lldev->lock, flags);
> @@ -654,7 +653,7 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
> u32 val;
> u32 nr_tres = lldev->nr_tres;
>
> - lldev->pending_tre_count = 0;
> + atomic_set(&lldev->pending_tre_count, 0);
> lldev->tre_processed_off = 0;
> lldev->evre_processed_off = 0;
> lldev->tre_write_offset = 0;
> @@ -816,7 +815,7 @@ int hidma_ll_uninit(struct hidma_lldev *lldev)
> tasklet_kill(&lldev->task);
> memset(lldev->trepool, 0, required_bytes);
> lldev->trepool = NULL;
> - lldev->pending_tre_count = 0;
> + atomic_set(&lldev->pending_tre_count, 0);
> lldev->tre_write_offset = 0;
>
> rc = hidma_ll_reset(lldev);
> --
> 1.9.1
>
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
2016-10-01 6:19 ` Vinod Koul
@ 2016-10-01 15:19 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-01 15:19 UTC (permalink / raw)
To: Vinod Koul
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Andy Shevchenko,
linux-kernel
On 10/1/2016 2:19 AM, Vinod Koul wrote:
>> Making it atomic so that it can be updated from multiple contexts.
> How is it multiple contexts? It's either existing context of MSI, not both!
>
I was trying to mean multiple processor contexts here. The driver allocates 11
MSI interrupts. Each MSI interrupt can be assigned to a different CPU. Then,
we have a race condition for common variables as they share the same interrupt
handler with a different cause bit.
I will put the above description into the commit text.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
@ 2016-10-01 15:19 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-10-01 15:19 UTC (permalink / raw)
To: linux-arm-kernel
On 10/1/2016 2:19 AM, Vinod Koul wrote:
>> Making it atomic so that it can be updated from multiple contexts.
> How is it multiple contexts? It's either existing context of MSI, not both!
>
I was trying to mean multiple processor contexts here. The driver allocates 11
MSI interrupts. Each MSI interrupt can be assigned to a different CPU. Then,
we have a race condition for common variables as they share the same interrupt
handler with a different cause bit.
I will put the above description into the commit text.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
2016-10-01 15:19 ` Sinan Kaya
@ 2016-10-03 3:39 ` Vinod Koul
-1 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-03 3:39 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, cov, jcm, agross, arnd,
linux-arm-msm, linux-arm-kernel, Dan Williams, Andy Shevchenko,
linux-kernel
On Sat, Oct 01, 2016 at 11:19:43AM -0400, Sinan Kaya wrote:
> On 10/1/2016 2:19 AM, Vinod Koul wrote:
> >> Making it atomic so that it can be updated from multiple contexts.
> > How is it multiple contexts? It's either existing context of MSI, not both!
> >
>
> I was trying to mean multiple processor contexts here. The driver allocates 11
> MSI interrupts. Each MSI interrupt can be assigned to a different CPU. Then,
> we have a race condition for common variables as they share the same interrupt
> handler with a different cause bit.
>
> I will put the above description into the commit text.
Sounds better :)
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 05/10] dmaengine: qcom_hidma: make pending_tre_count atomic
@ 2016-10-03 3:39 ` Vinod Koul
0 siblings, 0 replies; 43+ messages in thread
From: Vinod Koul @ 2016-10-03 3:39 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Oct 01, 2016 at 11:19:43AM -0400, Sinan Kaya wrote:
> On 10/1/2016 2:19 AM, Vinod Koul wrote:
> >> Making it atomic so that it can be updated from multiple contexts.
> > How is it multiple contexts? It's either existing context of MSI, not both!
> >
>
> I was trying to mean multiple processor contexts here. The driver allocates 11
> MSI interrupts. Each MSI interrupt can be assigned to a different CPU. Then,
> we have a race condition for common variables as they share the same interrupt
> handler with a different cause bit.
>
> I will put the above description into the commit text.
Sounds better :)
--
~Vinod
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH V4 08/10] dmaengine: qcom_hidma: add a common API to setup the interrupt
2016-09-29 2:12 ` Sinan Kaya
(?)
@ 2016-09-29 2:12 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, jcm-H+wXaHxf7aLQT0dZR+AlfA
Cc: agross-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sinan Kaya,
Dan Williams, Andy Shevchenko,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Introducing the hidma_ll_setup_irq function to set up the interrupt
type externally from the OS interface.
Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/dma/qcom/hidma.h | 2 ++
drivers/dma/qcom/hidma_ll.c | 27 +++++++++++++++++++++++----
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
index 3f2ddd4..181f7e0 100644
--- a/drivers/dma/qcom/hidma.h
+++ b/drivers/dma/qcom/hidma.h
@@ -46,6 +46,7 @@ struct hidma_tre {
};
struct hidma_lldev {
+ bool msi_support; /* flag indicating MSI support */
bool initialized; /* initialized flag */
u8 trch_state; /* trch_state of the device */
u8 evch_state; /* evch_state of the device */
@@ -145,6 +146,7 @@ int hidma_ll_disable(struct hidma_lldev *lldev);
int hidma_ll_enable(struct hidma_lldev *llhndl);
void hidma_ll_set_transfer_params(struct hidma_lldev *llhndl, u32 tre_ch,
dma_addr_t src, dma_addr_t dest, u32 len, u32 flags);
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi);
int hidma_ll_setup(struct hidma_lldev *lldev);
struct hidma_lldev *hidma_ll_init(struct device *dev, u32 max_channels,
void __iomem *trca, void __iomem *evca,
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 088935f..f0630e0 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -672,17 +672,36 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
writel(HIDMA_EVRE_SIZE * nr_tres,
lldev->evca + HIDMA_EVCA_RING_LEN_REG);
- /* support IRQ only for now */
+ /* configure interrupts */
+ hidma_ll_setup_irq(lldev, lldev->msi_support);
+
+ rc = hidma_ll_enable(lldev);
+ if (rc)
+ return rc;
+
+ return rc;
+}
+
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi)
+{
+ u32 val;
+
+ lldev->msi_support = msi;
+
+ /* disable interrupts again after reset */
+ writel(0, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+ writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+ /* support IRQ by default */
val = readl(lldev->evca + HIDMA_EVCA_INTCTRL_REG);
val &= ~0xF;
- val |= 0x1;
+ if (!lldev->msi_support)
+ val = val | 0x1;
writel(val, lldev->evca + HIDMA_EVCA_INTCTRL_REG);
/* clear all pending interrupts and enable them */
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
-
- return hidma_ll_enable(lldev);
}
struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 08/10] dmaengine: qcom_hidma: add a common API to setup the interrupt
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: linux-arm-kernel
Introducing the hidma_ll_setup_irq function to set up the interrupt
type externally from the OS interface.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma.h | 2 ++
drivers/dma/qcom/hidma_ll.c | 27 +++++++++++++++++++++++----
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
index 3f2ddd4..181f7e0 100644
--- a/drivers/dma/qcom/hidma.h
+++ b/drivers/dma/qcom/hidma.h
@@ -46,6 +46,7 @@ struct hidma_tre {
};
struct hidma_lldev {
+ bool msi_support; /* flag indicating MSI support */
bool initialized; /* initialized flag */
u8 trch_state; /* trch_state of the device */
u8 evch_state; /* evch_state of the device */
@@ -145,6 +146,7 @@ int hidma_ll_disable(struct hidma_lldev *lldev);
int hidma_ll_enable(struct hidma_lldev *llhndl);
void hidma_ll_set_transfer_params(struct hidma_lldev *llhndl, u32 tre_ch,
dma_addr_t src, dma_addr_t dest, u32 len, u32 flags);
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi);
int hidma_ll_setup(struct hidma_lldev *lldev);
struct hidma_lldev *hidma_ll_init(struct device *dev, u32 max_channels,
void __iomem *trca, void __iomem *evca,
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 088935f..f0630e0 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -672,17 +672,36 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
writel(HIDMA_EVRE_SIZE * nr_tres,
lldev->evca + HIDMA_EVCA_RING_LEN_REG);
- /* support IRQ only for now */
+ /* configure interrupts */
+ hidma_ll_setup_irq(lldev, lldev->msi_support);
+
+ rc = hidma_ll_enable(lldev);
+ if (rc)
+ return rc;
+
+ return rc;
+}
+
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi)
+{
+ u32 val;
+
+ lldev->msi_support = msi;
+
+ /* disable interrupts again after reset */
+ writel(0, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+ writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+ /* support IRQ by default */
val = readl(lldev->evca + HIDMA_EVCA_INTCTRL_REG);
val &= ~0xF;
- val |= 0x1;
+ if (!lldev->msi_support)
+ val = val | 0x1;
writel(val, lldev->evca + HIDMA_EVCA_INTCTRL_REG);
/* clear all pending interrupts and enable them */
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
-
- return hidma_ll_enable(lldev);
}
struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 08/10] dmaengine: qcom_hidma: add a common API to setup the interrupt
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine, timur, devicetree, cov, vinod.koul, jcm
Cc: agross, arnd, linux-arm-msm, linux-arm-kernel, Sinan Kaya,
Dan Williams, Andy Shevchenko, linux-kernel
Introducing the hidma_ll_setup_irq function to set up the interrupt
type externally from the OS interface.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma.h | 2 ++
drivers/dma/qcom/hidma_ll.c | 27 +++++++++++++++++++++++----
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/qcom/hidma.h b/drivers/dma/qcom/hidma.h
index 3f2ddd4..181f7e0 100644
--- a/drivers/dma/qcom/hidma.h
+++ b/drivers/dma/qcom/hidma.h
@@ -46,6 +46,7 @@ struct hidma_tre {
};
struct hidma_lldev {
+ bool msi_support; /* flag indicating MSI support */
bool initialized; /* initialized flag */
u8 trch_state; /* trch_state of the device */
u8 evch_state; /* evch_state of the device */
@@ -145,6 +146,7 @@ int hidma_ll_disable(struct hidma_lldev *lldev);
int hidma_ll_enable(struct hidma_lldev *llhndl);
void hidma_ll_set_transfer_params(struct hidma_lldev *llhndl, u32 tre_ch,
dma_addr_t src, dma_addr_t dest, u32 len, u32 flags);
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi);
int hidma_ll_setup(struct hidma_lldev *lldev);
struct hidma_lldev *hidma_ll_init(struct device *dev, u32 max_channels,
void __iomem *trca, void __iomem *evca,
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 088935f..f0630e0 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -672,17 +672,36 @@ int hidma_ll_setup(struct hidma_lldev *lldev)
writel(HIDMA_EVRE_SIZE * nr_tres,
lldev->evca + HIDMA_EVCA_RING_LEN_REG);
- /* support IRQ only for now */
+ /* configure interrupts */
+ hidma_ll_setup_irq(lldev, lldev->msi_support);
+
+ rc = hidma_ll_enable(lldev);
+ if (rc)
+ return rc;
+
+ return rc;
+}
+
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi)
+{
+ u32 val;
+
+ lldev->msi_support = msi;
+
+ /* disable interrupts again after reset */
+ writel(0, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+ writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+ /* support IRQ by default */
val = readl(lldev->evca + HIDMA_EVCA_INTCTRL_REG);
val &= ~0xF;
- val |= 0x1;
+ if (!lldev->msi_support)
+ val = val | 0x1;
writel(val, lldev->evca + HIDMA_EVCA_INTCTRL_REG);
/* clear all pending interrupts and enable them */
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
-
- return hidma_ll_enable(lldev);
}
struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 09/10] dmaengine: qcom_hidma: protect common data structures
2016-09-29 2:12 ` Sinan Kaya
(?)
@ 2016-09-29 2:12 ` Sinan Kaya
-1 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine-u79uwXL29TY76Z2rM5mHXA, timur-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA, cov-sgV2jX0FEOL9JmXXK+q4OQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, jcm-H+wXaHxf7aLQT0dZR+AlfA
Cc: agross-sgV2jX0FEOL9JmXXK+q4OQ, arnd-r2nGTMty4D4,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Sinan Kaya,
Dan Williams, linux-kernel-u79uwXL29TY76Z2rM5mHXA
When MSI interrupts are supported, error and the transfer interrupt can
come from multiple processor contexts.
Each error interrupt is an MSI interrupt. If the channel is disabled by
the first error interrupt, the remaining error interrupts will gracefully
return in the interrupt handler.
If an error is observed while servicing the completions in success case,
the posting of the completions will be aborted as soon as channel disabled
state is observed. The error interrupt handler will take it from there and
finish the remaining completions. We don't want to create multiple success
and error messages to be delivered to the client in mixed order.
Also got rid of hidma_post_completed method and moved the locks inside
hidma_ll_int_handler_internal function. Rearranged the assignments so that
variables are updated only when a lock is held.
Signed-off-by: Sinan Kaya <okaya-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/dma/qcom/hidma_ll.c | 142 ++++++++++++++++++--------------------------
1 file changed, 58 insertions(+), 84 deletions(-)
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index f0630e0..386a64c 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -198,18 +198,50 @@ static void hidma_ll_tre_complete(unsigned long arg)
}
}
-static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
- u8 err_info, u8 err_code)
+/*
+ * Called to handle the interrupt for the channel.
+ * Return a positive number if TRE or EVRE were consumed on this run.
+ * Return a positive number if there are pending TREs or EVREs.
+ * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
+ */
+static int hidma_handle_tre_completion(struct hidma_lldev *lldev, u8 err_info,
+ u8 err_code)
{
+ u32 *current_evre;
struct hidma_tre *tre;
unsigned long flags;
+ u32 evre_write_off;
+ u32 cfg;
+ u32 offset;
+
+ evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
+ if ((evre_write_off > lldev->evre_ring_size) ||
+ (evre_write_off % HIDMA_EVRE_SIZE)) {
+ dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
+ return -EINVAL;
+ }
spin_lock_irqsave(&lldev->lock, flags);
- tre = lldev->pending_tre_list[tre_iterator / HIDMA_TRE_SIZE];
+ if (lldev->evre_processed_off == evre_write_off) {
+ spin_unlock_irqrestore(&lldev->lock, flags);
+ return 0;
+ }
+ current_evre = lldev->evre_ring + lldev->evre_processed_off;
+ cfg = current_evre[HIDMA_EVRE_CFG_IDX];
+ if (!err_info) {
+ err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
+ err_info &= HIDMA_EVRE_ERRINFO_MASK;
+ }
+ if (!err_code)
+ err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) &
+ HIDMA_EVRE_CODE_MASK;
+
+ offset = lldev->tre_processed_off;
+ tre = lldev->pending_tre_list[offset / HIDMA_TRE_SIZE];
if (!tre) {
spin_unlock_irqrestore(&lldev->lock, flags);
dev_warn(lldev->dev, "tre_index [%d] and tre out of sync\n",
- tre_iterator / HIDMA_TRE_SIZE);
+ lldev->tre_processed_off / HIDMA_TRE_SIZE);
return -EINVAL;
}
lldev->pending_tre_list[tre->tre_index] = NULL;
@@ -223,6 +255,14 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
atomic_set(&lldev->pending_tre_count, 0);
}
+
+ HIDMA_INCREMENT_ITERATOR(lldev->tre_processed_off, HIDMA_TRE_SIZE,
+ lldev->tre_ring_size);
+ HIDMA_INCREMENT_ITERATOR(lldev->evre_processed_off, HIDMA_EVRE_SIZE,
+ lldev->evre_ring_size);
+
+ writel(lldev->evre_processed_off,
+ lldev->evca + HIDMA_EVCA_DOORBELL_REG);
spin_unlock_irqrestore(&lldev->lock, flags);
tre->err_info = err_info;
@@ -232,86 +272,7 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
kfifo_put(&lldev->handoff_fifo, tre);
tasklet_schedule(&lldev->task);
- return 0;
-}
-
-/*
- * Called to handle the interrupt for the channel.
- * Return a positive number if TRE or EVRE were consumed on this run.
- * Return a positive number if there are pending TREs or EVREs.
- * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
- */
-static int hidma_handle_tre_completion(struct hidma_lldev *lldev, u8 err_info,
- u8 err_code)
-{
- u32 evre_ring_size = lldev->evre_ring_size;
- u32 tre_ring_size = lldev->tre_ring_size;
- u32 tre_iterator, evre_iterator;
- u32 num_completed = 0;
-
- evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
- tre_iterator = lldev->tre_processed_off;
- evre_iterator = lldev->evre_processed_off;
-
- if ((evre_write_off > evre_ring_size) ||
- (evre_write_off % HIDMA_EVRE_SIZE)) {
- dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
- return 0;
- }
-
- /*
- * By the time control reaches here the number of EVREs and TREs
- * may not match. Only consume the ones that hardware told us.
- */
- while ((evre_iterator != evre_write_off)) {
- u32 *current_evre = lldev->evre_ring + evre_iterator;
- u32 cfg;
-
- cfg = current_evre[HIDMA_EVRE_CFG_IDX];
- if (!err_info) {
- err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
- err_info &= HIDMA_EVRE_ERRINFO_MASK;
- }
- if (!err_code)
- err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) &
- HIDMA_EVRE_CODE_MASK;
-
- if (hidma_post_completed(lldev, tre_iterator, err_info,
- err_code))
- break;
-
- HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
- tre_ring_size);
- HIDMA_INCREMENT_ITERATOR(evre_iterator, HIDMA_EVRE_SIZE,
- evre_ring_size);
-
- /*
- * Read the new event descriptor written by the HW.
- * As we are processing the delivered events, other events
- * get queued to the SW for processing.
- */
- evre_write_off =
- readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
- num_completed++;
- }
-
- if (num_completed) {
- u32 evre_read_off = (lldev->evre_processed_off +
- HIDMA_EVRE_SIZE * num_completed);
- u32 tre_read_off = (lldev->tre_processed_off +
- HIDMA_TRE_SIZE * num_completed);
-
- evre_read_off = evre_read_off % evre_ring_size;
- tre_read_off = tre_read_off % tre_ring_size;
-
- writel(evre_read_off, lldev->evca + HIDMA_EVCA_DOORBELL_REG);
-
- /* record the last processed tre offset */
- lldev->tre_processed_off = tre_read_off;
- lldev->evre_processed_off = evre_read_off;
- }
-
- return num_completed;
+ return 1;
}
void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
@@ -399,6 +360,16 @@ static int hidma_ll_reset(struct hidma_lldev *lldev)
*/
static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
{
+ if ((lldev->trch_state == HIDMA_CH_DISABLED) ||
+ (lldev->evch_state == HIDMA_CH_DISABLED)) {
+ dev_err(lldev->dev, "error 0x%x, already disabled...\n",
+ cause);
+
+ /* Clear out pending interrupts */
+ writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+ return;
+ }
+
if (cause & HIDMA_ERR_INT_MASK) {
dev_err(lldev->dev, "error 0x%x, disabling...\n",
cause);
@@ -430,6 +401,9 @@ static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
*/
if (hidma_handle_tre_completion(lldev, 0, 0))
break;
+ if ((lldev->trch_state == HIDMA_CH_DISABLED) ||
+ (lldev->evch_state == HIDMA_CH_DISABLED))
+ break;
}
/* We consumed TREs or there are pending TREs or EVREs. */
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 09/10] dmaengine: qcom_hidma: protect common data structures
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: linux-arm-kernel
When MSI interrupts are supported, error and the transfer interrupt can
come from multiple processor contexts.
Each error interrupt is an MSI interrupt. If the channel is disabled by
the first error interrupt, the remaining error interrupts will gracefully
return in the interrupt handler.
If an error is observed while servicing the completions in success case,
the posting of the completions will be aborted as soon as channel disabled
state is observed. The error interrupt handler will take it from there and
finish the remaining completions. We don't want to create multiple success
and error messages to be delivered to the client in mixed order.
Also got rid of hidma_post_completed method and moved the locks inside
hidma_ll_int_handler_internal function. Rearranged the assignments so that
variables are updated only when a lock is held.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma_ll.c | 142 ++++++++++++++++++--------------------------
1 file changed, 58 insertions(+), 84 deletions(-)
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index f0630e0..386a64c 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -198,18 +198,50 @@ static void hidma_ll_tre_complete(unsigned long arg)
}
}
-static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
- u8 err_info, u8 err_code)
+/*
+ * Called to handle the interrupt for the channel.
+ * Return a positive number if TRE or EVRE were consumed on this run.
+ * Return a positive number if there are pending TREs or EVREs.
+ * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
+ */
+static int hidma_handle_tre_completion(struct hidma_lldev *lldev, u8 err_info,
+ u8 err_code)
{
+ u32 *current_evre;
struct hidma_tre *tre;
unsigned long flags;
+ u32 evre_write_off;
+ u32 cfg;
+ u32 offset;
+
+ evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
+ if ((evre_write_off > lldev->evre_ring_size) ||
+ (evre_write_off % HIDMA_EVRE_SIZE)) {
+ dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
+ return -EINVAL;
+ }
spin_lock_irqsave(&lldev->lock, flags);
- tre = lldev->pending_tre_list[tre_iterator / HIDMA_TRE_SIZE];
+ if (lldev->evre_processed_off == evre_write_off) {
+ spin_unlock_irqrestore(&lldev->lock, flags);
+ return 0;
+ }
+ current_evre = lldev->evre_ring + lldev->evre_processed_off;
+ cfg = current_evre[HIDMA_EVRE_CFG_IDX];
+ if (!err_info) {
+ err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
+ err_info &= HIDMA_EVRE_ERRINFO_MASK;
+ }
+ if (!err_code)
+ err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) &
+ HIDMA_EVRE_CODE_MASK;
+
+ offset = lldev->tre_processed_off;
+ tre = lldev->pending_tre_list[offset / HIDMA_TRE_SIZE];
if (!tre) {
spin_unlock_irqrestore(&lldev->lock, flags);
dev_warn(lldev->dev, "tre_index [%d] and tre out of sync\n",
- tre_iterator / HIDMA_TRE_SIZE);
+ lldev->tre_processed_off / HIDMA_TRE_SIZE);
return -EINVAL;
}
lldev->pending_tre_list[tre->tre_index] = NULL;
@@ -223,6 +255,14 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
atomic_set(&lldev->pending_tre_count, 0);
}
+
+ HIDMA_INCREMENT_ITERATOR(lldev->tre_processed_off, HIDMA_TRE_SIZE,
+ lldev->tre_ring_size);
+ HIDMA_INCREMENT_ITERATOR(lldev->evre_processed_off, HIDMA_EVRE_SIZE,
+ lldev->evre_ring_size);
+
+ writel(lldev->evre_processed_off,
+ lldev->evca + HIDMA_EVCA_DOORBELL_REG);
spin_unlock_irqrestore(&lldev->lock, flags);
tre->err_info = err_info;
@@ -232,86 +272,7 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
kfifo_put(&lldev->handoff_fifo, tre);
tasklet_schedule(&lldev->task);
- return 0;
-}
-
-/*
- * Called to handle the interrupt for the channel.
- * Return a positive number if TRE or EVRE were consumed on this run.
- * Return a positive number if there are pending TREs or EVREs.
- * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
- */
-static int hidma_handle_tre_completion(struct hidma_lldev *lldev, u8 err_info,
- u8 err_code)
-{
- u32 evre_ring_size = lldev->evre_ring_size;
- u32 tre_ring_size = lldev->tre_ring_size;
- u32 tre_iterator, evre_iterator;
- u32 num_completed = 0;
-
- evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
- tre_iterator = lldev->tre_processed_off;
- evre_iterator = lldev->evre_processed_off;
-
- if ((evre_write_off > evre_ring_size) ||
- (evre_write_off % HIDMA_EVRE_SIZE)) {
- dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
- return 0;
- }
-
- /*
- * By the time control reaches here the number of EVREs and TREs
- * may not match. Only consume the ones that hardware told us.
- */
- while ((evre_iterator != evre_write_off)) {
- u32 *current_evre = lldev->evre_ring + evre_iterator;
- u32 cfg;
-
- cfg = current_evre[HIDMA_EVRE_CFG_IDX];
- if (!err_info) {
- err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
- err_info &= HIDMA_EVRE_ERRINFO_MASK;
- }
- if (!err_code)
- err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) &
- HIDMA_EVRE_CODE_MASK;
-
- if (hidma_post_completed(lldev, tre_iterator, err_info,
- err_code))
- break;
-
- HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
- tre_ring_size);
- HIDMA_INCREMENT_ITERATOR(evre_iterator, HIDMA_EVRE_SIZE,
- evre_ring_size);
-
- /*
- * Read the new event descriptor written by the HW.
- * As we are processing the delivered events, other events
- * get queued to the SW for processing.
- */
- evre_write_off =
- readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
- num_completed++;
- }
-
- if (num_completed) {
- u32 evre_read_off = (lldev->evre_processed_off +
- HIDMA_EVRE_SIZE * num_completed);
- u32 tre_read_off = (lldev->tre_processed_off +
- HIDMA_TRE_SIZE * num_completed);
-
- evre_read_off = evre_read_off % evre_ring_size;
- tre_read_off = tre_read_off % tre_ring_size;
-
- writel(evre_read_off, lldev->evca + HIDMA_EVCA_DOORBELL_REG);
-
- /* record the last processed tre offset */
- lldev->tre_processed_off = tre_read_off;
- lldev->evre_processed_off = evre_read_off;
- }
-
- return num_completed;
+ return 1;
}
void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
@@ -399,6 +360,16 @@ static int hidma_ll_reset(struct hidma_lldev *lldev)
*/
static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
{
+ if ((lldev->trch_state == HIDMA_CH_DISABLED) ||
+ (lldev->evch_state == HIDMA_CH_DISABLED)) {
+ dev_err(lldev->dev, "error 0x%x, already disabled...\n",
+ cause);
+
+ /* Clear out pending interrupts */
+ writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+ return;
+ }
+
if (cause & HIDMA_ERR_INT_MASK) {
dev_err(lldev->dev, "error 0x%x, disabling...\n",
cause);
@@ -430,6 +401,9 @@ static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
*/
if (hidma_handle_tre_completion(lldev, 0, 0))
break;
+ if ((lldev->trch_state == HIDMA_CH_DISABLED) ||
+ (lldev->evch_state == HIDMA_CH_DISABLED))
+ break;
}
/* We consumed TREs or there are pending TREs or EVREs. */
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH V4 09/10] dmaengine: qcom_hidma: protect common data structures
@ 2016-09-29 2:12 ` Sinan Kaya
0 siblings, 0 replies; 43+ messages in thread
From: Sinan Kaya @ 2016-09-29 2:12 UTC (permalink / raw)
To: dmaengine, timur, devicetree, cov, vinod.koul, jcm
Cc: agross, arnd, linux-arm-msm, linux-arm-kernel, Sinan Kaya,
Dan Williams, linux-kernel
When MSI interrupts are supported, error and the transfer interrupt can
come from multiple processor contexts.
Each error interrupt is an MSI interrupt. If the channel is disabled by
the first error interrupt, the remaining error interrupts will gracefully
return in the interrupt handler.
If an error is observed while servicing the completions in success case,
the posting of the completions will be aborted as soon as channel disabled
state is observed. The error interrupt handler will take it from there and
finish the remaining completions. We don't want to create multiple success
and error messages to be delivered to the client in mixed order.
Also got rid of hidma_post_completed method and moved the locks inside
hidma_ll_int_handler_internal function. Rearranged the assignments so that
variables are updated only when a lock is held.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/dma/qcom/hidma_ll.c | 142 ++++++++++++++++++--------------------------
1 file changed, 58 insertions(+), 84 deletions(-)
diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index f0630e0..386a64c 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -198,18 +198,50 @@ static void hidma_ll_tre_complete(unsigned long arg)
}
}
-static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
- u8 err_info, u8 err_code)
+/*
+ * Called to handle the interrupt for the channel.
+ * Return a positive number if TRE or EVRE were consumed on this run.
+ * Return a positive number if there are pending TREs or EVREs.
+ * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
+ */
+static int hidma_handle_tre_completion(struct hidma_lldev *lldev, u8 err_info,
+ u8 err_code)
{
+ u32 *current_evre;
struct hidma_tre *tre;
unsigned long flags;
+ u32 evre_write_off;
+ u32 cfg;
+ u32 offset;
+
+ evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
+ if ((evre_write_off > lldev->evre_ring_size) ||
+ (evre_write_off % HIDMA_EVRE_SIZE)) {
+ dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
+ return -EINVAL;
+ }
spin_lock_irqsave(&lldev->lock, flags);
- tre = lldev->pending_tre_list[tre_iterator / HIDMA_TRE_SIZE];
+ if (lldev->evre_processed_off == evre_write_off) {
+ spin_unlock_irqrestore(&lldev->lock, flags);
+ return 0;
+ }
+ current_evre = lldev->evre_ring + lldev->evre_processed_off;
+ cfg = current_evre[HIDMA_EVRE_CFG_IDX];
+ if (!err_info) {
+ err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
+ err_info &= HIDMA_EVRE_ERRINFO_MASK;
+ }
+ if (!err_code)
+ err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) &
+ HIDMA_EVRE_CODE_MASK;
+
+ offset = lldev->tre_processed_off;
+ tre = lldev->pending_tre_list[offset / HIDMA_TRE_SIZE];
if (!tre) {
spin_unlock_irqrestore(&lldev->lock, flags);
dev_warn(lldev->dev, "tre_index [%d] and tre out of sync\n",
- tre_iterator / HIDMA_TRE_SIZE);
+ lldev->tre_processed_off / HIDMA_TRE_SIZE);
return -EINVAL;
}
lldev->pending_tre_list[tre->tre_index] = NULL;
@@ -223,6 +255,14 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
atomic_set(&lldev->pending_tre_count, 0);
}
+
+ HIDMA_INCREMENT_ITERATOR(lldev->tre_processed_off, HIDMA_TRE_SIZE,
+ lldev->tre_ring_size);
+ HIDMA_INCREMENT_ITERATOR(lldev->evre_processed_off, HIDMA_EVRE_SIZE,
+ lldev->evre_ring_size);
+
+ writel(lldev->evre_processed_off,
+ lldev->evca + HIDMA_EVCA_DOORBELL_REG);
spin_unlock_irqrestore(&lldev->lock, flags);
tre->err_info = err_info;
@@ -232,86 +272,7 @@ static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
kfifo_put(&lldev->handoff_fifo, tre);
tasklet_schedule(&lldev->task);
- return 0;
-}
-
-/*
- * Called to handle the interrupt for the channel.
- * Return a positive number if TRE or EVRE were consumed on this run.
- * Return a positive number if there are pending TREs or EVREs.
- * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
- */
-static int hidma_handle_tre_completion(struct hidma_lldev *lldev, u8 err_info,
- u8 err_code)
-{
- u32 evre_ring_size = lldev->evre_ring_size;
- u32 tre_ring_size = lldev->tre_ring_size;
- u32 tre_iterator, evre_iterator;
- u32 num_completed = 0;
-
- evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
- tre_iterator = lldev->tre_processed_off;
- evre_iterator = lldev->evre_processed_off;
-
- if ((evre_write_off > evre_ring_size) ||
- (evre_write_off % HIDMA_EVRE_SIZE)) {
- dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
- return 0;
- }
-
- /*
- * By the time control reaches here the number of EVREs and TREs
- * may not match. Only consume the ones that hardware told us.
- */
- while ((evre_iterator != evre_write_off)) {
- u32 *current_evre = lldev->evre_ring + evre_iterator;
- u32 cfg;
-
- cfg = current_evre[HIDMA_EVRE_CFG_IDX];
- if (!err_info) {
- err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
- err_info &= HIDMA_EVRE_ERRINFO_MASK;
- }
- if (!err_code)
- err_code = (cfg >> HIDMA_EVRE_CODE_BIT_POS) &
- HIDMA_EVRE_CODE_MASK;
-
- if (hidma_post_completed(lldev, tre_iterator, err_info,
- err_code))
- break;
-
- HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
- tre_ring_size);
- HIDMA_INCREMENT_ITERATOR(evre_iterator, HIDMA_EVRE_SIZE,
- evre_ring_size);
-
- /*
- * Read the new event descriptor written by the HW.
- * As we are processing the delivered events, other events
- * get queued to the SW for processing.
- */
- evre_write_off =
- readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
- num_completed++;
- }
-
- if (num_completed) {
- u32 evre_read_off = (lldev->evre_processed_off +
- HIDMA_EVRE_SIZE * num_completed);
- u32 tre_read_off = (lldev->tre_processed_off +
- HIDMA_TRE_SIZE * num_completed);
-
- evre_read_off = evre_read_off % evre_ring_size;
- tre_read_off = tre_read_off % tre_ring_size;
-
- writel(evre_read_off, lldev->evca + HIDMA_EVCA_DOORBELL_REG);
-
- /* record the last processed tre offset */
- lldev->tre_processed_off = tre_read_off;
- lldev->evre_processed_off = evre_read_off;
- }
-
- return num_completed;
+ return 1;
}
void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
@@ -399,6 +360,16 @@ static int hidma_ll_reset(struct hidma_lldev *lldev)
*/
static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
{
+ if ((lldev->trch_state == HIDMA_CH_DISABLED) ||
+ (lldev->evch_state == HIDMA_CH_DISABLED)) {
+ dev_err(lldev->dev, "error 0x%x, already disabled...\n",
+ cause);
+
+ /* Clear out pending interrupts */
+ writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+ return;
+ }
+
if (cause & HIDMA_ERR_INT_MASK) {
dev_err(lldev->dev, "error 0x%x, disabling...\n",
cause);
@@ -430,6 +401,9 @@ static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
*/
if (hidma_handle_tre_completion(lldev, 0, 0))
break;
+ if ((lldev->trch_state == HIDMA_CH_DISABLED) ||
+ (lldev->evch_state == HIDMA_CH_DISABLED))
+ break;
}
/* We consumed TREs or there are pending TREs or EVREs. */
--
1.9.1
^ permalink raw reply related [flat|nested] 43+ messages in thread