* [PATCH 2/5] arm64: Add support for TI's K3 Multicore SoC architecture
From: Nishanth Menon @ 2018-06-19 19:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619194253.27288-1-nm@ti.com>
Add support for Texas Instrument's K3 Multicore SoC architecture
processors.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
Changes since RFC:
* None
RFC: https://patchwork.kernel.org/patch/10447633/
arch/arm64/Kconfig.platforms | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index d5aeac351fc3..52df25bf4f8c 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -71,6 +71,13 @@ config ARCH_EXYNOS
help
This enables support for ARMv8 based Samsung Exynos SoC family.
+config ARCH_K3
+ bool "Texas Instruments Inc. K3 multicore SoC architecture"
+ select PM_GENERIC_DOMAINS if PM
+ help
+ This enables support for Texas Instruments' K3 multicore SoC
+ architecture.
+
config ARCH_LAYERSCAPE
bool "ARMv8 based Freescale Layerscape SoC family"
select EDAC_SUPPORT
--
2.15.1
^ permalink raw reply related
* [PATCH 1/5] dt-bindings: arm: ti: Add bindings for AM654 SoC
From: Nishanth Menon @ 2018-06-19 19:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619194253.27288-1-nm@ti.com>
The AM654 SoC is a lead device of the K3 Multicore SoC architecture
platform, targeted for broad market and industrial control with aim to
meet the complex processing needs of modern embedded products.
Some highlights of this SoC are:
* Quad ARMv8 A53 cores split over two clusters
* GICv3 compliant GIC500
* Configurable L3 Cache and IO-coherent architecture
* Dual lock-step capable R5F uC for safety-critical applications
* High data throughput capable distributed DMA architecture under NAVSS
* Three Gigabit Industrial Communication Subsystems (ICSSG), each with dual
PRUs and dual RTUs
* Hardware accelerator block containing AES/DES/SHA/MD5 called SA2UL
* Centralized System Controller for Security, Power, and Resource
management.
* Dual ADCSS, eQEP/eCAP, eHRPWM, dual CAN-FD
* Flash subsystem with OSPI and Hyperbus interfaces
* Multimedia capability with CAL, DSS7-UL, SGX544, McASP
* Peripheral connectivity including USB3, PCIE, MMC/SD, GPMC, I2C, SPI,
GPIO
See AM65x Technical Reference Manual (SPRUID7, April 2018)
for further details: http://www.ti.com/lit/pdf/spruid7
Signed-off-by: Nishanth Menon <nm@ti.com>
---
Changes since RFC:
* Dropped the generic terminology for compatibles
previous RFC: https://patchwork.kernel.org/patch/10447643/
Documentation/devicetree/bindings/arm/ti/k3.txt | 23 +++++++++++++++++++++++
MAINTAINERS | 7 +++++++
2 files changed, 30 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/ti/k3.txt
diff --git a/Documentation/devicetree/bindings/arm/ti/k3.txt b/Documentation/devicetree/bindings/arm/ti/k3.txt
new file mode 100644
index 000000000000..6a059cabb2da
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/ti/k3.txt
@@ -0,0 +1,23 @@
+Texas Instruments K3 Multicore SoC architecture device tree bindings
+--------------------------------------------------------------------
+
+Platforms based on Texas Instruments K3 Multicore SoC architecture
+shall follow the following scheme:
+
+SoCs
+----
+
+Each device tree root node must specify which exact SoC in K3 Multicore SoC
+architecture it uses, using one of the following compatible values:
+
+- AM654
+ compatible = "ti,am654";
+
+Boards
+------
+
+In addition, each device tree root node must specify which one or more
+of the following board-specific compatible values:
+
+- AM654 EVM
+ compatible = "ti,am654-evm", "ti,am654";
diff --git a/MAINTAINERS b/MAINTAINERS
index 9d5eeff51b5f..fbd93eee41ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2087,6 +2087,13 @@ L: linux-kernel at vger.kernel.org
S: Maintained
F: drivers/memory/*emif*
+ARM/TEXAS INSTRUMENTS K3 ARCHITECTURE
+M: Tero Kristo <t-kristo@ti.com>
+M: Nishanth Menon <nm@ti.com>
+L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S: Supported
+F: Documentation/devicetree/bindings/arm/ti/k3.txt
+
ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
M: Santosh Shilimkar <ssantosh@kernel.org>
L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
--
2.15.1
^ permalink raw reply related
* [PATCH 0/5] arm64: Initial support Texas Instrument's AM654 Platform
From: Nishanth Menon @ 2018-06-19 19:42 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This is an update from RFC posted earlier:
https://marc.info/?l=linux-arm-kernel&m=152817866312732&w=2
The following series enables support for newest addition in TI's SoC
portfolio - AM654 SoC.
The series is based off v4.18-rc1, also available here:
https://github.com/nmenon/linux-2.6-playground/tree/upstream/v4.18-rc1/k3-1-am6-base
Key changes since RFC are indicated in respective patches:
* dt bindings updates (from review comments)
* device tree is split up to incorporate ranges and bus segments
* Cosmetic fixes including renaming the base dts to prevent confusion
* UART has been split out
Consolidated all patches (including all series) are available here:
https://github.com/nmenon/linux-2.6-playground/commits/upstream/v4.18-rc1/k3-am6-integ
Full Boot log (integrated of all series) is available here:
https://pastebin.ubuntu.com/p/bBFmnzYtCd/
NOTE: The uart series is seperated out and we get operational console only
after that series is merged.
The AM654 SoC is a lead device of the K3 Multicore SoC architecture
platform, targeted for broad market and industrial control with aim to
meet the complex processing needs of modern embedded products.
The Linux development follows closely the 66AK2G SoC model in aarch64.
See AM65x Technical Reference Manual (SPRUID7, April 2018)
for further details: http://www.ti.com/lit/pdf/spruid7
Nishanth Menon (5):
dt-bindings: arm: ti: Add bindings for AM654 SoC
arm64: Add support for TI's K3 Multicore SoC architecture
arm64: dts: ti: Add Support for AM654 SoC
soc: ti: Add Support for AM654 SoC config option
arm64: dts: ti: Add support for AM654 EVM base board
Documentation/devicetree/bindings/arm/ti/k3.txt | 23 +++++
MAINTAINERS | 9 ++
arch/arm64/Kconfig.platforms | 7 ++
arch/arm64/boot/dts/Makefile | 1 +
arch/arm64/boot/dts/ti/Makefile | 9 ++
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 31 +++++++
arch/arm64/boot/dts/ti/k3-am65.dtsi | 87 ++++++++++++++++++
arch/arm64/boot/dts/ti/k3-am654-base-board.dts | 36 ++++++++
arch/arm64/boot/dts/ti/k3-am654.dtsi | 115 ++++++++++++++++++++++++
drivers/soc/ti/Kconfig | 14 +++
10 files changed, 332 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/ti/k3.txt
create mode 100644 arch/arm64/boot/dts/ti/Makefile
create mode 100644 arch/arm64/boot/dts/ti/k3-am65-main.dtsi
create mode 100644 arch/arm64/boot/dts/ti/k3-am65.dtsi
create mode 100644 arch/arm64/boot/dts/ti/k3-am654-base-board.dts
create mode 100644 arch/arm64/boot/dts/ti/k3-am654.dtsi
--
2.15.1
^ permalink raw reply
* [PATCH 2/2] ARM: assembler: prevent ADR from setting the Thumb bit twice
From: Ard Biesheuvel @ 2018-06-19 19:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619192633.21846-1-ard.biesheuvel@linaro.org>
To work around recent issues where ADR references to Thumb function
symbols may or may not have the Thumb bit set already when they are
resolved by GAS, reference the symbol indirectly via a local symbol
typed as 'function', and emit the reference in a way that prevents
the assembler from resolving it directly. Instead, it will be fixed
up by the linker, which behaves consistently and according to spec
when it comes to relocations of symbols with function annotation
targetting wide ADR instructions.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/include/asm/assembler.h | 22 +++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 6ae42ad29518..ee2d4eb26318 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -195,13 +195,33 @@
.irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
.macro badr\c, rd, sym
#ifdef CONFIG_THUMB2_KERNEL
- adr\c \rd, \sym + 1
+ __badr \c, \rd, \sym
#else
adr\c \rd, \sym
#endif
.endm
.endr
+ /*
+ * GAS's behavior with respect to setting the Thumb bit on addresses
+ * of locally defined symbols taken using adr instructions is
+ * inconsistent, and so we are better off letting the linker handle
+ * it instead. So emit the reference as a relocation, and force a
+ * wide encoding so that we can support both forward and backward
+ * references, and avoid the R_ARM_THM_PC8 relocation that operates
+ * on the narrow encoding, which is documented as not taking the
+ * Thumb bit into account. (IHI 0044E ELF for the ARM Architecture)
+ *
+ * Note that this needs to be a separate macro or \@ does not work
+ * correctly.
+ */
+ .macro __badr, c, rd, sym
+ .set .Lsym\@, \sym
+ .type .Lsym\@, %function
+ .reloc ., R_ARM_THM_ALU_PREL_11_0, .Lsym\@
+ adr\c\().w \rd, .
+ .endm
+
/*
* Get current thread_info.
*/
--
2.17.1
^ permalink raw reply related
* [PATCH 1/2] ARM: avoid badr macro for switching to Thumb-2 mode
From: Ard Biesheuvel @ 2018-06-19 19:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619192633.21846-1-ard.biesheuvel@linaro.org>
Switching to Thumb-2 mode can be done using a single 'sub' instruction
so use that instead of the badr macro in various places in the code.
This allows us to reimplement the macro in a way that does not allow
it to be used in ARM code sequences when building a Thumb2 kernel.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/common/mcpm_head.S | 5 ++---
arch/arm/kernel/head-nommu.S | 7 +++----
arch/arm/kernel/head.S | 15 +++++++--------
arch/arm/kernel/sleep.S | 7 +++----
4 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/arch/arm/common/mcpm_head.S b/arch/arm/common/mcpm_head.S
index 08b3bb9bc6a2..4c72314e87a3 100644
--- a/arch/arm/common/mcpm_head.S
+++ b/arch/arm/common/mcpm_head.S
@@ -49,10 +49,9 @@
ENTRY(mcpm_entry_point)
ARM_BE8(setend be)
- THUMB( badr r12, 1f )
- THUMB( bx r12 )
+ THUMB( sub pc, pc, #3 )
THUMB( .thumb )
-1:
+
mrc p15, 0, r0, c0, c0, 5 @ MPIDR
ubfx r9, r0, #0, #8 @ r9 = cpu
ubfx r10, r0, #8, #8 @ r10 = cluster
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index dae8fa2f72c5..406dab0b773c 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -47,10 +47,9 @@ ENTRY(stext)
.arm
ENTRY(stext)
- THUMB( badr r9, 1f ) @ Kernel is always entered in ARM.
- THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
- THUMB( .thumb ) @ switch to Thumb now.
- THUMB(1: )
+ THUMB( sub pc, pc, #3 ) @ Kernel is always entered in ARM.
+ THUMB( .thumb ) @ If this is a Thumb-2 kernel,
+ @ switch to Thumb now.
#endif
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4b815821ec02..1e44ee9b2074 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -80,10 +80,9 @@
ENTRY(stext)
ARM_BE8(setend be ) @ ensure we are in BE8 mode
- THUMB( badr r9, 1f ) @ Kernel is always entered in ARM.
- THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
- THUMB( .thumb ) @ switch to Thumb now.
- THUMB(1: )
+ THUMB( sub pc, pc, #3 ) @ Kernel is always entered in ARM.
+ THUMB( .thumb ) @ If this is a Thumb-2 kernel,
+ @ switch to Thumb now.
#ifdef CONFIG_ARM_VIRT_EXT
bl __hyp_stub_install
@@ -363,10 +362,10 @@ __turn_mmu_on_loc:
.text
.arm
ENTRY(secondary_startup_arm)
- THUMB( badr r9, 1f ) @ Kernel is entered in ARM.
- THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
- THUMB( .thumb ) @ switch to Thumb now.
- THUMB(1: )
+ THUMB( sub pc, pc, #3 ) @ Kernel is entered in ARM.
+ THUMB( .thumb ) @ If this is a Thumb-2 kernel,
+ @ switch to Thumb now.
+
ENTRY(secondary_startup)
/*
* Common entry point for secondary CPUs.
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index a8257fc9cf2a..76b3d7c1c8d0 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -123,10 +123,9 @@ ENDPROC(cpu_resume_after_mmu)
#ifdef CONFIG_MMU
.arm
ENTRY(cpu_resume_arm)
- THUMB( badr r9, 1f ) @ Kernel is entered in ARM.
- THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
- THUMB( .thumb ) @ switch to Thumb now.
- THUMB(1: )
+ THUMB( sub pc, pc, #3 ) @ Kernel is entered in ARM.
+ THUMB( .thumb ) @ If this is a Thumb-2 kernel,
+ @ switch to Thumb now.
#endif
ENTRY(cpu_resume)
--
2.17.1
^ permalink raw reply related
* [PATCH 0/2] Make badr macro compatible with newer GAS versions
From: Ard Biesheuvel @ 2018-06-19 19:26 UTC (permalink / raw)
To: linux-arm-kernel
Work around the mindless and backward incompatible change in GAS that
prevents us from using a simple addition to set the Thumb bit in local
symbol references taken using 'adr' instructions (#2)
As a preparatory step, remove badr occurrences in ARM code sequences
contained in Thumb2 kernels.
Ard Biesheuvel (2):
ARM: avoid badr macro for switching to Thumb-2 mode
ARM: assembler: prevent ADR from setting the Thumb bit twice
arch/arm/common/mcpm_head.S | 5 ++---
arch/arm/include/asm/assembler.h | 22 +++++++++++++++++++-
arch/arm/kernel/head-nommu.S | 7 +++----
arch/arm/kernel/head.S | 15 +++++++------
arch/arm/kernel/sleep.S | 7 +++----
5 files changed, 36 insertions(+), 20 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH 04/11] input: rohm_bu21023: switch to i2c_lock_segment
From: Dmitry Torokhov @ 2018-06-19 18:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180615101506.8012-5-peda@axentia.se>
On Fri, Jun 15, 2018 at 12:14:59PM +0200, Peter Rosin wrote:
> Locking the root adapter for __i2c_transfer will deadlock if the
> device sits behind a mux-locked I2C mux. Switch to the finer-grained
> i2c_lock_segment. If the device does not sit behind a mux-locked mux,
> the two locking variants are equivalent.
>
> Signed-off-by: Peter Rosin <peda@axentia.se>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
I'm OK with it going through Wolfram's tree; I do not think I'd need an
immutable branch for this even...
> ---
> drivers/input/touchscreen/rohm_bu21023.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
> index bda0500c9b57..22d79db07234 100644
> --- a/drivers/input/touchscreen/rohm_bu21023.c
> +++ b/drivers/input/touchscreen/rohm_bu21023.c
> @@ -304,7 +304,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
> msg[1].len = len;
> msg[1].buf = buf;
>
> - i2c_lock_adapter(adap);
> + i2c_lock_segment(adap);
>
> for (i = 0; i < 2; i++) {
> if (__i2c_transfer(adap, &msg[i], 1) < 0) {
> @@ -313,7 +313,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
> }
> }
>
> - i2c_unlock_adapter(adap);
> + i2c_unlock_segment(adap);
>
> return ret;
> }
> --
> 2.11.0
>
Thanks.
--
Dmitry
^ permalink raw reply
* [RFC PATCH v2] driver core: add a debugfs entry to show deferred devices
From: Javier Martinez Canillas @ 2018-06-19 18:33 UTC (permalink / raw)
To: linux-arm-kernel
For debugging purposes it may be useful to know what are the devices whose
probe function was deferred. Add a debugfs entry showing that information.
$ cat /sys/kernel/debug/deferred_devices
48070000.i2c:twl at 48:bci
musb-hdrc.0.auto
omapdrm.0
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
Changes in v2:
- Remove unneeded ret variable from deferred_devs_show()
drivers/base/dd.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d7281c6..d95bd4636fc 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,6 +224,42 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
}
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+#include <linux/debugfs.h>
+
+static struct dentry *deferred_devices;
+
+/*
+ * deferred_devs_show() - Show the devices in the deferred probe pending list.
+ */
+static int deferred_devs_show(struct seq_file *s, void *data)
+{
+ struct device_private *curr;
+
+ mutex_lock(&deferred_probe_mutex);
+
+ list_for_each_entry(curr, &deferred_probe_pending_list, deferred_probe)
+ seq_printf(s, "%s\n", dev_name(curr->device));
+
+ mutex_unlock(&deferred_probe_mutex);
+
+ return 0;
+}
+
+static int deferred_devs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, deferred_devs_show, inode->i_private);
+}
+
+static const struct file_operations deferred_devs_fops = {
+ .owner = THIS_MODULE,
+ .open = deferred_devs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
+
/**
* deferred_probe_initcall() - Enable probing of deferred devices
*
@@ -233,6 +269,14 @@ void device_unblock_probing(void)
*/
static int deferred_probe_initcall(void)
{
+ if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+ deferred_devices = debugfs_create_file("deferred_devices",
+ 0444, NULL, NULL,
+ &deferred_devs_fops);
+ if (!deferred_devices)
+ return -ENOMEM;
+ }
+
driver_deferred_probe_enable = true;
driver_deferred_probe_trigger();
/* Sort as many dependencies as possible before exiting initcalls */
--
2.17.1
^ permalink raw reply related
* [RFC PATCH] ARM: Use logical or instead of addition for badr address calculation
From: Ard Biesheuvel @ 2018-06-19 18:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-SWaq0s46x_RCQ_TVN2vCBFp_NDmW3jUgUyMrbGoLcbA@mail.gmail.com>
On 19 June 2018 at 20:20, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 19 June 2018 at 20:17, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> On 19 June 2018 at 19:24, Guenter Roeck <linux@roeck-us.net> wrote:
>>> On Tue, Jun 19, 2018 at 03:35:07PM +0200, Ard Biesheuvel wrote:
>>>> >>
>>>> >> + /* this needs to be a separate macro or \@ does not work correctly
>>>> >> */
>>>> >> + .macro __badr, c, rd, sym
>>>> >> + .eqv .Lsym\@, \sym
>>>> >> + adr\c \rd, .Lsym\@ + 1
>>>> >
>>>> >
>>>> > Wild shot, but the following works for me.
>>>> >
>>>> > .eqv .Lsym\@, \sym + 1
>>>> > adr\c \rd, .Lsym\@
>>>> >
>>>> > Does it make sense ?
>>>> >
>>>>
>>>> Interesting. Do you mean this works with your 2.30 binutils that
>>>> triggers the original issue?
>>>>
>>>
>>> Yes, it does. It is also the solution used for some graphics libraries,
>>> though of course now I don't find the link anymore.
>>>
>>> Guess this is going nowhere given Russell's response, so I'll just
>>> live with it, like obviously everyone else does already. I built
>>> a toolchain using gcc 7.3.0 and binutils 2.28.1 which "solves"
>>> the problem for me.
>>>
>>
>> If we can live with using a wide encoding unconditionally, we could
>> consider something like below. That forces the symbol references to be
>> resolved at link time, which means we completely sidestep the new GAS
>> code.
>>
>> -----------8<----------------
>> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Date: Tue, 16 Jan 2018 12:12:45 +0000
>> Subject: [PATCH] ARM: assembler: prevent ADR from setting the Thumb bit twice
>>
>> To work around recent issues where ADR references to Thumb function
>> symbols may or may not have the Thumb bit set already when they are
>> resolved by GAS, reference the symbol indirectly via a global symbol
>> typed as 'function', and emit a relocation that lets the linker fix
>> up the reference.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>
>> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
>> index 6ae42ad29518..1a55ce4b245c 100644
>> --- a/arch/arm/include/asm/assembler.h
>> +++ b/arch/arm/include/asm/assembler.h
>> @@ -195,13 +195,22 @@
>> .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
>> .macro badr\c, rd, sym
>> #ifdef CONFIG_THUMB2_KERNEL
>> - adr\c \rd, \sym + 1
>> + __badr \c, \rd, \sym
>> #else
>> adr\c \rd, \sym
>> #endif
>> .endm
>> .endr
>>
>> + /* this needs to be a separate macro or \@ does not work correctly */
>> + .macro __badr, c, rd, sym
>> + .globl .Lsym_\sym\()_\@
>> + .type .Lsym_\sym\()_\@, %function
>> + .set .Lsym_\sym\()_\@, \sym
>> + .reloc ., R_ARM_THM_ALU_PREL_11_0, .Lsym_\sym\()_\@
>> + adr\c\().w \rd, .
>> + .endm
>> +
>> /*
>> * Get current thread_info.
>> */
>
> It seems we can drop the .globl btw
Another note: this makes the badr unusable for switching from ARM to
Thumb2 mode. I didn't spot this right away because i have this patch
https://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux.git/commit/?h=arm-badr-cleanup&id=40ac917eef965aae3146e49f7948d1db9c01e968
in my working tree. I will send it out separately if we are ok with
going ahead with this
(That means we should retain the explicit .w suffix rather than using
the W() in this macro since the new code sequence is fundamentally
Thumb2 only)
^ permalink raw reply
* [PATCH] dt-bindings: Fix unbalanced quotation marks
From: Dmitry Torokhov @ 2018-06-19 18:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180617143127.11421-1-j.neuschaefer@gmx.net>
On Sun, Jun 17, 2018 at 04:31:18PM +0200, Jonathan Neusch?fer wrote:
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/hideep.txt b/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
> index 121d9b7c79a2..1063c30d53f7 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
> +++ b/Documentation/devicetree/bindings/input/touchscreen/hideep.txt
> @@ -32,7 +32,7 @@ i2c at 00000000 {
> reg = <0x6c>;
> interrupt-parent = <&gpx1>;
> interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
> - vdd-supply = <&ldo15_reg>";
> + vdd-supply = <&ldo15_reg>;
> vid-supply = <&ldo18_reg>;
> reset-gpios = <&gpx1 5 0>;
> touchscreen-size-x = <1080>;
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
--
Dmitry
^ permalink raw reply
* [RFC PATCH] driver core: add a debugfs entry to show deferred devices
From: Javier Martinez Canillas @ 2018-06-19 18:20 UTC (permalink / raw)
To: linux-arm-kernel
For debugging purposes it may be useful to know what are the devices whose
probe function was deferred. Add a debugfs entry showing that information.
$ cat /sys/kernel/debug/deferred_devices
48070000.i2c:twl at 48:bci
musb-hdrc.0.auto
omapdrm.0
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
drivers/base/dd.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1435d7281c6..98a3ab4a852 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -224,6 +224,43 @@ void device_unblock_probing(void)
driver_deferred_probe_trigger();
}
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+#include <linux/debugfs.h>
+
+static struct dentry *deferred_devices;
+
+/*
+ * deferred_devs_show() - Show the devices in the deferred probe pending list.
+ */
+static int deferred_devs_show(struct seq_file *s, void *data)
+{
+ struct device_private *curr;
+ int ret = 0;
+
+ mutex_lock(&deferred_probe_mutex);
+
+ list_for_each_entry(curr, &deferred_probe_pending_list, deferred_probe)
+ seq_printf(s, "%s\n", dev_name(curr->device));
+
+ mutex_unlock(&deferred_probe_mutex);
+
+ return ret;
+}
+
+static int deferred_devs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, deferred_devs_show, inode->i_private);
+}
+
+static const struct file_operations deferred_devs_fops = {
+ .owner = THIS_MODULE,
+ .open = deferred_devs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
+
/**
* deferred_probe_initcall() - Enable probing of deferred devices
*
@@ -233,6 +270,14 @@ void device_unblock_probing(void)
*/
static int deferred_probe_initcall(void)
{
+ if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+ deferred_devices = debugfs_create_file("deferred_devices",
+ 0444, NULL, NULL,
+ &deferred_devs_fops);
+ if (!deferred_devices)
+ return -ENOMEM;
+ }
+
driver_deferred_probe_enable = true;
driver_deferred_probe_trigger();
/* Sort as many dependencies as possible before exiting initcalls */
--
2.17.1
^ permalink raw reply related
* [RFC PATCH] ARM: Use logical or instead of addition for badr address calculation
From: Ard Biesheuvel @ 2018-06-19 18:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9JTsKEwwKN4OjmNHLf_86s753f2yEdo=7esERdUCaWiQ@mail.gmail.com>
On 19 June 2018 at 20:17, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 19 June 2018 at 19:24, Guenter Roeck <linux@roeck-us.net> wrote:
>> On Tue, Jun 19, 2018 at 03:35:07PM +0200, Ard Biesheuvel wrote:
>>> >>
>>> >> + /* this needs to be a separate macro or \@ does not work correctly
>>> >> */
>>> >> + .macro __badr, c, rd, sym
>>> >> + .eqv .Lsym\@, \sym
>>> >> + adr\c \rd, .Lsym\@ + 1
>>> >
>>> >
>>> > Wild shot, but the following works for me.
>>> >
>>> > .eqv .Lsym\@, \sym + 1
>>> > adr\c \rd, .Lsym\@
>>> >
>>> > Does it make sense ?
>>> >
>>>
>>> Interesting. Do you mean this works with your 2.30 binutils that
>>> triggers the original issue?
>>>
>>
>> Yes, it does. It is also the solution used for some graphics libraries,
>> though of course now I don't find the link anymore.
>>
>> Guess this is going nowhere given Russell's response, so I'll just
>> live with it, like obviously everyone else does already. I built
>> a toolchain using gcc 7.3.0 and binutils 2.28.1 which "solves"
>> the problem for me.
>>
>
> If we can live with using a wide encoding unconditionally, we could
> consider something like below. That forces the symbol references to be
> resolved at link time, which means we completely sidestep the new GAS
> code.
>
> -----------8<----------------
> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Date: Tue, 16 Jan 2018 12:12:45 +0000
> Subject: [PATCH] ARM: assembler: prevent ADR from setting the Thumb bit twice
>
> To work around recent issues where ADR references to Thumb function
> symbols may or may not have the Thumb bit set already when they are
> resolved by GAS, reference the symbol indirectly via a global symbol
> typed as 'function', and emit a relocation that lets the linker fix
> up the reference.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index 6ae42ad29518..1a55ce4b245c 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -195,13 +195,22 @@
> .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
> .macro badr\c, rd, sym
> #ifdef CONFIG_THUMB2_KERNEL
> - adr\c \rd, \sym + 1
> + __badr \c, \rd, \sym
> #else
> adr\c \rd, \sym
> #endif
> .endm
> .endr
>
> + /* this needs to be a separate macro or \@ does not work correctly */
> + .macro __badr, c, rd, sym
> + .globl .Lsym_\sym\()_\@
> + .type .Lsym_\sym\()_\@, %function
> + .set .Lsym_\sym\()_\@, \sym
> + .reloc ., R_ARM_THM_ALU_PREL_11_0, .Lsym_\sym\()_\@
> + adr\c\().w \rd, .
> + .endm
> +
> /*
> * Get current thread_info.
> */
It seems we can drop the .globl btw
^ permalink raw reply
* [PATCH v1 0/6] perf cs-etm: Fix tracing packet handling and minor refactoring
From: Arnaldo Carvalho de Melo @ 2018-06-19 18:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANLsYkyxuz+tPrC7wb1omsw+qj=7ZB5t6FRbqZz54994g62q6g@mail.gmail.com>
Em Tue, Jun 19, 2018 at 11:46:02AM -0600, Mathieu Poirier escreveu:
> On Sun, 17 Jun 2018 at 23:10, Leo Yan <leo.yan@linaro.org> wrote:
> >
> > Due the current code is missing to handle cs-etm start tracing packet
> > and CS_ETM_TRACE_ON packet, we fail to generate branch sample for them.
> >
> > This patch series is to fix cs-etm tracing packet handling:
> >
> > Patch 0001 is to add invalid address macro for readable coding;
> >
> > Patch 0002 is one minor fixing to return error code for instruction
> > sample failure;
> >
> > Patches 0003~0006 are fixing patches for start tracing packet
> > and CS_ETM_TRACE_ON packet.
> >
> > This patch series is applied on acme tree [1] on branch perf/core with
> > latest commit: e238cf2e3d2e ("perf intel-pt: Fix packet decoding of CYC
> > packets"). Also applied successfully this patch series on Linus tree
> > on 4.18-rc1.
> >
> > This patch series has been verified on Hikey620 platform with below two
> > commands:
> > perf script --itrace=i10000il128 -F cpu,event,ip,addr,sym -k ./vmlinux
> > perf script -F cpu,event,ip,addr,sym -k ./vmlinux
> >
> > [1] https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git
> >
> >
> > Leo Yan (6):
> > perf cs-etm: Introduce invalid address macro
> > perf cs-etm: Bail out immediately for instruction sample failure
> > perf cs-etm: Fix start tracing packet handling
> > perf cs-etm: Support dummy address value for CS_ETM_TRACE_ON packet
> > perf cs-etm: Generate branch sample when receiving a CS_ETM_TRACE_ON
> > packet
> > perf cs-etm: Generate branch sample for CS_ETM_TRACE_ON packet
> >
> > tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 10 ++--
> > tools/perf/util/cs-etm-decoder/cs-etm-decoder.h | 1 +
> > tools/perf/util/cs-etm.c | 71 +++++++++++++++++++++----
> > 3 files changed, 68 insertions(+), 14 deletions(-)
>
> Good day Arnaldo,
>
> I am good with this set:
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
> Please consider for inclusion in your tree if you are satisfied with the work.
I'll take a look and get it into perf/core, now I'm concentrating on
perf/urgent work.
Thanks,
- Arnaldo
^ permalink raw reply
* [RFC PATCH] ARM: Use logical or instead of addition for badr address calculation
From: Ard Biesheuvel @ 2018-06-19 18:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619172422.GB16846@roeck-us.net>
On 19 June 2018 at 19:24, Guenter Roeck <linux@roeck-us.net> wrote:
> On Tue, Jun 19, 2018 at 03:35:07PM +0200, Ard Biesheuvel wrote:
>> >>
>> >> + /* this needs to be a separate macro or \@ does not work correctly
>> >> */
>> >> + .macro __badr, c, rd, sym
>> >> + .eqv .Lsym\@, \sym
>> >> + adr\c \rd, .Lsym\@ + 1
>> >
>> >
>> > Wild shot, but the following works for me.
>> >
>> > .eqv .Lsym\@, \sym + 1
>> > adr\c \rd, .Lsym\@
>> >
>> > Does it make sense ?
>> >
>>
>> Interesting. Do you mean this works with your 2.30 binutils that
>> triggers the original issue?
>>
>
> Yes, it does. It is also the solution used for some graphics libraries,
> though of course now I don't find the link anymore.
>
> Guess this is going nowhere given Russell's response, so I'll just
> live with it, like obviously everyone else does already. I built
> a toolchain using gcc 7.3.0 and binutils 2.28.1 which "solves"
> the problem for me.
>
If we can live with using a wide encoding unconditionally, we could
consider something like below. That forces the symbol references to be
resolved at link time, which means we completely sidestep the new GAS
code.
-----------8<----------------
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Date: Tue, 16 Jan 2018 12:12:45 +0000
Subject: [PATCH] ARM: assembler: prevent ADR from setting the Thumb bit twice
To work around recent issues where ADR references to Thumb function
symbols may or may not have the Thumb bit set already when they are
resolved by GAS, reference the symbol indirectly via a global symbol
typed as 'function', and emit a relocation that lets the linker fix
up the reference.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 6ae42ad29518..1a55ce4b245c 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -195,13 +195,22 @@
.irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
.macro badr\c, rd, sym
#ifdef CONFIG_THUMB2_KERNEL
- adr\c \rd, \sym + 1
+ __badr \c, \rd, \sym
#else
adr\c \rd, \sym
#endif
.endm
.endr
+ /* this needs to be a separate macro or \@ does not work correctly */
+ .macro __badr, c, rd, sym
+ .globl .Lsym_\sym\()_\@
+ .type .Lsym_\sym\()_\@, %function
+ .set .Lsym_\sym\()_\@, \sym
+ .reloc ., R_ARM_THM_ALU_PREL_11_0, .Lsym_\sym\()_\@
+ adr\c\().w \rd, .
+ .endm
+
/*
* Get current thread_info.
*/
^ permalink raw reply related
* [RFC PATCH] ARM: Use logical or instead of addition for badr address calculation
From: Russell King - ARM Linux @ 2018-06-19 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619171424.GA16846@roeck-us.net>
On Tue, Jun 19, 2018 at 10:14:24AM -0700, Guenter Roeck wrote:
> On Tue, Jun 19, 2018 at 04:12:35PM +0100, Russell King - ARM Linux wrote:
> >
> > So, I'm going to continue sitting on the fence on this, and basically
> > take the attitude that it's better that people don't use the new
> > binutils until binutils people can provide us with an officially
> > sanctioned solution that's going to work for both older and future
> > assemblers.
> >
> I would so much love if people were working together instead of against
> each other :-(. Never mind, I'll try a toolchain with binutils 2.28.1.
> At least that is still supported with buildroot.
You could say that about the toolchain people who decided to change
the behaviour in this area that has existed before July 2009, and
broke multiple software packages in the process.
What I don't want to do is to change it in some way that breaks
existing setups, or that ends up breaking again in the future. This
is why I want input _from the toolchain people_ before we try to fix
the problem.
That isn't "against each other" - it's a request _for_ toolchain
people to be involved in this.
The fact that this thread doesn't involve any toolchain people says
a lot about the "working together" aspect. So, please don't try and
lump this on me being "un-cooperative".
What I'm saying is talk to the toolchain people and find a solution
in conjunction _with_ them that we can be sure will work, rather
than guessing at some obscure undocumented method that could end up
breaking again.
Remember, _you_ have the problem, _I_ don't. It's not for me to go
off and talk to the toolchain people on your behalf.
Thanks.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH v1 0/6] perf cs-etm: Fix tracing packet handling and minor refactoring
From: Mathieu Poirier @ 2018-06-19 17:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>
On Sun, 17 Jun 2018 at 23:10, Leo Yan <leo.yan@linaro.org> wrote:
>
> Due the current code is missing to handle cs-etm start tracing packet
> and CS_ETM_TRACE_ON packet, we fail to generate branch sample for them.
>
> This patch series is to fix cs-etm tracing packet handling:
>
> Patch 0001 is to add invalid address macro for readable coding;
>
> Patch 0002 is one minor fixing to return error code for instruction
> sample failure;
>
> Patches 0003~0006 are fixing patches for start tracing packet
> and CS_ETM_TRACE_ON packet.
>
> This patch series is applied on acme tree [1] on branch perf/core with
> latest commit: e238cf2e3d2e ("perf intel-pt: Fix packet decoding of CYC
> packets"). Also applied successfully this patch series on Linus tree
> on 4.18-rc1.
>
> This patch series has been verified on Hikey620 platform with below two
> commands:
> perf script --itrace=i10000il128 -F cpu,event,ip,addr,sym -k ./vmlinux
> perf script -F cpu,event,ip,addr,sym -k ./vmlinux
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git
>
>
> Leo Yan (6):
> perf cs-etm: Introduce invalid address macro
> perf cs-etm: Bail out immediately for instruction sample failure
> perf cs-etm: Fix start tracing packet handling
> perf cs-etm: Support dummy address value for CS_ETM_TRACE_ON packet
> perf cs-etm: Generate branch sample when receiving a CS_ETM_TRACE_ON
> packet
> perf cs-etm: Generate branch sample for CS_ETM_TRACE_ON packet
>
> tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 10 ++--
> tools/perf/util/cs-etm-decoder/cs-etm-decoder.h | 1 +
> tools/perf/util/cs-etm.c | 71 +++++++++++++++++++++----
> 3 files changed, 68 insertions(+), 14 deletions(-)
Good day Arnaldo,
I am good with this set:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Please consider for inclusion in your tree if you are satisfied with the work.
Regards,
Mathieu
>
> --
> 2.7.4
>
^ permalink raw reply
* [RFC PATCH] ARM: Use logical or instead of addition for badr address calculation
From: Guenter Roeck @ 2018-06-19 17:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-T8Fx3Nry7pUdOoOeRU-Ns89w3oo4itmu1q4FzYF5Rag@mail.gmail.com>
On Tue, Jun 19, 2018 at 03:35:07PM +0200, Ard Biesheuvel wrote:
> >>
> >> + /* this needs to be a separate macro or \@ does not work correctly
> >> */
> >> + .macro __badr, c, rd, sym
> >> + .eqv .Lsym\@, \sym
> >> + adr\c \rd, .Lsym\@ + 1
> >
> >
> > Wild shot, but the following works for me.
> >
> > .eqv .Lsym\@, \sym + 1
> > adr\c \rd, .Lsym\@
> >
> > Does it make sense ?
> >
>
> Interesting. Do you mean this works with your 2.30 binutils that
> triggers the original issue?
>
Yes, it does. It is also the solution used for some graphics libraries,
though of course now I don't find the link anymore.
Guess this is going nowhere given Russell's response, so I'll just
live with it, like obviously everyone else does already. I built
a toolchain using gcc 7.3.0 and binutils 2.28.1 which "solves"
the problem for me.
Guenter
^ permalink raw reply
* [PATCH] ARM: shmobile: rcar-gen2: Stop compiling headsmp-apmu on !SMP
From: Geert Uytterhoeven @ 2018-06-19 17:20 UTC (permalink / raw)
To: linux-arm-kernel
As of commit cad160ed0a94927e ("ARM: shmobile: Convert file to use
cntvoff"), there's no non-SMP code left in headsmp-apmu.S.
Hence build the file for SMP only, and drop the no longer needed check
for CONFIG_SMP inside the file.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
arch/arm/mach-shmobile/Makefile | 2 +-
arch/arm/mach-shmobile/headsmp-apmu.S | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 05ba728ed4f67cf2..b33dc59d8698d218 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -21,13 +21,13 @@ cpu-y := platsmp.o headsmp.o
# Shared SoC family objects
obj-$(CONFIG_ARCH_RCAR_GEN2) += setup-rcar-gen2.o platsmp-apmu.o $(cpu-y)
CFLAGS_setup-rcar-gen2.o += -march=armv7-a
-obj-$(CONFIG_ARCH_RCAR_GEN2) += headsmp-apmu.o
obj-$(CONFIG_ARCH_R8A7790) += regulator-quirk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7791) += regulator-quirk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7793) += regulator-quirk-rcar-gen2.o
# SMP objects
smp-y := $(cpu-y)
+smp-$(CONFIG_ARCH_RCAR_GEN2) += headsmp-apmu.o
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
diff --git a/arch/arm/mach-shmobile/headsmp-apmu.S b/arch/arm/mach-shmobile/headsmp-apmu.S
index a7b4bc7a087bdca1..fabe9cadd12ef0b1 100644
--- a/arch/arm/mach-shmobile/headsmp-apmu.S
+++ b/arch/arm/mach-shmobile/headsmp-apmu.S
@@ -8,9 +8,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
-#ifdef CONFIG_SMP
ENTRY(shmobile_boot_apmu)
bl secure_cntvoff_init
b secondary_startup
ENDPROC(shmobile_boot_apmu)
-#endif
--
2.17.1
^ permalink raw reply related
* [RFC PATCH] ARM: Use logical or instead of addition for badr address calculation
From: Guenter Roeck @ 2018-06-19 17:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619151235.GH17671@n2100.armlinux.org.uk>
On Tue, Jun 19, 2018 at 04:12:35PM +0100, Russell King - ARM Linux wrote:
>
> So, I'm going to continue sitting on the fence on this, and basically
> take the attitude that it's better that people don't use the new
> binutils until binutils people can provide us with an officially
> sanctioned solution that's going to work for both older and future
> assemblers.
>
I would so much love if people were working together instead of against
each other :-(. Never mind, I'll try a toolchain with binutils 2.28.1.
At least that is still supported with buildroot.
Guenter
^ permalink raw reply
* [PATCH v5 7/7] dmaengine: imx-sdma: alloclate bd memory from dma pool
From: Robin Gong @ 2018-06-19 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>
dma_terminate_all maybe called in interrupt context which means
WARN_ON() will be triggered as below when bd memory freed. Allocat
bd memory from dma pool instead.
[ 29.161079] WARNING: CPU: 1 PID: 533 at ./include/linux/dma-mapping.h:541 sdma_free_bd+0xa4/0xb4
[ 29.169883] Modules linked in:
[ 29.172990] CPU: 1 PID: 533 Comm: mpegaudioparse0 Not tainted 4.18.0-rc1-next-20180618-00009-gf79f22c #20
[ 29.182597] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[ 29.189163] Backtrace:
[ 29.191685] [<c010d1e0>] (dump_backtrace) from [<c010d4a0>] (show_stack+0x18/0x1c)
[ 29.199306] r7:00000000 r6:600f0093 r5:00000000 r4:c107db7c
[ 29.205029] [<c010d488>] (show_stack) from [<c0a5bba0>] (dump_stack+0xb4/0xe8)
[ 29.212312] [<c0a5baec>] (dump_stack) from [<c012703c>] (__warn+0x104/0x130)
[ 29.219411] r9:ec3e817c r8:0000021d r7:00000009 r6:c0d1d440 r5:00000000 r4:00000000
[ 29.227204] [<c0126f38>] (__warn) from [<c0127180>] (warn_slowpath_null+0x44/0x50)
[ 29.234821] r8:ed129dc4 r7:c0b01978 r6:c04d4e90 r5:0000021d r4:c0d1d440
[ 29.241574] [<c012713c>] (warn_slowpath_null) from [<c04d4e90>] (sdma_free_bd+0xa4/0xb4)
[ 29.249706] r6:4c001000 r5:f082e000 r4:00000024
[ 29.254376] [<c04d4dec>] (sdma_free_bd) from [<c04d4eb4>] (sdma_desc_free+0x14/0x20)
[ 29.262163] r7:ec3e8110 r6:00000100 r5:00000200 r4:ecf89a00
[ 29.267873] [<c04d4ea0>] (sdma_desc_free) from [<c04d229c>] (vchan_dma_desc_free_list+0xa4/0xac)
[ 29.276697] r5:00000200 r4:ed129d9c
[ 29.280326] [<c04d21f8>] (vchan_dma_desc_free_list) from [<c04d482c>] (sdma_disable_channel_with_delay+0x14c/0x188)
[ 29.290808] r9:ecae560c r8:ec3e815c r7:00000000 r6:c1008908 r5:ed129dc4 r4:ec3e8110
[ 29.298605] [<c04d46e0>] (sdma_disable_channel_with_delay) from [<c07c5c84>] (snd_dmaengine_pcm_trigger+0x90/0x1b0)
[ 29.309087] r8:ecae5000 r7:ec940800 r6:ed31bd80 r5:ecadb200 r4:ec26a700
[ 29.315855] [<c07c5bf4>] (snd_dmaengine_pcm_trigger) from [<c07dd800>] (soc_pcm_trigger+0xb4/0x130)
[ 29.324953] r8:ecae5000 r7:ec940800 r6:00000000 r5:ecadb200 r4:ec26a700
[ 29.331716] [<c07dd74c>] (soc_pcm_trigger) from [<c07bc008>] (snd_pcm_do_stop+0x58/0x5c)
[ 29.339859] r9:ecaed5a8 r8:ed31bdc0 r7:00000000 r6:00000001 r5:ecadb200 r4:c0b9c4d0
[ 29.347652] [<c07bbfb0>] (snd_pcm_do_stop) from [<c07bbde8>] (snd_pcm_action_single+0x40/0x80)
[ 29.356315] [<c07bbda8>] (snd_pcm_action_single) from [<c07bbf1c>] (snd_pcm_action+0xf4/0xfc)
[ 29.364883] r7:00000001 r6:c0b9c4d0 r5:ecadb2d4 r4:ecadb200
[ 29.370593] [<c07bbe28>] (snd_pcm_action) from [<c07bc8dc>] (snd_pcm_drop+0x58/0x9c)
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/imx-sdma.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f8becaf..7dab7e9 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
@@ -343,6 +344,7 @@ struct sdma_channel {
u32 shp_addr, per_addr;
enum dma_status status;
struct imx_dma_data data;
+ struct dma_pool *bd_pool;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -1153,11 +1155,10 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
static int sdma_alloc_bd(struct sdma_desc *desc)
{
- u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
int ret = 0;
- desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
- GFP_ATOMIC);
+ desc->bd = dma_pool_alloc(desc->sdmac->bd_pool, GFP_ATOMIC,
+ &desc->bd_phys);
if (!desc->bd) {
ret = -ENOMEM;
goto out;
@@ -1168,9 +1169,7 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
static void sdma_free_bd(struct sdma_desc *desc)
{
- u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
-
- dma_free_coherent(NULL, bd_size, desc->bd, desc->bd_phys);
+ dma_pool_free(desc->sdmac->bd_pool, desc->bd, desc->bd_phys);
}
static void sdma_desc_free(struct virt_dma_desc *vd)
@@ -1218,6 +1217,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto disable_clk_ahb;
+ sdmac->bd_pool = dma_pool_create("bd_pool", chan->device->dev,
+ sizeof(struct sdma_buffer_descriptor),
+ 32, 0);
+
return 0;
disable_clk_ahb:
@@ -1246,6 +1249,9 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
+
+ dma_pool_destroy(sdmac->bd_pool);
+ sdmac->bd_pool = NULL;
}
static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
--
2.7.4
^ permalink raw reply related
* [PATCH v5 6/7] dmaengine: imx-sdma: add sdma_transfer_init to decrease code overlap
From: Robin Gong @ 2018-06-19 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>
There are lot of codes overlap between prep_sg and prep_cyclic function.
Add sdma_transfer_init() function to elimated the code overlap.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/imx-sdma.c | 83 ++++++++++++++++++++++----------------------------
1 file changed, 37 insertions(+), 46 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 9f1a462..f8becaf 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1248,6 +1248,40 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
clk_disable(sdma->clk_ahb);
}
+static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
+ enum dma_transfer_direction direction, u32 bds)
+{
+ struct sdma_desc *desc;
+
+ desc = kzalloc((sizeof(*desc)), GFP_NOWAIT);
+ if (!desc)
+ goto err_out;
+
+ sdmac->status = DMA_IN_PROGRESS;
+ sdmac->direction = direction;
+ sdmac->flags = 0;
+
+ desc->chn_count = 0;
+ desc->chn_real_count = 0;
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->sdmac = sdmac;
+ desc->num_bd = bds;
+
+ if (sdma_alloc_bd(desc))
+ goto err_desc_out;
+
+ if (sdma_load_context(sdmac))
+ goto err_desc_out;
+
+ return desc;
+
+err_desc_out:
+ kfree(desc);
+err_out:
+ return NULL;
+}
+
static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
@@ -1260,36 +1294,13 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
struct scatterlist *sg;
struct sdma_desc *desc;
- if (sdmac->status == DMA_IN_PROGRESS)
- return NULL;
- sdmac->status = DMA_IN_PROGRESS;
-
- sdmac->flags = 0;
-
- desc = kzalloc((sizeof(*desc)), GFP_NOWAIT);
+ desc = sdma_transfer_init(sdmac, direction, sg_len);
if (!desc)
goto err_out;
- desc->buf_tail = 0;
- desc->buf_ptail = 0;
- desc->sdmac = sdmac;
- desc->num_bd = sg_len;
- desc->chn_real_count = 0;
-
- if (sdma_alloc_bd(desc)) {
- kfree(desc);
- goto err_out;
- }
-
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
sg_len, channel);
- sdmac->direction = direction;
- ret = sdma_load_context(sdmac);
- if (ret)
- goto err_bd_out;
-
- desc->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) {
struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
@@ -1365,38 +1376,18 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
struct sdma_engine *sdma = sdmac->sdma;
int num_periods = buf_len / period_len;
int channel = sdmac->channel;
- int ret, i = 0, buf = 0;
+ int i = 0, buf = 0;
struct sdma_desc *desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
- if (sdmac->status == DMA_IN_PROGRESS)
- return NULL;
-
- sdmac->status = DMA_IN_PROGRESS;
-
- desc = kzalloc((sizeof(*desc)), GFP_NOWAIT);
+ desc = sdma_transfer_init(sdmac, direction, num_periods);
if (!desc)
goto err_out;
- desc->buf_tail = 0;
- desc->buf_ptail = 0;
- desc->sdmac = sdmac;
- desc->num_bd = num_periods;
- desc->chn_real_count = 0;
desc->period_len = period_len;
sdmac->flags |= IMX_DMA_SG_LOOP;
- sdmac->direction = direction;
-
- if (sdma_alloc_bd(desc)) {
- kfree(desc);
- goto err_bd_out;
- }
-
- ret = sdma_load_context(sdmac);
- if (ret)
- goto err_bd_out;
if (period_len > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
--
2.7.4
^ permalink raw reply related
* [PATCH v5 5/7] dmaengine: imx-sdma: remove the maximum limitation for bd numbers
From: Robin Gong @ 2018-06-19 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>
No this limitation now after virtual dma used since bd is allocated
dynamically instead of static.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/imx-sdma.c | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d1d3494..9f1a462 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -285,7 +285,6 @@ struct sdma_context_data {
u32 scratch7;
} __attribute__ ((packed));
-#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
struct sdma_engine;
@@ -1290,13 +1289,6 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
if (ret)
goto err_bd_out;
- if (sg_len > NUM_BD) {
- dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
- channel, sg_len, NUM_BD);
- ret = -EINVAL;
- goto err_bd_out;
- }
-
desc->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) {
struct sdma_buffer_descriptor *bd = &desc->bd[i];
@@ -1406,12 +1398,6 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
if (ret)
goto err_bd_out;
- if (num_periods > NUM_BD) {
- dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
- channel, num_periods, NUM_BD);
- goto err_bd_out;
- }
-
if (period_len > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
channel, period_len, 0xffff);
--
2.7.4
^ permalink raw reply related
* [PATCH v5 4/7] dmaengine: imx-sdma: remove useless 'lock' and 'enabled' in 'struct sdma_channel'
From: Robin Gong @ 2018-06-19 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>
Since 'sdmac->vc.lock' and 'sdmac->desc' can be used as 'lock' and
'enabled' in 'struct sdma_channel sdmac', remove them.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/imx-sdma.c | 23 -----------------------
1 file changed, 23 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 86fa799..d1d3494 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -342,10 +342,8 @@ struct sdma_channel {
unsigned long event_mask[2];
unsigned long watermark_level;
u32 shp_addr, per_addr;
- spinlock_t lock;
enum dma_status status;
struct imx_dma_data data;
- bool enabled;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -606,14 +604,7 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
{
- unsigned long flags;
- struct sdma_channel *sdmac = &sdma->channel[channel];
-
writel(BIT(channel), sdma->regs + SDMA_H_START);
-
- spin_lock_irqsave(&sdmac->lock, flags);
- sdmac->enabled = true;
- spin_unlock_irqrestore(&sdmac->lock, flags);
}
/*
@@ -731,14 +722,6 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
struct sdma_buffer_descriptor *bd;
int error = 0;
enum dma_status old_status = sdmac->status;
- unsigned long flags;
-
- spin_lock_irqsave(&sdmac->lock, flags);
- if (!sdmac->enabled) {
- spin_unlock_irqrestore(&sdmac->lock, flags);
- return;
- }
- spin_unlock_irqrestore(&sdmac->lock, flags);
/*
* loop mode. Iterate over descriptors, re-setup them and
@@ -1000,15 +983,10 @@ static int sdma_disable_channel(struct dma_chan *chan)
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
- unsigned long flags;
writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
sdmac->status = DMA_ERROR;
- spin_lock_irqsave(&sdmac->lock, flags);
- sdmac->enabled = false;
- spin_unlock_irqrestore(&sdmac->lock, flags);
-
return 0;
}
@@ -1922,7 +1900,6 @@ static int sdma_probe(struct platform_device *pdev)
struct sdma_channel *sdmac = &sdma->channel[i];
sdmac->sdma = sdma;
- spin_lock_init(&sdmac->lock);
sdmac->channel = i;
sdmac->vc.desc_free = sdma_desc_free;
--
2.7.4
^ permalink raw reply related
* [PATCH v5 3/7] dmaengine: imx-sdma: add virt-dma support
From: Robin Gong @ 2018-06-19 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>
The legacy sdma driver has below limitations or drawbacks:
1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
one page size for one channel regardless of only few BDs needed
most time. But in few cases, the max PAGE_SIZE maybe not enough.
2. One SDMA channel can't stop immediatley once channel disabled which
means SDMA interrupt may come in after this channel terminated.There
are some patches for this corner case such as commit "2746e2c389f9",
but not cover non-cyclic.
The common virt-dma overcomes the above limitations. It can alloc bd
dynamically and free bd once this tx transfer done. No memory wasted or
maximum limititation here, only depends on how many memory can be requested
from kernel. For No.2, such issue can be workaround by checking if there
is available descript("sdmac->desc") now once the unwanted interrupt
coming. At last the common virt-dma is easier for sdma driver maintain.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/Kconfig | 1 +
drivers/dma/imx-sdma.c | 263 ++++++++++++++++++++++++++++++++-----------------
2 files changed, 171 insertions(+), 93 deletions(-)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index ca1680a..d4a4230 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -250,6 +250,7 @@ config IMX_SDMA
tristate "i.MX SDMA support"
depends on ARCH_MXC
select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
help
Support the i.MX SDMA engine. This engine is integrated into
Freescale i.MX25/31/35/51/53/6 chips.
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 19c351f..86fa799 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -41,6 +41,7 @@
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include "dmaengine.h"
+#include "virt-dma.h"
/* SDMA registers */
#define SDMA_H_C0PTR 0x000
@@ -301,6 +302,7 @@ struct sdma_engine;
* @bd pointer of alloced bd
*/
struct sdma_desc {
+ struct virt_dma_desc vd;
unsigned int num_bd;
dma_addr_t bd_phys;
unsigned int buf_tail;
@@ -324,8 +326,8 @@ struct sdma_desc {
* @word_size peripheral access size
*/
struct sdma_channel {
+ struct virt_dma_chan vc;
struct sdma_desc *desc;
- struct sdma_desc _desc;
struct sdma_engine *sdma;
unsigned int channel;
enum dma_transfer_direction direction;
@@ -340,11 +342,8 @@ struct sdma_channel {
unsigned long event_mask[2];
unsigned long watermark_level;
u32 shp_addr, per_addr;
- struct dma_chan chan;
spinlock_t lock;
- struct dma_async_tx_descriptor txdesc;
enum dma_status status;
- struct tasklet_struct tasklet;
struct imx_dma_data data;
bool enabled;
};
@@ -698,6 +697,35 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
writel_relaxed(val, sdma->regs + chnenbl);
}
+static struct sdma_desc *to_sdma_desc(struct dma_async_tx_descriptor *t)
+{
+ return container_of(t, struct sdma_desc, vd.tx);
+}
+
+static void sdma_start_desc(struct sdma_channel *sdmac)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&sdmac->vc);
+ struct sdma_desc *desc;
+ struct sdma_engine *sdma = sdmac->sdma;
+ int channel = sdmac->channel;
+
+ if (!vd) {
+ sdmac->desc = NULL;
+ return;
+ }
+ sdmac->desc = desc = to_sdma_desc(&vd->tx);
+ /*
+ * Do not delete the node in desc_issued list in cyclic mode, otherwise
+ * the desc alloced will never be freed in vchan_dma_desc_free_list
+ */
+ if (!(sdmac->flags & IMX_DMA_SG_LOOP))
+ list_del(&vd->node);
+
+ sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
+ sdma_enable_channel(sdma, sdmac->channel);
+}
+
static void sdma_update_channel_loop(struct sdma_channel *sdmac)
{
struct sdma_buffer_descriptor *bd;
@@ -716,7 +744,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* loop mode. Iterate over descriptors, re-setup them and
* call callback function.
*/
- while (1) {
+ while (sdmac->desc) {
struct sdma_desc *desc = sdmac->desc;
bd = &desc->bd[desc->buf_tail];
@@ -747,15 +775,16 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* SDMA transaction status by the time the client tasklet is
* executed.
*/
-
- dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
+ spin_unlock(&sdmac->vc.lock);
+ dmaengine_desc_get_callback_invoke(&desc->vd.tx, NULL);
+ spin_lock(&sdmac->vc.lock);
if (error)
sdmac->status = old_status;
}
}
-static void mxc_sdma_handle_channel_normal(unsigned long data)
+static void mxc_sdma_handle_channel_normal(struct sdma_channel *data)
{
struct sdma_channel *sdmac = (struct sdma_channel *) data;
struct sdma_buffer_descriptor *bd;
@@ -778,10 +807,6 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
sdmac->status = DMA_ERROR;
else
sdmac->status = DMA_COMPLETE;
-
- dma_cookie_complete(&sdmac->txdesc);
-
- dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
}
static irqreturn_t sdma_int_handler(int irq, void *dev_id)
@@ -797,12 +822,21 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
while (stat) {
int channel = fls(stat) - 1;
struct sdma_channel *sdmac = &sdma->channel[channel];
+ struct sdma_desc *desc;
+
+ spin_lock(&sdmac->vc.lock);
+ desc = sdmac->desc;
+ if (desc) {
+ if (sdmac->flags & IMX_DMA_SG_LOOP) {
+ sdma_update_channel_loop(sdmac);
+ } else {
+ mxc_sdma_handle_channel_normal(sdmac);
+ vchan_cookie_complete(&desc->vd);
+ sdma_start_desc(sdmac);
+ }
+ }
- if (sdmac->flags & IMX_DMA_SG_LOOP)
- sdma_update_channel_loop(sdmac);
- else
- tasklet_schedule(&sdmac->tasklet);
-
+ spin_unlock(&sdmac->vc.lock);
__clear_bit(channel, &stat);
}
@@ -958,7 +992,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
{
- return container_of(chan, struct sdma_channel, chan);
+ return container_of(chan, struct sdma_channel, vc.chan);
}
static int sdma_disable_channel(struct dma_chan *chan)
@@ -980,7 +1014,16 @@ static int sdma_disable_channel(struct dma_chan *chan)
static int sdma_disable_channel_with_delay(struct dma_chan *chan)
{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
+ unsigned long flags;
+ LIST_HEAD(head);
+
sdma_disable_channel(chan);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ vchan_get_all_descriptors(&sdmac->vc, &head);
+ sdmac->desc = NULL;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+ vchan_dma_desc_free_list(&sdmac->vc, &head);
/*
* According to NXP R&D team a delay of one BD SDMA cost time
@@ -1109,46 +1152,56 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
return 0;
}
-static int sdma_request_channel(struct sdma_channel *sdmac)
+static int sdma_request_channel0(struct sdma_engine *sdma)
{
- struct sdma_engine *sdma = sdmac->sdma;
- struct sdma_desc *desc;
- int channel = sdmac->channel;
int ret = -EBUSY;
- sdmac->desc = &sdmac->_desc;
- desc = sdmac->desc;
-
- desc->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &desc->bd_phys,
- GFP_KERNEL);
- if (!desc->bd) {
+ sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
+ GFP_NOWAIT);
+ if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
}
- sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
- sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
+ sdma->channel_control[0].base_bd_ptr = sdma->bd0_phys;
+ sdma->channel_control[0].current_bd_ptr = sdma->bd0_phys;
- sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
+ sdma_set_channel_priority(&sdma->channel[0], MXC_SDMA_DEFAULT_PRIORITY);
return 0;
out:
return ret;
}
-static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
+
+static int sdma_alloc_bd(struct sdma_desc *desc)
{
- unsigned long flags;
- struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
- dma_cookie_t cookie;
+ u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+ int ret = 0;
- spin_lock_irqsave(&sdmac->lock, flags);
+ desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
+ GFP_ATOMIC);
+ if (!desc->bd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+out:
+ return ret;
+}
- cookie = dma_cookie_assign(tx);
+static void sdma_free_bd(struct sdma_desc *desc)
+{
+ u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
- spin_unlock_irqrestore(&sdmac->lock, flags);
+ dma_free_coherent(NULL, bd_size, desc->bd, desc->bd_phys);
+}
- return cookie;
+static void sdma_desc_free(struct virt_dma_desc *vd)
+{
+ struct sdma_desc *desc = container_of(vd, struct sdma_desc, vd);
+
+ sdma_free_bd(desc);
+ kfree(desc);
}
static int sdma_alloc_chan_resources(struct dma_chan *chan)
@@ -1184,19 +1237,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto disable_clk_ipg;
- ret = sdma_request_channel(sdmac);
- if (ret)
- goto disable_clk_ahb;
-
ret = sdma_set_channel_priority(sdmac, prio);
if (ret)
goto disable_clk_ahb;
- dma_async_tx_descriptor_init(&sdmac->txdesc, chan);
- sdmac->txdesc.tx_submit = sdma_tx_submit;
- /* txd.flags will be overwritten in prep funcs */
- sdmac->txdesc.flags = DMA_CTRL_ACK;
-
return 0;
disable_clk_ahb:
@@ -1210,9 +1254,8 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- struct sdma_desc *desc = sdmac->desc;
- sdma_disable_channel(chan);
+ sdma_disable_channel_with_delay(chan);
if (sdmac->event_id0)
sdma_event_disable(sdmac, sdmac->event_id0);
@@ -1224,8 +1267,6 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdma_set_channel_priority(sdmac, 0);
- dma_free_coherent(NULL, PAGE_SIZE, desc->bd, desc->bd_phys);
-
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
}
@@ -1240,7 +1281,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
int ret, i, count;
int channel = sdmac->channel;
struct scatterlist *sg;
- struct sdma_desc *desc = sdmac->desc;
+ struct sdma_desc *desc;
if (sdmac->status == DMA_IN_PROGRESS)
return NULL;
@@ -1248,23 +1289,34 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
sdmac->flags = 0;
+ desc = kzalloc((sizeof(*desc)), GFP_NOWAIT);
+ if (!desc)
+ goto err_out;
+
desc->buf_tail = 0;
desc->buf_ptail = 0;
+ desc->sdmac = sdmac;
+ desc->num_bd = sg_len;
desc->chn_real_count = 0;
+ if (sdma_alloc_bd(desc)) {
+ kfree(desc);
+ goto err_out;
+ }
+
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
sg_len, channel);
sdmac->direction = direction;
ret = sdma_load_context(sdmac);
if (ret)
- goto err_out;
+ goto err_bd_out;
if (sg_len > NUM_BD) {
dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
channel, sg_len, NUM_BD);
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
desc->chn_count = 0;
@@ -1280,7 +1332,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
channel, count, 0xffff);
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
bd->mode.count = count;
@@ -1288,25 +1340,25 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
switch (sdmac->word_size) {
case DMA_SLAVE_BUSWIDTH_4_BYTES:
bd->mode.command = 0;
if (count & 3 || sg->dma_address & 3)
- return NULL;
+ goto err_bd_out;
break;
case DMA_SLAVE_BUSWIDTH_2_BYTES:
bd->mode.command = 2;
if (count & 1 || sg->dma_address & 1)
- return NULL;
+ goto err_bd_out;
break;
case DMA_SLAVE_BUSWIDTH_1_BYTE:
bd->mode.command = 1;
break;
default:
- return NULL;
+ goto err_bd_out;
}
param = BD_DONE | BD_EXTD | BD_CONT;
@@ -1325,10 +1377,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
bd->mode.status = param;
}
- desc->num_bd = sg_len;
- sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
-
- return &sdmac->txdesc;
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1344,7 +1396,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
int num_periods = buf_len / period_len;
int channel = sdmac->channel;
int ret, i = 0, buf = 0;
- struct sdma_desc *desc = sdmac->desc;
+ struct sdma_desc *desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
@@ -1353,27 +1405,39 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
sdmac->status = DMA_IN_PROGRESS;
+ desc = kzalloc((sizeof(*desc)), GFP_NOWAIT);
+ if (!desc)
+ goto err_out;
+
desc->buf_tail = 0;
desc->buf_ptail = 0;
+ desc->sdmac = sdmac;
+ desc->num_bd = num_periods;
desc->chn_real_count = 0;
desc->period_len = period_len;
sdmac->flags |= IMX_DMA_SG_LOOP;
sdmac->direction = direction;
+
+ if (sdma_alloc_bd(desc)) {
+ kfree(desc);
+ goto err_bd_out;
+ }
+
ret = sdma_load_context(sdmac);
if (ret)
- goto err_out;
+ goto err_bd_out;
if (num_periods > NUM_BD) {
dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
channel, num_periods, NUM_BD);
- goto err_out;
+ goto err_bd_out;
}
if (period_len > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
channel, period_len, 0xffff);
- goto err_out;
+ goto err_bd_out;
}
while (buf < buf_len) {
@@ -1385,7 +1449,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
bd->mode.count = period_len;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
- goto err_out;
+ goto err_bd_out;
if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES)
bd->mode.command = 0;
else
@@ -1408,10 +1472,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
i++;
}
- desc->num_bd = num_periods;
- sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
-
- return &sdmac->txdesc;
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1450,14 +1514,31 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
- struct sdma_desc *desc = sdmac->desc;
+ struct sdma_desc *desc;
u32 residue;
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
- if (sdmac->flags & IMX_DMA_SG_LOOP)
- residue = (desc->num_bd - desc->buf_ptail) *
- desc->period_len - desc->chn_real_count;
- else
- residue = desc->chn_count - desc->chn_real_count;
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ vd = vchan_find_desc(&sdmac->vc, cookie);
+ if (vd) {
+ desc = to_sdma_desc(&vd->tx);
+ if (sdmac->flags & IMX_DMA_SG_LOOP)
+ residue = (desc->num_bd - desc->buf_ptail) *
+ desc->period_len - desc->chn_real_count;
+ else
+ residue = desc->chn_count - desc->chn_real_count;
+ } else if (sdmac->desc && sdmac->desc->vd.tx.cookie == cookie) {
+ residue = sdmac->desc->chn_count - sdmac->desc->chn_real_count;
+ } else {
+ residue = 0;
+ }
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
residue);
@@ -1468,10 +1549,12 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
static void sdma_issue_pending(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
- struct sdma_engine *sdma = sdmac->sdma;
+ unsigned long flags;
- if (sdmac->status == DMA_IN_PROGRESS)
- sdma_enable_channel(sdma, sdmac->channel);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ if (vchan_issue_pending(&sdmac->vc) && !sdmac->desc)
+ sdma_start_desc(sdmac);
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
}
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
@@ -1677,12 +1760,10 @@ static int sdma_init(struct sdma_engine *sdma)
for (i = 0; i < MAX_DMA_CHANNELS; i++)
writel_relaxed(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
- ret = sdma_request_channel(&sdma->channel[0]);
+ ret = sdma_request_channel0(sdma);
if (ret)
goto err_dma_alloc;
- sdma->bd0 = sdma->channel[0].desc->bd;
-
sdma_config_ownership(&sdma->channel[0], false, true, false);
/* Set Command Channel (Channel Zero) */
@@ -1843,20 +1924,15 @@ static int sdma_probe(struct platform_device *pdev)
sdmac->sdma = sdma;
spin_lock_init(&sdmac->lock);
- sdmac->chan.device = &sdma->dma_device;
- dma_cookie_init(&sdmac->chan);
sdmac->channel = i;
-
- tasklet_init(&sdmac->tasklet, mxc_sdma_handle_channel_normal,
- (unsigned long) sdmac);
+ sdmac->vc.desc_free = sdma_desc_free;
/*
* Add the channel to the DMAC list. Do not add channel 0 though
* because we need it internally in the SDMA driver. This also means
* that channel 0 in dmaengine counting matches sdma channel 1.
*/
if (i)
- list_add_tail(&sdmac->chan.device_node,
- &sdma->dma_device.channels);
+ vchan_init(&sdmac->vc, &sdma->dma_device);
}
ret = sdma_init(sdma);
@@ -1961,7 +2037,8 @@ static int sdma_remove(struct platform_device *pdev)
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
struct sdma_channel *sdmac = &sdma->channel[i];
- tasklet_kill(&sdmac->tasklet);
+ tasklet_kill(&sdmac->vc.task);
+ sdma_free_chan_resources(&sdmac->vc.chan);
}
platform_set_drvdata(pdev, NULL);
--
2.7.4
^ permalink raw reply related
* [PATCH v5 2/7] dmaengine: imx-sdma: factor out a struct sdma_desc from struct sdma_channel
From: Robin Gong @ 2018-06-19 16:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>
From: Sascha Hauer <s.hauer@pengutronix.de>
This is a preparation step to make the adding of virt-dma easier.
We create a struct sdma_desc, move some fields from struct sdma_channel
there and add a pointer from the former to the latter. For now we
allocate the data statically in struct sdma_channel, but with
virt-dma support it will be dynamically allocated.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/imx-sdma.c | 137 ++++++++++++++++++++++++++++++-------------------
1 file changed, 83 insertions(+), 54 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f0779926..19c351f 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -289,6 +289,30 @@ struct sdma_context_data {
struct sdma_engine;
/**
+ * struct sdma_desc - descriptor structor for one transfer
+ * @vd descriptor for virt dma
+ * @num_bd max NUM_BD. number of descriptors currently handling
+ * @buf_tail ID of the buffer that was processed
+ * @buf_ptail ID of the previous buffer that was processed
+ * @period_len period length, used in cyclic.
+ * @chn_real_count the real count updated from bd->mode.count
+ * @chn_count the transfer count setuped
+ * @sdmac sdma_channel pointer
+ * @bd pointer of alloced bd
+ */
+struct sdma_desc {
+ unsigned int num_bd;
+ dma_addr_t bd_phys;
+ unsigned int buf_tail;
+ unsigned int buf_ptail;
+ unsigned int period_len;
+ unsigned int chn_real_count;
+ unsigned int chn_count;
+ struct sdma_channel *sdmac;
+ struct sdma_buffer_descriptor *bd;
+};
+
+/**
* struct sdma_channel - housekeeping for a SDMA channel
*
* @sdma pointer to the SDMA engine for this channel
@@ -298,11 +322,10 @@ struct sdma_engine;
* @event_id0 aka dma request line
* @event_id1 for channels that use 2 events
* @word_size peripheral access size
- * @buf_tail ID of the buffer that was processed
- * @buf_ptail ID of the previous buffer that was processed
- * @num_bd max NUM_BD. number of descriptors currently handling
*/
struct sdma_channel {
+ struct sdma_desc *desc;
+ struct sdma_desc _desc;
struct sdma_engine *sdma;
unsigned int channel;
enum dma_transfer_direction direction;
@@ -310,12 +333,6 @@ struct sdma_channel {
unsigned int event_id0;
unsigned int event_id1;
enum dma_slave_buswidth word_size;
- unsigned int buf_tail;
- unsigned int buf_ptail;
- unsigned int num_bd;
- unsigned int period_len;
- struct sdma_buffer_descriptor *bd;
- dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device;
unsigned int device_to_device;
unsigned long flags;
@@ -325,10 +342,8 @@ struct sdma_channel {
u32 shp_addr, per_addr;
struct dma_chan chan;
spinlock_t lock;
- struct dma_async_tx_descriptor desc;
+ struct dma_async_tx_descriptor txdesc;
enum dma_status status;
- unsigned int chn_count;
- unsigned int chn_real_count;
struct tasklet_struct tasklet;
struct imx_dma_data data;
bool enabled;
@@ -391,6 +406,8 @@ struct sdma_engine {
u32 spba_start_addr;
u32 spba_end_addr;
unsigned int irq;
+ dma_addr_t bd0_phys;
+ struct sdma_buffer_descriptor *bd0;
};
static struct sdma_driver_data sdma_imx31 = {
@@ -625,7 +642,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
u32 address)
{
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
void *buf_virt;
dma_addr_t buf_phys;
int ret;
@@ -700,7 +717,9 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* call callback function.
*/
while (1) {
- bd = &sdmac->bd[sdmac->buf_tail];
+ struct sdma_desc *desc = sdmac->desc;
+
+ bd = &desc->bd[desc->buf_tail];
if (bd->mode.status & BD_DONE)
break;
@@ -716,11 +735,11 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* the number of bytes present in the current buffer descriptor.
*/
- sdmac->chn_real_count = bd->mode.count;
+ desc->chn_real_count = bd->mode.count;
bd->mode.status |= BD_DONE;
- bd->mode.count = sdmac->period_len;
- sdmac->buf_ptail = sdmac->buf_tail;
- sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
+ bd->mode.count = desc->period_len;
+ desc->buf_ptail = desc->buf_tail;
+ desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
/*
* The callback is called from the interrupt context in order
@@ -729,7 +748,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* executed.
*/
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+ dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
if (error)
sdmac->status = old_status;
@@ -742,17 +761,17 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
struct sdma_buffer_descriptor *bd;
int i, error = 0;
- sdmac->chn_real_count = 0;
+ sdmac->desc->chn_real_count = 0;
/*
* non loop mode. Iterate over all descriptors, collect
* errors and call callback function
*/
- for (i = 0; i < sdmac->num_bd; i++) {
- bd = &sdmac->bd[i];
+ for (i = 0; i < sdmac->desc->num_bd; i++) {
+ bd = &sdmac->desc->bd[i];
if (bd->mode.status & (BD_DONE | BD_RROR))
error = -EIO;
- sdmac->chn_real_count += bd->mode.count;
+ sdmac->desc->chn_real_count += bd->mode.count;
}
if (error)
@@ -760,9 +779,9 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
else
sdmac->status = DMA_COMPLETE;
- dma_cookie_complete(&sdmac->desc);
+ dma_cookie_complete(&sdmac->txdesc);
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+ dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
}
static irqreturn_t sdma_int_handler(int irq, void *dev_id)
@@ -890,7 +909,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int channel = sdmac->channel;
int load_address;
struct sdma_context_data *context = sdma->context;
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
int ret;
unsigned long flags;
@@ -1093,18 +1112,22 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
static int sdma_request_channel(struct sdma_channel *sdmac)
{
struct sdma_engine *sdma = sdmac->sdma;
+ struct sdma_desc *desc;
int channel = sdmac->channel;
int ret = -EBUSY;
- sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
+ sdmac->desc = &sdmac->_desc;
+ desc = sdmac->desc;
+
+ desc->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &desc->bd_phys,
GFP_KERNEL);
- if (!sdmac->bd) {
+ if (!desc->bd) {
ret = -ENOMEM;
goto out;
}
- sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
return 0;
@@ -1169,10 +1192,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto disable_clk_ahb;
- dma_async_tx_descriptor_init(&sdmac->desc, chan);
- sdmac->desc.tx_submit = sdma_tx_submit;
+ dma_async_tx_descriptor_init(&sdmac->txdesc, chan);
+ sdmac->txdesc.tx_submit = sdma_tx_submit;
/* txd.flags will be overwritten in prep funcs */
- sdmac->desc.flags = DMA_CTRL_ACK;
+ sdmac->txdesc.flags = DMA_CTRL_ACK;
return 0;
@@ -1187,6 +1210,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
+ struct sdma_desc *desc = sdmac->desc;
sdma_disable_channel(chan);
@@ -1200,7 +1224,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdma_set_channel_priority(sdmac, 0);
- dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
+ dma_free_coherent(NULL, PAGE_SIZE, desc->bd, desc->bd_phys);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
@@ -1216,6 +1240,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
int ret, i, count;
int channel = sdmac->channel;
struct scatterlist *sg;
+ struct sdma_desc *desc = sdmac->desc;
if (sdmac->status == DMA_IN_PROGRESS)
return NULL;
@@ -1223,9 +1248,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
sdmac->flags = 0;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->chn_real_count = 0;
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
sg_len, channel);
@@ -1242,9 +1267,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
goto err_out;
}
- sdmac->chn_count = 0;
+ desc->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = sg->dma_address;
@@ -1259,7 +1284,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
}
bd->mode.count = count;
- sdmac->chn_count += count;
+ desc->chn_count += count;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
ret = -EINVAL;
@@ -1300,10 +1325,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
bd->mode.status = param;
}
- sdmac->num_bd = sg_len;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ desc->num_bd = sg_len;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
- return &sdmac->desc;
+ return &sdmac->txdesc;
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1319,6 +1344,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
int num_periods = buf_len / period_len;
int channel = sdmac->channel;
int ret, i = 0, buf = 0;
+ struct sdma_desc *desc = sdmac->desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
@@ -1327,10 +1353,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
sdmac->status = DMA_IN_PROGRESS;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
- sdmac->period_len = period_len;
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->chn_real_count = 0;
+ desc->period_len = period_len;
sdmac->flags |= IMX_DMA_SG_LOOP;
sdmac->direction = direction;
@@ -1351,7 +1377,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
}
while (buf < buf_len) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = dma_addr;
@@ -1382,10 +1408,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
i++;
}
- sdmac->num_bd = num_periods;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ desc->num_bd = num_periods;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
- return &sdmac->desc;
+ return &sdmac->txdesc;
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1424,13 +1450,14 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
+ struct sdma_desc *desc = sdmac->desc;
u32 residue;
if (sdmac->flags & IMX_DMA_SG_LOOP)
- residue = (sdmac->num_bd - sdmac->buf_ptail) *
- sdmac->period_len - sdmac->chn_real_count;
+ residue = (desc->num_bd - desc->buf_ptail) *
+ desc->period_len - desc->chn_real_count;
else
- residue = sdmac->chn_count - sdmac->chn_real_count;
+ residue = desc->chn_count - desc->chn_real_count;
dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
residue);
@@ -1654,6 +1681,8 @@ static int sdma_init(struct sdma_engine *sdma)
if (ret)
goto err_dma_alloc;
+ sdma->bd0 = sdma->channel[0].desc->bd;
+
sdma_config_ownership(&sdma->channel[0], false, true, false);
/* Set Command Channel (Channel Zero) */
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox