diff options
223 files changed, 7096 insertions, 4686 deletions
diff --git a/Documentation/devicetree/bindings/dma/atmel-dma.txt b/Documentation/devicetree/bindings/dma/atmel-dma.txt index c80e8a3402f0..c280a0e6f42d 100644 --- a/Documentation/devicetree/bindings/dma/atmel-dma.txt +++ b/Documentation/devicetree/bindings/dma/atmel-dma.txt | |||
@@ -24,8 +24,11 @@ The three cells in order are: | |||
24 | 1. A phandle pointing to the DMA controller. | 24 | 1. A phandle pointing to the DMA controller. |
25 | 2. The memory interface (16 most significant bits), the peripheral interface | 25 | 2. The memory interface (16 most significant bits), the peripheral interface |
26 | (16 less significant bits). | 26 | (16 less significant bits). |
27 | 3. The peripheral identifier for the hardware handshaking interface. The | 27 | 3. Parameters for the at91 DMA configuration register which are device |
28 | identifier can be different for tx and rx. | 28 | dependant: |
29 | - bit 7-0: peripheral identifier for the hardware handshaking interface. The | ||
30 | identifier can be different for tx and rx. | ||
31 | - bit 11-8: FIFO configuration. 0 for half FIFO, 1 for ALAP, 1 for ASAP. | ||
29 | 32 | ||
30 | Example: | 33 | Example: |
31 | 34 | ||
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt new file mode 100644 index 000000000000..2717ecb47db9 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt | |||
@@ -0,0 +1,48 @@ | |||
1 | * Freescale Direct Memory Access (DMA) Controller for i.MX | ||
2 | |||
3 | This document will only describe differences to the generic DMA Controller and | ||
4 | DMA request bindings as described in dma/dma.txt . | ||
5 | |||
6 | * DMA controller | ||
7 | |||
8 | Required properties: | ||
9 | - compatible : Should be "fsl,<chip>-dma". chip can be imx1, imx21 or imx27 | ||
10 | - reg : Should contain DMA registers location and length | ||
11 | - interrupts : First item should be DMA interrupt, second one is optional and | ||
12 | should contain DMA Error interrupt | ||
13 | - #dma-cells : Has to be 1. imx-dma does not support anything else. | ||
14 | |||
15 | Optional properties: | ||
16 | - #dma-channels : Number of DMA channels supported. Should be 16. | ||
17 | - #dma-requests : Number of DMA requests supported. | ||
18 | |||
19 | Example: | ||
20 | |||
21 | dma: dma@10001000 { | ||
22 | compatible = "fsl,imx27-dma"; | ||
23 | reg = <0x10001000 0x1000>; | ||
24 | interrupts = <32 33>; | ||
25 | #dma-cells = <1>; | ||
26 | #dma-channels = <16>; | ||
27 | }; | ||
28 | |||
29 | |||
30 | * DMA client | ||
31 | |||
32 | Clients have to specify the DMA requests with phandles in a list. | ||
33 | |||
34 | Required properties: | ||
35 | - dmas: List of one or more DMA request specifiers. One DMA request specifier | ||
36 | consists of a phandle to the DMA controller followed by the integer | ||
37 | specifiying the request line. | ||
38 | - dma-names: List of string identifiers for the DMA requests. For the correct | ||
39 | names, have a look at the specific client driver. | ||
40 | |||
41 | Example: | ||
42 | |||
43 | sdhci1: sdhci@10013000 { | ||
44 | ... | ||
45 | dmas = <&dma 7>; | ||
46 | dma-names = "rx-tx"; | ||
47 | ... | ||
48 | }; | ||
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt index d1e3f443e205..68cee4f5539f 100644 --- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt | |||
@@ -4,14 +4,70 @@ Required properties: | |||
4 | - compatible : Should be "fsl,<chip>-sdma" | 4 | - compatible : Should be "fsl,<chip>-sdma" |
5 | - reg : Should contain SDMA registers location and length | 5 | - reg : Should contain SDMA registers location and length |
6 | - interrupts : Should contain SDMA interrupt | 6 | - interrupts : Should contain SDMA interrupt |
7 | - #dma-cells : Must be <3>. | ||
8 | The first cell specifies the DMA request/event ID. See details below | ||
9 | about the second and third cell. | ||
7 | - fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM | 10 | - fsl,sdma-ram-script-name : Should contain the full path of SDMA RAM |
8 | scripts firmware | 11 | scripts firmware |
9 | 12 | ||
13 | The second cell of dma phandle specifies the peripheral type of DMA transfer. | ||
14 | The full ID of peripheral types can be found below. | ||
15 | |||
16 | ID transfer type | ||
17 | --------------------- | ||
18 | 0 MCU domain SSI | ||
19 | 1 Shared SSI | ||
20 | 2 MMC | ||
21 | 3 SDHC | ||
22 | 4 MCU domain UART | ||
23 | 5 Shared UART | ||
24 | 6 FIRI | ||
25 | 7 MCU domain CSPI | ||
26 | 8 Shared CSPI | ||
27 | 9 SIM | ||
28 | 10 ATA | ||
29 | 11 CCM | ||
30 | 12 External peripheral | ||
31 | 13 Memory Stick Host Controller | ||
32 | 14 Shared Memory Stick Host Controller | ||
33 | 15 DSP | ||
34 | 16 Memory | ||
35 | 17 FIFO type Memory | ||
36 | 18 SPDIF | ||
37 | 19 IPU Memory | ||
38 | 20 ASRC | ||
39 | 21 ESAI | ||
40 | |||
41 | The third cell specifies the transfer priority as below. | ||
42 | |||
43 | ID transfer priority | ||
44 | ------------------------- | ||
45 | 0 High | ||
46 | 1 Medium | ||
47 | 2 Low | ||
48 | |||
10 | Examples: | 49 | Examples: |
11 | 50 | ||
12 | sdma@83fb0000 { | 51 | sdma@83fb0000 { |
13 | compatible = "fsl,imx51-sdma", "fsl,imx35-sdma"; | 52 | compatible = "fsl,imx51-sdma", "fsl,imx35-sdma"; |
14 | reg = <0x83fb0000 0x4000>; | 53 | reg = <0x83fb0000 0x4000>; |
15 | interrupts = <6>; | 54 | interrupts = <6>; |
55 | #dma-cells = <3>; | ||
16 | fsl,sdma-ram-script-name = "sdma-imx51.bin"; | 56 | fsl,sdma-ram-script-name = "sdma-imx51.bin"; |
17 | }; | 57 | }; |
58 | |||
59 | DMA clients connected to the i.MX SDMA controller must use the format | ||
60 | described in the dma.txt file. | ||
61 | |||
62 | Examples: | ||
63 | |||
64 | ssi2: ssi@70014000 { | ||
65 | compatible = "fsl,imx51-ssi", "fsl,imx21-ssi"; | ||
66 | reg = <0x70014000 0x4000>; | ||
67 | interrupts = <30>; | ||
68 | clocks = <&clks 49>; | ||
69 | dmas = <&sdma 24 1 0>, | ||
70 | <&sdma 25 1 0>; | ||
71 | dma-names = "rx", "tx"; | ||
72 | fsl,fifo-depth = <15>; | ||
73 | }; | ||
diff --git a/Documentation/devicetree/bindings/dma/shdma.txt b/Documentation/devicetree/bindings/dma/shdma.txt new file mode 100644 index 000000000000..c15994aa1939 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/shdma.txt | |||
@@ -0,0 +1,75 @@ | |||
1 | * SHDMA Device Tree bindings | ||
2 | |||
3 | Sh-/r-mobile and r-car systems often have multiple identical DMA controller | ||
4 | instances, capable of serving any of a common set of DMA slave devices, using | ||
5 | the same configuration. To describe this topology we require all compatible | ||
6 | SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible | ||
7 | DMAC instances have the same number of channels and use the same DMA | ||
8 | descriptors. Therefore respective DMA DT bindings can also all be placed in the | ||
9 | multiplexer node. Even if there is only one such DMAC instance on a system, it | ||
10 | still has to be placed under such a multiplexer node. | ||
11 | |||
12 | * DMA multiplexer | ||
13 | |||
14 | Required properties: | ||
15 | - compatible: should be "renesas,shdma-mux" | ||
16 | - #dma-cells: should be <1>, see "dmas" property below | ||
17 | |||
18 | Optional properties (currently unused): | ||
19 | - dma-channels: number of DMA channels | ||
20 | - dma-requests: number of DMA request signals | ||
21 | |||
22 | * DMA controller | ||
23 | |||
24 | Required properties: | ||
25 | - compatible: should be "renesas,shdma" | ||
26 | |||
27 | Example: | ||
28 | dmac: dma-mux0 { | ||
29 | compatible = "renesas,shdma-mux"; | ||
30 | #dma-cells = <1>; | ||
31 | dma-channels = <6>; | ||
32 | dma-requests = <256>; | ||
33 | reg = <0 0>; /* Needed for AUXDATA */ | ||
34 | #address-cells = <1>; | ||
35 | #size-cells = <1>; | ||
36 | ranges; | ||
37 | |||
38 | dma0: shdma@fe008020 { | ||
39 | compatible = "renesas,shdma"; | ||
40 | reg = <0xfe008020 0x270>, | ||
41 | <0xfe009000 0xc>; | ||
42 | interrupt-parent = <&gic>; | ||
43 | interrupts = <0 34 4 | ||
44 | 0 28 4 | ||
45 | 0 29 4 | ||
46 | 0 30 4 | ||
47 | 0 31 4 | ||
48 | 0 32 4 | ||
49 | 0 33 4>; | ||
50 | interrupt-names = "error", | ||
51 | "ch0", "ch1", "ch2", "ch3", | ||
52 | "ch4", "ch5"; | ||
53 | }; | ||
54 | |||
55 | dma1: shdma@fe018020 { | ||
56 | ... | ||
57 | }; | ||
58 | |||
59 | dma2: shdma@fe028020 { | ||
60 | ... | ||
61 | }; | ||
62 | }; | ||
63 | |||
64 | * DMA client | ||
65 | |||
66 | Required properties: | ||
67 | - dmas: a list of <[DMA multiplexer phandle] [MID/RID value]> pairs, | ||
68 | where MID/RID values are fixed handles, specified in the SoC | ||
69 | manual | ||
70 | - dma-names: a list of DMA channel names, one per "dmas" entry | ||
71 | |||
72 | Example: | ||
73 | dmas = <&dmac 0xd1 | ||
74 | &dmac 0xd2>; | ||
75 | dma-names = "tx", "rx"; | ||
diff --git a/Documentation/devicetree/bindings/metag/meta.txt b/Documentation/devicetree/bindings/metag/meta.txt new file mode 100644 index 000000000000..f4457f57ab08 --- /dev/null +++ b/Documentation/devicetree/bindings/metag/meta.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | * Meta Processor Binding | ||
2 | |||
3 | This binding specifies what properties must be available in the device tree | ||
4 | representation of a Meta Processor Core, which is the root node in the tree. | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible: Specifies the compatibility list for the Meta processor. | ||
9 | The type shall be <string> and the value shall include "img,meta". | ||
10 | |||
11 | Optional properties: | ||
12 | |||
13 | - clocks: Clock consumer specifiers as described in | ||
14 | Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
15 | |||
16 | - clock-names: Clock consumer names as described in | ||
17 | Documentation/devicetree/bindings/clock/clock-bindings.txt. | ||
18 | |||
19 | Clocks are identified by name. Valid clocks are: | ||
20 | |||
21 | - "core": The Meta core clock from which the Meta timers are derived. | ||
22 | |||
23 | * Examples | ||
24 | |||
25 | / { | ||
26 | compatible = "toumaz,tz1090", "img,meta"; | ||
27 | |||
28 | clocks = <&meta_core_clk>; | ||
29 | clock-names = "core"; | ||
30 | }; | ||
diff --git a/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt b/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt new file mode 100644 index 000000000000..b2d07ad90e9a --- /dev/null +++ b/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt | |||
@@ -0,0 +1,33 @@ | |||
1 | TI-NSPIRE timer | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible : should be "lsi,zevio-timer". | ||
6 | - reg : The physical base address and size of the timer (always first). | ||
7 | - clocks: phandle to the source clock. | ||
8 | |||
9 | Optional properties: | ||
10 | |||
11 | - interrupts : The interrupt number of the first timer. | ||
12 | - reg : The interrupt acknowledgement registers | ||
13 | (always after timer base address) | ||
14 | |||
15 | If any of the optional properties are not given, the timer is added as a | ||
16 | clock-source only. | ||
17 | |||
18 | Example: | ||
19 | |||
20 | timer { | ||
21 | compatible = "lsi,zevio-timer"; | ||
22 | reg = <0x900D0000 0x1000>, <0x900A0020 0x8>; | ||
23 | interrupts = <19>; | ||
24 | clocks = <&timer_clk>; | ||
25 | }; | ||
26 | |||
27 | Example (no clock-events): | ||
28 | |||
29 | timer { | ||
30 | compatible = "lsi,zevio-timer"; | ||
31 | reg = <0x900D0000 0x1000>; | ||
32 | clocks = <&timer_clk>; | ||
33 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index db0457d61682..948f61561ffa 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -58,6 +58,7 @@ snps Synopsys, Inc. | |||
58 | st STMicroelectronics | 58 | st STMicroelectronics |
59 | ste ST-Ericsson | 59 | ste ST-Ericsson |
60 | stericsson ST-Ericsson | 60 | stericsson ST-Ericsson |
61 | toumaz Toumaz | ||
61 | ti Texas Instruments | 62 | ti Texas Instruments |
62 | toshiba Toshiba Corporation | 63 | toshiba Toshiba Corporation |
63 | v3 V3 Semiconductor | 64 | v3 V3 Semiconductor |
diff --git a/MAINTAINERS b/MAINTAINERS index 50105f98cb68..97762ad25300 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7057,8 +7057,7 @@ SYNOPSYS DESIGNWARE DMAC DRIVER | |||
7057 | M: Viresh Kumar <viresh.linux@gmail.com> | 7057 | M: Viresh Kumar <viresh.linux@gmail.com> |
7058 | S: Maintained | 7058 | S: Maintained |
7059 | F: include/linux/dw_dmac.h | 7059 | F: include/linux/dw_dmac.h |
7060 | F: drivers/dma/dw_dmac_regs.h | 7060 | F: drivers/dma/dw/ |
7061 | F: drivers/dma/dw_dmac.c | ||
7062 | 7061 | ||
7063 | SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER | 7062 | SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER |
7064 | M: Seungwon Jeon <tgih.jun@samsung.com> | 7063 | M: Seungwon Jeon <tgih.jun@samsung.com> |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 531cdda016f9..5ef7af01373a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -14,6 +14,7 @@ config ARM | |||
14 | select GENERIC_IRQ_PROBE | 14 | select GENERIC_IRQ_PROBE |
15 | select GENERIC_IRQ_SHOW | 15 | select GENERIC_IRQ_SHOW |
16 | select GENERIC_PCI_IOMAP | 16 | select GENERIC_PCI_IOMAP |
17 | select GENERIC_SCHED_CLOCK | ||
17 | select GENERIC_SMP_IDLE_THREAD | 18 | select GENERIC_SMP_IDLE_THREAD |
18 | select GENERIC_IDLE_POLL_SETUP | 19 | select GENERIC_IDLE_POLL_SETUP |
19 | select GENERIC_STRNCPY_FROM_USER | 20 | select GENERIC_STRNCPY_FROM_USER |
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 195451bf7706..6a8acb01b1d3 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi | |||
@@ -736,7 +736,7 @@ | |||
736 | dcp@80028000 { | 736 | dcp@80028000 { |
737 | reg = <0x80028000 0x2000>; | 737 | reg = <0x80028000 0x2000>; |
738 | interrupts = <52 53 54>; | 738 | interrupts = <52 53 54>; |
739 | status = "disabled"; | 739 | compatible = "fsl-dcp"; |
740 | }; | 740 | }; |
741 | 741 | ||
742 | pxp@8002a000 { | 742 | pxp@8002a000 { |
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index ddc740769601..023ee63827a2 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c | |||
@@ -28,8 +28,8 @@ | |||
28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
29 | #include <linux/of_address.h> | 29 | #include <linux/of_address.h> |
30 | #include <linux/of_irq.h> | 30 | #include <linux/of_irq.h> |
31 | #include <linux/sched_clock.h> | ||
31 | 32 | ||
32 | #include <asm/sched_clock.h> | ||
33 | #include <asm/hardware/arm_timer.h> | 33 | #include <asm/hardware/arm_timer.h> |
34 | #include <asm/hardware/timer-sp.h> | 34 | #include <asm/hardware/timer-sp.h> |
35 | 35 | ||
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index 3d520ddca61b..2389b71a8e7c 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h | |||
@@ -1,16 +1,4 @@ | |||
1 | /* | 1 | /* You shouldn't include this file. Use linux/sched_clock.h instead. |
2 | * sched_clock.h: support for extending counters to full 64-bit ns counter | 2 | * Temporary file until all asm/sched_clock.h users are gone |
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | 3 | */ |
8 | #ifndef ASM_SCHED_CLOCK | 4 | #include <linux/sched_clock.h> |
9 | #define ASM_SCHED_CLOCK | ||
10 | |||
11 | extern void sched_clock_postinit(void); | ||
12 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); | ||
13 | |||
14 | extern unsigned long long (*sched_clock_func)(void); | ||
15 | |||
16 | #endif | ||
diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h index 799f42ecca63..7704e28c3483 100644 --- a/arch/arm/include/asm/xen/hypercall.h +++ b/arch/arm/include/asm/xen/hypercall.h | |||
@@ -47,6 +47,7 @@ unsigned long HYPERVISOR_hvm_op(int op, void *arg); | |||
47 | int HYPERVISOR_memory_op(unsigned int cmd, void *arg); | 47 | int HYPERVISOR_memory_op(unsigned int cmd, void *arg); |
48 | int HYPERVISOR_physdev_op(int cmd, void *arg); | 48 | int HYPERVISOR_physdev_op(int cmd, void *arg); |
49 | int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args); | 49 | int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args); |
50 | int HYPERVISOR_tmem_op(void *arg); | ||
50 | 51 | ||
51 | static inline void | 52 | static inline void |
52 | MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, | 53 | MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index fccfbdb03df1..86d10dd47dc4 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -16,7 +16,7 @@ CFLAGS_REMOVE_return_address.o = -pg | |||
16 | # Object file lists. | 16 | # Object file lists. |
17 | 17 | ||
18 | obj-y := elf.o entry-common.o irq.o opcodes.o \ | 18 | obj-y := elf.o entry-common.o irq.o opcodes.o \ |
19 | process.o ptrace.o return_address.o sched_clock.o \ | 19 | process.o ptrace.o return_address.o \ |
20 | setup.o signal.o stacktrace.o sys_arm.o time.o traps.o | 20 | setup.o signal.o stacktrace.o sys_arm.o time.o traps.o |
21 | 21 | ||
22 | obj-$(CONFIG_ATAGS) += atags_parse.o | 22 | obj-$(CONFIG_ATAGS) += atags_parse.o |
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index 59dcdced6e30..221f07b11ccb 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c | |||
@@ -11,9 +11,9 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/sched_clock.h> | ||
14 | 15 | ||
15 | #include <asm/delay.h> | 16 | #include <asm/delay.h> |
16 | #include <asm/sched_clock.h> | ||
17 | 17 | ||
18 | #include <clocksource/arm_arch_timer.h> | 18 | #include <clocksource/arm_arch_timer.h> |
19 | 19 | ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index abff4e9aaee0..98aee3258398 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -24,9 +24,9 @@ | |||
24 | #include <linux/timer.h> | 24 | #include <linux/timer.h> |
25 | #include <linux/clocksource.h> | 25 | #include <linux/clocksource.h> |
26 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
27 | #include <linux/sched_clock.h> | ||
27 | 28 | ||
28 | #include <asm/thread_info.h> | 29 | #include <asm/thread_info.h> |
29 | #include <asm/sched_clock.h> | ||
30 | #include <asm/stacktrace.h> | 30 | #include <asm/stacktrace.h> |
31 | #include <asm/mach/arch.h> | 31 | #include <asm/mach/arch.h> |
32 | #include <asm/mach/time.h> | 32 | #include <asm/mach/time.h> |
@@ -120,6 +120,4 @@ void __init time_init(void) | |||
120 | machine_desc->init_time(); | 120 | machine_desc->init_time(); |
121 | else | 121 | else |
122 | clocksource_of_init(); | 122 | clocksource_of_init(); |
123 | |||
124 | sched_clock_postinit(); | ||
125 | } | 123 | } |
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index bad361ec1666..7a55b5c95971 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/sched_clock.h> | ||
21 | 22 | ||
22 | #include <asm/sched_clock.h> | ||
23 | #include <asm/mach/irq.h> | 23 | #include <asm/mach/irq.h> |
24 | #include <asm/mach/time.h> | 24 | #include <asm/mach/time.h> |
25 | 25 | ||
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index fea91313678b..cd46529e9eaa 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include <linux/clockchips.h> | 26 | #include <linux/clockchips.h> |
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/sched_clock.h> | ||
29 | 30 | ||
30 | #include <asm/sched_clock.h> | ||
31 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
32 | 32 | ||
33 | #include "common.h" | 33 | #include "common.h" |
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index a5b15c4e8def..d9e95e612fcb 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/stat.h> | 41 | #include <linux/stat.h> |
42 | #include <linux/sys_soc.h> | 42 | #include <linux/sys_soc.h> |
43 | #include <linux/termios.h> | 43 | #include <linux/termios.h> |
44 | #include <linux/sched_clock.h> | ||
44 | 45 | ||
45 | #include <mach/hardware.h> | 46 | #include <mach/hardware.h> |
46 | #include <mach/platform.h> | 47 | #include <mach/platform.h> |
@@ -48,7 +49,6 @@ | |||
48 | #include <asm/setup.h> | 49 | #include <asm/setup.h> |
49 | #include <asm/param.h> /* HZ */ | 50 | #include <asm/param.h> /* HZ */ |
50 | #include <asm/mach-types.h> | 51 | #include <asm/mach-types.h> |
51 | #include <asm/sched_clock.h> | ||
52 | 52 | ||
53 | #include <mach/lm.h> | 53 | #include <mach/lm.h> |
54 | #include <mach/irqs.h> | 54 | #include <mach/irqs.h> |
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index d7223b3b81f3..1f6c1fb353ad 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/export.h> | 30 | #include <linux/export.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/cpu.h> | 32 | #include <linux/cpu.h> |
33 | #include <linux/sched_clock.h> | ||
33 | 34 | ||
34 | #include <mach/udc.h> | 35 | #include <mach/udc.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
@@ -38,7 +39,6 @@ | |||
38 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
39 | #include <asm/page.h> | 40 | #include <asm/page.h> |
40 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
41 | #include <asm/sched_clock.h> | ||
42 | #include <asm/system_misc.h> | 42 | #include <asm/system_misc.h> |
43 | 43 | ||
44 | #include <asm/mach/map.h> | 44 | #include <asm/mach/map.h> |
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index c1cd5a943ab1..e54f87ec2e4a 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c | |||
@@ -182,8 +182,8 @@ static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch) | |||
182 | static struct pl08x_platform_data pl08x_pd = { | 182 | static struct pl08x_platform_data pl08x_pd = { |
183 | .slave_channels = &pl08x_slave_channels[0], | 183 | .slave_channels = &pl08x_slave_channels[0], |
184 | .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), | 184 | .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), |
185 | .get_signal = pl08x_get_signal, | 185 | .get_xfer_signal = pl08x_get_signal, |
186 | .put_signal = pl08x_put_signal, | 186 | .put_xfer_signal = pl08x_put_signal, |
187 | .lli_buses = PL08X_AHB1, | 187 | .lli_buses = PL08X_AHB1, |
188 | .mem_buses = PL08X_AHB1, | 188 | .mem_buses = PL08X_AHB1, |
189 | }; | 189 | }; |
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 86a18b3d252e..7ac41e83cfef 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c | |||
@@ -28,8 +28,8 @@ | |||
28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
29 | #include <linux/of_address.h> | 29 | #include <linux/of_address.h> |
30 | #include <linux/of_irq.h> | 30 | #include <linux/of_irq.h> |
31 | #include <linux/sched_clock.h> | ||
31 | 32 | ||
32 | #include <asm/sched_clock.h> | ||
33 | #include <mach/addr-map.h> | 33 | #include <mach/addr-map.h> |
34 | #include <mach/regs-timers.h> | 34 | #include <mach/regs-timers.h> |
35 | #include <mach/regs-apbc.h> | 35 | #include <mach/regs-apbc.h> |
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 284313f3e02c..b6418fd5fe0d 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c | |||
@@ -23,10 +23,10 @@ | |||
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
25 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
26 | #include <linux/sched_clock.h> | ||
26 | 27 | ||
27 | #include <asm/mach/time.h> | 28 | #include <asm/mach/time.h> |
28 | #include <asm/localtimer.h> | 29 | #include <asm/localtimer.h> |
29 | #include <asm/sched_clock.h> | ||
30 | 30 | ||
31 | #include "common.h" | 31 | #include "common.h" |
32 | 32 | ||
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 726ec23d29c7..80603d2fef77 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -43,9 +43,9 @@ | |||
43 | #include <linux/clocksource.h> | 43 | #include <linux/clocksource.h> |
44 | #include <linux/clockchips.h> | 44 | #include <linux/clockchips.h> |
45 | #include <linux/io.h> | 45 | #include <linux/io.h> |
46 | #include <linux/sched_clock.h> | ||
46 | 47 | ||
47 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
48 | #include <asm/sched_clock.h> | ||
49 | 49 | ||
50 | #include <mach/hardware.h> | 50 | #include <mach/hardware.h> |
51 | #include <asm/mach/irq.h> | 51 | #include <asm/mach/irq.h> |
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 3bdb0fb02028..29ac667b7a8b 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -41,10 +41,10 @@ | |||
41 | #include <linux/of_irq.h> | 41 | #include <linux/of_irq.h> |
42 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
43 | #include <linux/platform_data/dmtimer-omap.h> | 43 | #include <linux/platform_data/dmtimer-omap.h> |
44 | #include <linux/sched_clock.h> | ||
44 | 45 | ||
45 | #include <asm/mach/time.h> | 46 | #include <asm/mach/time.h> |
46 | #include <asm/smp_twd.h> | 47 | #include <asm/smp_twd.h> |
47 | #include <asm/sched_clock.h> | ||
48 | 48 | ||
49 | #include "omap_hwmod.h" | 49 | #include "omap_hwmod.h" |
50 | #include "omap_device.h" | 50 | #include "omap_device.h" |
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 8f1ee92aea30..9aa852a8fab9 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
@@ -16,11 +16,11 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
19 | #include <linux/sched_clock.h> | ||
19 | 20 | ||
20 | #include <asm/div64.h> | 21 | #include <asm/div64.h> |
21 | #include <asm/mach/irq.h> | 22 | #include <asm/mach/irq.h> |
22 | #include <asm/mach/time.h> | 23 | #include <asm/mach/time.h> |
23 | #include <asm/sched_clock.h> | ||
24 | #include <mach/regs-ost.h> | 24 | #include <mach/regs-ost.h> |
25 | #include <mach/irqs.h> | 25 | #include <mach/irqs.h> |
26 | 26 | ||
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index a59a13a665a6..713c86cd3d64 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c | |||
@@ -14,9 +14,9 @@ | |||
14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
15 | #include <linux/timex.h> | 15 | #include <linux/timex.h> |
16 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
17 | #include <linux/sched_clock.h> | ||
17 | 18 | ||
18 | #include <asm/mach/time.h> | 19 | #include <asm/mach/time.h> |
19 | #include <asm/sched_clock.h> | ||
20 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
21 | #include <mach/irqs.h> | 21 | #include <mach/irqs.h> |
22 | 22 | ||
diff --git a/arch/arm/mach-spear/spear3xx.c b/arch/arm/mach-spear/spear3xx.c index 0227c97797cd..bf3b1fd8cb23 100644 --- a/arch/arm/mach-spear/spear3xx.c +++ b/arch/arm/mach-spear/spear3xx.c | |||
@@ -56,8 +56,8 @@ struct pl08x_platform_data pl080_plat_data = { | |||
56 | }, | 56 | }, |
57 | .lli_buses = PL08X_AHB1, | 57 | .lli_buses = PL08X_AHB1, |
58 | .mem_buses = PL08X_AHB1, | 58 | .mem_buses = PL08X_AHB1, |
59 | .get_signal = pl080_get_signal, | 59 | .get_xfer_signal = pl080_get_signal, |
60 | .put_signal = pl080_put_signal, | 60 | .put_xfer_signal = pl080_put_signal, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* | 63 | /* |
diff --git a/arch/arm/mach-spear/spear6xx.c b/arch/arm/mach-spear/spear6xx.c index 8b0295a41226..da26fa5b68d7 100644 --- a/arch/arm/mach-spear/spear6xx.c +++ b/arch/arm/mach-spear/spear6xx.c | |||
@@ -334,8 +334,8 @@ static struct pl08x_platform_data spear6xx_pl080_plat_data = { | |||
334 | }, | 334 | }, |
335 | .lli_buses = PL08X_AHB1, | 335 | .lli_buses = PL08X_AHB1, |
336 | .mem_buses = PL08X_AHB1, | 336 | .mem_buses = PL08X_AHB1, |
337 | .get_signal = pl080_get_signal, | 337 | .get_xfer_signal = pl080_get_signal, |
338 | .put_signal = pl080_put_signal, | 338 | .put_xfer_signal = pl080_put_signal, |
339 | .slave_channels = spear600_dma_info, | 339 | .slave_channels = spear600_dma_info, |
340 | .num_slave_channels = ARRAY_SIZE(spear600_dma_info), | 340 | .num_slave_channels = ARRAY_SIZE(spear600_dma_info), |
341 | }; | 341 | }; |
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 390ae5feb1d0..b5db207dfd1e 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c | |||
@@ -21,9 +21,9 @@ | |||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
23 | #include <linux/of_irq.h> | 23 | #include <linux/of_irq.h> |
24 | #include <linux/sched_clock.h> | ||
24 | 25 | ||
25 | /* Generic stuff */ | 26 | /* Generic stuff */ |
26 | #include <asm/sched_clock.h> | ||
27 | #include <asm/mach/map.h> | 27 | #include <asm/mach/map.h> |
28 | #include <asm/mach/time.h> | 28 | #include <asm/mach/time.h> |
29 | 29 | ||
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 7ec02961dfa0..7f9b1798c6cf 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -1328,6 +1328,15 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, | |||
1328 | if (gfp & GFP_ATOMIC) | 1328 | if (gfp & GFP_ATOMIC) |
1329 | return __iommu_alloc_atomic(dev, size, handle); | 1329 | return __iommu_alloc_atomic(dev, size, handle); |
1330 | 1330 | ||
1331 | /* | ||
1332 | * Following is a work-around (a.k.a. hack) to prevent pages | ||
1333 | * with __GFP_COMP being passed to split_page() which cannot | ||
1334 | * handle them. The real problem is that this flag probably | ||
1335 | * should be 0 on ARM as it is not supported on this | ||
1336 | * platform; see CONFIG_HUGETLBFS. | ||
1337 | */ | ||
1338 | gfp &= ~(__GFP_COMP); | ||
1339 | |||
1331 | pages = __iommu_alloc_buffer(dev, size, gfp, attrs); | 1340 | pages = __iommu_alloc_buffer(dev, size, gfp, attrs); |
1332 | if (!pages) | 1341 | if (!pages) |
1333 | return NULL; | 1342 | return NULL; |
@@ -1386,16 +1395,17 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, | |||
1386 | void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, | 1395 | void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, |
1387 | dma_addr_t handle, struct dma_attrs *attrs) | 1396 | dma_addr_t handle, struct dma_attrs *attrs) |
1388 | { | 1397 | { |
1389 | struct page **pages = __iommu_get_pages(cpu_addr, attrs); | 1398 | struct page **pages; |
1390 | size = PAGE_ALIGN(size); | 1399 | size = PAGE_ALIGN(size); |
1391 | 1400 | ||
1392 | if (!pages) { | 1401 | if (__in_atomic_pool(cpu_addr, size)) { |
1393 | WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); | 1402 | __iommu_free_atomic(dev, cpu_addr, handle, size); |
1394 | return; | 1403 | return; |
1395 | } | 1404 | } |
1396 | 1405 | ||
1397 | if (__in_atomic_pool(cpu_addr, size)) { | 1406 | pages = __iommu_get_pages(cpu_addr, attrs); |
1398 | __iommu_free_atomic(dev, cpu_addr, handle, size); | 1407 | if (!pages) { |
1408 | WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); | ||
1399 | return; | 1409 | return; |
1400 | } | 1410 | } |
1401 | 1411 | ||
@@ -1650,13 +1660,27 @@ static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *p | |||
1650 | { | 1660 | { |
1651 | struct dma_iommu_mapping *mapping = dev->archdata.mapping; | 1661 | struct dma_iommu_mapping *mapping = dev->archdata.mapping; |
1652 | dma_addr_t dma_addr; | 1662 | dma_addr_t dma_addr; |
1653 | int ret, len = PAGE_ALIGN(size + offset); | 1663 | int ret, prot, len = PAGE_ALIGN(size + offset); |
1654 | 1664 | ||
1655 | dma_addr = __alloc_iova(mapping, len); | 1665 | dma_addr = __alloc_iova(mapping, len); |
1656 | if (dma_addr == DMA_ERROR_CODE) | 1666 | if (dma_addr == DMA_ERROR_CODE) |
1657 | return dma_addr; | 1667 | return dma_addr; |
1658 | 1668 | ||
1659 | ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0); | 1669 | switch (dir) { |
1670 | case DMA_BIDIRECTIONAL: | ||
1671 | prot = IOMMU_READ | IOMMU_WRITE; | ||
1672 | break; | ||
1673 | case DMA_TO_DEVICE: | ||
1674 | prot = IOMMU_READ; | ||
1675 | break; | ||
1676 | case DMA_FROM_DEVICE: | ||
1677 | prot = IOMMU_WRITE; | ||
1678 | break; | ||
1679 | default: | ||
1680 | prot = 0; | ||
1681 | } | ||
1682 | |||
1683 | ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot); | ||
1660 | if (ret < 0) | 1684 | if (ret < 0) |
1661 | goto fail; | 1685 | goto fail; |
1662 | 1686 | ||
@@ -1921,7 +1945,7 @@ void arm_iommu_detach_device(struct device *dev) | |||
1921 | 1945 | ||
1922 | iommu_detach_device(mapping->domain, dev); | 1946 | iommu_detach_device(mapping->domain, dev); |
1923 | kref_put(&mapping->kref, release_iommu_mapping); | 1947 | kref_put(&mapping->kref, release_iommu_mapping); |
1924 | mapping = NULL; | 1948 | dev->archdata.mapping = NULL; |
1925 | set_dma_ops(dev, NULL); | 1949 | set_dma_ops(dev, NULL); |
1926 | 1950 | ||
1927 | pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); | 1951 | pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); |
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 837a2d52e9db..29606bd75f3f 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c | |||
@@ -22,9 +22,9 @@ | |||
22 | #include <linux/clocksource.h> | 22 | #include <linux/clocksource.h> |
23 | #include <linux/clockchips.h> | 23 | #include <linux/clockchips.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/sched_clock.h> | ||
25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
26 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
27 | #include <asm/sched_clock.h> | ||
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/mach/irq.h> | 29 | #include <asm/mach/irq.h> |
30 | #include <asm/mach/time.h> | 30 | #include <asm/mach/time.h> |
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 5b0b86bb34bb..d9bc98eb2a6b 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/clocksource.h> | 20 | #include <linux/clocksource.h> |
21 | #include <linux/sched_clock.h> | ||
21 | 22 | ||
22 | #include <asm/mach/time.h> | 23 | #include <asm/mach/time.h> |
23 | #include <asm/sched_clock.h> | ||
24 | 24 | ||
25 | #include <plat/counter-32k.h> | 25 | #include <plat/counter-32k.h> |
26 | 26 | ||
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 5d5ac0f05422..9d2b2ac74938 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <asm/sched_clock.h> | 19 | #include <linux/sched_clock.h> |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * MBus bridge block registers. | 22 | * MBus bridge block registers. |
diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c index f899cbc9b288..2957075ca836 100644 --- a/arch/arm/plat-samsung/samsung-time.c +++ b/arch/arm/plat-samsung/samsung-time.c | |||
@@ -15,12 +15,12 @@ | |||
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/sched_clock.h> | ||
18 | 19 | ||
19 | #include <asm/smp_twd.h> | 20 | #include <asm/smp_twd.h> |
20 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
21 | #include <asm/mach/arch.h> | 22 | #include <asm/mach/arch.h> |
22 | #include <asm/mach/map.h> | 23 | #include <asm/mach/map.h> |
23 | #include <asm/sched_clock.h> | ||
24 | 24 | ||
25 | #include <mach/map.h> | 25 | #include <mach/map.h> |
26 | #include <plat/devs.h> | 26 | #include <plat/devs.h> |
diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c index b33b74c87232..51b109e3b6c3 100644 --- a/arch/arm/plat-versatile/sched-clock.c +++ b/arch/arm/plat-versatile/sched-clock.c | |||
@@ -20,8 +20,8 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/sched_clock.h> | ||
23 | 24 | ||
24 | #include <asm/sched_clock.h> | ||
25 | #include <plat/sched_clock.h> | 25 | #include <plat/sched_clock.h> |
26 | 26 | ||
27 | static void __iomem *ctr; | 27 | static void __iomem *ctr; |
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 13609e01f4b7..f71c37edca26 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -314,4 +314,5 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); | |||
314 | EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); | 314 | EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); |
315 | EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); | 315 | EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); |
316 | EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op); | 316 | EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op); |
317 | EXPORT_SYMBOL_GPL(HYPERVISOR_tmem_op); | ||
317 | EXPORT_SYMBOL_GPL(privcmd_call); | 318 | EXPORT_SYMBOL_GPL(privcmd_call); |
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S index 199cb2da7663..d1cf7b7c2200 100644 --- a/arch/arm/xen/hypercall.S +++ b/arch/arm/xen/hypercall.S | |||
@@ -88,6 +88,7 @@ HYPERCALL2(hvm_op); | |||
88 | HYPERCALL2(memory_op); | 88 | HYPERCALL2(memory_op); |
89 | HYPERCALL2(physdev_op); | 89 | HYPERCALL2(physdev_op); |
90 | HYPERCALL3(vcpu_op); | 90 | HYPERCALL3(vcpu_op); |
91 | HYPERCALL1(tmem_op); | ||
91 | 92 | ||
92 | ENTRY(privcmd_call) | 93 | ENTRY(privcmd_call) |
93 | stmdb sp!, {r4} | 94 | stmdb sp!, {r4} |
diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S index 2816c479cd49..531342ec4bcf 100644 --- a/arch/arm64/xen/hypercall.S +++ b/arch/arm64/xen/hypercall.S | |||
@@ -79,6 +79,7 @@ HYPERCALL2(hvm_op); | |||
79 | HYPERCALL2(memory_op); | 79 | HYPERCALL2(memory_op); |
80 | HYPERCALL2(physdev_op); | 80 | HYPERCALL2(physdev_op); |
81 | HYPERCALL3(vcpu_op); | 81 | HYPERCALL3(vcpu_op); |
82 | HYPERCALL1(tmem_op); | ||
82 | 83 | ||
83 | ENTRY(privcmd_call) | 84 | ENTRY(privcmd_call) |
84 | mov x16, x0 | 85 | mov x16, x0 |
diff --git a/arch/metag/Kconfig.soc b/arch/metag/Kconfig.soc index ec079cfb7c6a..2a3c860c7525 100644 --- a/arch/metag/Kconfig.soc +++ b/arch/metag/Kconfig.soc | |||
@@ -14,6 +14,18 @@ config META21_FPGA | |||
14 | help | 14 | help |
15 | This is a Meta 2.1 FPGA bitstream, just a bare CPU. | 15 | This is a Meta 2.1 FPGA bitstream, just a bare CPU. |
16 | 16 | ||
17 | config SOC_TZ1090 | ||
18 | bool "Toumaz Xenif TZ1090 SoC (Comet)" | ||
19 | select METAG_LNKGET_AROUND_CACHE | ||
20 | select METAG_META21 | ||
21 | select METAG_SMP_WRITE_REORDERING | ||
22 | select PINCTRL | ||
23 | select PINCTRL_TZ1090 | ||
24 | select PINCTRL_TZ1090_PDC | ||
25 | help | ||
26 | This is a Toumaz Technology Xenif TZ1090 (A.K.A. Comet) SoC containing | ||
27 | a 2-threaded HTP. | ||
28 | |||
17 | endchoice | 29 | endchoice |
18 | 30 | ||
19 | menu "SoC configuration" | 31 | menu "SoC configuration" |
diff --git a/arch/metag/Makefile b/arch/metag/Makefile index b566116b171b..9739857bdedc 100644 --- a/arch/metag/Makefile +++ b/arch/metag/Makefile | |||
@@ -20,7 +20,7 @@ checkflags-$(CONFIG_METAG_META12) += -DMETAC_1_2 | |||
20 | checkflags-$(CONFIG_METAG_META21) += -DMETAC_2_1 | 20 | checkflags-$(CONFIG_METAG_META21) += -DMETAC_2_1 |
21 | CHECKFLAGS += -D__metag__ $(checkflags-y) | 21 | CHECKFLAGS += -D__metag__ $(checkflags-y) |
22 | 22 | ||
23 | KBUILD_DEFCONFIG := meta2_defconfig | 23 | KBUILD_DEFCONFIG := tz1090_defconfig |
24 | 24 | ||
25 | sflags-$(CONFIG_METAG_META12) += -mmetac=1.2 | 25 | sflags-$(CONFIG_METAG_META12) += -mmetac=1.2 |
26 | ifeq ($(CONFIG_METAG_META12),y) | 26 | ifeq ($(CONFIG_METAG_META12),y) |
diff --git a/arch/metag/boot/.gitignore b/arch/metag/boot/.gitignore index a021da201156..2d6c0c160884 100644 --- a/arch/metag/boot/.gitignore +++ b/arch/metag/boot/.gitignore | |||
@@ -1,4 +1,4 @@ | |||
1 | vmlinux* | 1 | vmlinux* |
2 | uImage* | 2 | uImage* |
3 | ramdisk.* | 3 | ramdisk.* |
4 | *.dtb | 4 | *.dtb* |
diff --git a/arch/metag/boot/dts/Makefile b/arch/metag/boot/dts/Makefile index dbd95217733a..72c121879426 100644 --- a/arch/metag/boot/dts/Makefile +++ b/arch/metag/boot/dts/Makefile | |||
@@ -1,7 +1,9 @@ | |||
1 | dtb-y += skeleton.dtb | 1 | dtb-y += skeleton.dtb |
2 | dtb-y += tz1090_generic.dtb | ||
2 | 3 | ||
3 | # Built-in dtb | 4 | # Built-in dtb |
4 | builtindtb-y := skeleton | 5 | builtindtb-y := skeleton |
6 | builtindtb-$(CONFIG_SOC_TZ1090) := tz1090_generic | ||
5 | 7 | ||
6 | ifneq ($(CONFIG_METAG_BUILTIN_DTB_NAME),"") | 8 | ifneq ($(CONFIG_METAG_BUILTIN_DTB_NAME),"") |
7 | builtindtb-y := $(patsubst "%",%,$(CONFIG_METAG_BUILTIN_DTB_NAME)) | 9 | builtindtb-y := $(patsubst "%",%,$(CONFIG_METAG_BUILTIN_DTB_NAME)) |
diff --git a/arch/metag/boot/dts/include/dt-bindings b/arch/metag/boot/dts/include/dt-bindings new file mode 120000 index 000000000000..08c00e4972fa --- /dev/null +++ b/arch/metag/boot/dts/include/dt-bindings | |||
@@ -0,0 +1 @@ | |||
../../../../../include/dt-bindings \ No newline at end of file | |||
diff --git a/arch/metag/boot/dts/skeleton.dts b/arch/metag/boot/dts/skeleton.dts index 7244d1f0d555..7a49aeb365d0 100644 --- a/arch/metag/boot/dts/skeleton.dts +++ b/arch/metag/boot/dts/skeleton.dts | |||
@@ -7,4 +7,4 @@ | |||
7 | */ | 7 | */ |
8 | /dts-v1/; | 8 | /dts-v1/; |
9 | 9 | ||
10 | /include/ "skeleton.dtsi" | 10 | #include "skeleton.dtsi" |
diff --git a/arch/metag/boot/dts/tz1090.dtsi b/arch/metag/boot/dts/tz1090.dtsi new file mode 100644 index 000000000000..853744652b93 --- /dev/null +++ b/arch/metag/boot/dts/tz1090.dtsi | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Imagination Technologies Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include "skeleton.dtsi" | ||
10 | |||
11 | / { | ||
12 | compatible = "toumaz,tz1090", "img,meta"; | ||
13 | |||
14 | interrupt-parent = <&intc>; | ||
15 | |||
16 | intc: interrupt-controller { | ||
17 | compatible = "img,meta-intc"; | ||
18 | interrupt-controller; | ||
19 | #interrupt-cells = <2>; | ||
20 | num-banks = <2>; | ||
21 | }; | ||
22 | |||
23 | soc { | ||
24 | compatible = "simple-bus"; | ||
25 | #address-cells = <1>; | ||
26 | #size-cells = <1>; | ||
27 | ranges; | ||
28 | |||
29 | pinctrl: pinctrl@02005800 { | ||
30 | #gpio-range-cells = <3>; | ||
31 | compatible = "img,tz1090-pinctrl"; | ||
32 | reg = <0x02005800 0xe4>; | ||
33 | }; | ||
34 | |||
35 | pdc_pinctrl: pinctrl@02006500 { | ||
36 | #gpio-range-cells = <3>; | ||
37 | compatible = "img,tz1090-pdc-pinctrl"; | ||
38 | reg = <0x02006500 0x100>; | ||
39 | }; | ||
40 | }; | ||
41 | }; | ||
diff --git a/arch/metag/boot/dts/tz1090_generic.dts b/arch/metag/boot/dts/tz1090_generic.dts new file mode 100644 index 000000000000..f96090955964 --- /dev/null +++ b/arch/metag/boot/dts/tz1090_generic.dts | |||
@@ -0,0 +1,10 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Imagination Technologies Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | /dts-v1/; | ||
9 | |||
10 | #include "tz1090.dtsi" | ||
diff --git a/arch/metag/configs/tz1090_defconfig b/arch/metag/configs/tz1090_defconfig new file mode 100644 index 000000000000..9f9316a6df27 --- /dev/null +++ b/arch/metag/configs/tz1090_defconfig | |||
@@ -0,0 +1,42 @@ | |||
1 | # CONFIG_LOCALVERSION_AUTO is not set | ||
2 | # CONFIG_SWAP is not set | ||
3 | CONFIG_SYSVIPC=y | ||
4 | CONFIG_SYSFS_DEPRECATED=y | ||
5 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
6 | CONFIG_KALLSYMS_ALL=y | ||
7 | # CONFIG_ELF_CORE is not set | ||
8 | CONFIG_SLAB=y | ||
9 | # CONFIG_BLK_DEV_BSG is not set | ||
10 | CONFIG_PARTITION_ADVANCED=y | ||
11 | # CONFIG_MSDOS_PARTITION is not set | ||
12 | # CONFIG_IOSCHED_DEADLINE is not set | ||
13 | # CONFIG_IOSCHED_CFQ is not set | ||
14 | CONFIG_FLATMEM_MANUAL=y | ||
15 | CONFIG_SOC_TZ1090=y | ||
16 | CONFIG_METAG_HALT_ON_PANIC=y | ||
17 | # CONFIG_METAG_FPU is not set | ||
18 | CONFIG_METAG_DA=y | ||
19 | CONFIG_HZ_100=y | ||
20 | CONFIG_DEVTMPFS=y | ||
21 | # CONFIG_STANDALONE is not set | ||
22 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | ||
23 | # CONFIG_FW_LOADER is not set | ||
24 | CONFIG_BLK_DEV_RAM=y | ||
25 | CONFIG_BLK_DEV_RAM_COUNT=1 | ||
26 | CONFIG_BLK_DEV_RAM_SIZE=16384 | ||
27 | # CONFIG_INPUT is not set | ||
28 | # CONFIG_SERIO is not set | ||
29 | # CONFIG_VT is not set | ||
30 | # CONFIG_LEGACY_PTYS is not set | ||
31 | CONFIG_DA_TTY=y | ||
32 | CONFIG_DA_CONSOLE=y | ||
33 | # CONFIG_DEVKMEM is not set | ||
34 | # CONFIG_HW_RANDOM is not set | ||
35 | CONFIG_GPIOLIB=y | ||
36 | # CONFIG_HWMON is not set | ||
37 | # CONFIG_USB_SUPPORT is not set | ||
38 | # CONFIG_DNOTIFY is not set | ||
39 | CONFIG_TMPFS=y | ||
40 | # CONFIG_MISC_FILESYSTEMS is not set | ||
41 | # CONFIG_SCHED_DEBUG is not set | ||
42 | CONFIG_DEBUG_INFO=y | ||
diff --git a/arch/metag/include/asm/bug.h b/arch/metag/include/asm/bug.h index d04b48cefecc..9f8967f10f8c 100644 --- a/arch/metag/include/asm/bug.h +++ b/arch/metag/include/asm/bug.h | |||
@@ -6,7 +6,7 @@ | |||
6 | struct pt_regs; | 6 | struct pt_regs; |
7 | 7 | ||
8 | extern const char *trap_name(int trapno); | 8 | extern const char *trap_name(int trapno); |
9 | extern void die(const char *str, struct pt_regs *regs, long err, | 9 | extern void __noreturn die(const char *str, struct pt_regs *regs, long err, |
10 | unsigned long addr) __attribute__ ((noreturn)); | 10 | unsigned long addr); |
11 | 11 | ||
12 | #endif | 12 | #endif |
diff --git a/arch/metag/include/asm/clock.h b/arch/metag/include/asm/clock.h index 3e2915a280c7..ded4ab2e1fd0 100644 --- a/arch/metag/include/asm/clock.h +++ b/arch/metag/include/asm/clock.h | |||
@@ -19,6 +19,8 @@ | |||
19 | * core frequency will be determined like this: | 19 | * core frequency will be determined like this: |
20 | * Meta 1: based on loops_per_jiffy. | 20 | * Meta 1: based on loops_per_jiffy. |
21 | * Meta 2: (EXPAND_TIMER_DIV + 1) MHz. | 21 | * Meta 2: (EXPAND_TIMER_DIV + 1) MHz. |
22 | * If a "core" clock is provided by the device tree, it | ||
23 | * will override this function. | ||
22 | */ | 24 | */ |
23 | struct meta_clock_desc { | 25 | struct meta_clock_desc { |
24 | unsigned long (*get_core_freq)(void); | 26 | unsigned long (*get_core_freq)(void); |
@@ -27,6 +29,12 @@ struct meta_clock_desc { | |||
27 | extern struct meta_clock_desc _meta_clock; | 29 | extern struct meta_clock_desc _meta_clock; |
28 | 30 | ||
29 | /* | 31 | /* |
32 | * Perform platform clock initialisation, reading clocks from device tree etc. | ||
33 | * Only accessible during boot. | ||
34 | */ | ||
35 | void init_metag_clocks(void); | ||
36 | |||
37 | /* | ||
30 | * Set up the default clock, ensuring all callbacks are valid - only accessible | 38 | * Set up the default clock, ensuring all callbacks are valid - only accessible |
31 | * during boot. | 39 | * during boot. |
32 | */ | 40 | */ |
diff --git a/arch/metag/include/asm/irq.h b/arch/metag/include/asm/irq.h index be0c8f3c5a5d..ad6bd0edbc3b 100644 --- a/arch/metag/include/asm/irq.h +++ b/arch/metag/include/asm/irq.h | |||
@@ -17,6 +17,7 @@ struct pt_regs; | |||
17 | 17 | ||
18 | int tbisig_map(unsigned int hw); | 18 | int tbisig_map(unsigned int hw); |
19 | extern void do_IRQ(int irq, struct pt_regs *regs); | 19 | extern void do_IRQ(int irq, struct pt_regs *regs); |
20 | extern void init_IRQ(void); | ||
20 | 21 | ||
21 | #ifdef CONFIG_METAG_SUSPEND_MEM | 22 | #ifdef CONFIG_METAG_SUSPEND_MEM |
22 | int traps_save_context(void); | 23 | int traps_save_context(void); |
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h index 9b029a7911c3..f16477d1f571 100644 --- a/arch/metag/include/asm/processor.h +++ b/arch/metag/include/asm/processor.h | |||
@@ -199,4 +199,6 @@ extern void (*soc_halt)(void); | |||
199 | extern void show_trace(struct task_struct *tsk, unsigned long *sp, | 199 | extern void show_trace(struct task_struct *tsk, unsigned long *sp, |
200 | struct pt_regs *regs); | 200 | struct pt_regs *regs); |
201 | 201 | ||
202 | extern const struct seq_operations cpuinfo_op; | ||
203 | |||
202 | #endif | 204 | #endif |
diff --git a/arch/metag/kernel/cachepart.c b/arch/metag/kernel/cachepart.c index 954548b1bea8..0a2385fa2a1d 100644 --- a/arch/metag/kernel/cachepart.c +++ b/arch/metag/kernel/cachepart.c | |||
@@ -100,22 +100,23 @@ void check_for_cache_aliasing(int thread_id) | |||
100 | thread_cache_size = | 100 | thread_cache_size = |
101 | get_thread_cache_size(cache_type, thread_id); | 101 | get_thread_cache_size(cache_type, thread_id); |
102 | if (thread_cache_size < 0) | 102 | if (thread_cache_size < 0) |
103 | pr_emerg("Can't read %s cache size", \ | 103 | pr_emerg("Can't read %s cache size\n", |
104 | cache_type ? "DCACHE" : "ICACHE"); | 104 | cache_type ? "DCACHE" : "ICACHE"); |
105 | else if (thread_cache_size == 0) | 105 | else if (thread_cache_size == 0) |
106 | /* Cache is off. No need to check for aliasing */ | 106 | /* Cache is off. No need to check for aliasing */ |
107 | continue; | 107 | continue; |
108 | if (thread_cache_size / CACHE_ASSOCIATIVITY > PAGE_SIZE) { | 108 | if (thread_cache_size / CACHE_ASSOCIATIVITY > PAGE_SIZE) { |
109 | pr_emerg("Cache aliasing detected in %s on Thread %d", | 109 | pr_emerg("Potential cache aliasing detected in %s on Thread %d\n", |
110 | cache_type ? "DCACHE" : "ICACHE", thread_id); | 110 | cache_type ? "DCACHE" : "ICACHE", thread_id); |
111 | pr_warn("Total %s size: %u bytes", | 111 | pr_warn("Total %s size: %u bytes\n", |
112 | cache_type ? "DCACHE" : "ICACHE ", | 112 | cache_type ? "DCACHE" : "ICACHE", |
113 | cache_type ? get_dcache_size() | 113 | cache_type ? get_dcache_size() |
114 | : get_icache_size()); | 114 | : get_icache_size()); |
115 | pr_warn("Thread %s size: %d bytes", | 115 | pr_warn("Thread %s size: %d bytes\n", |
116 | cache_type ? "CACHE" : "ICACHE", | 116 | cache_type ? "CACHE" : "ICACHE", |
117 | thread_cache_size); | 117 | thread_cache_size); |
118 | pr_warn("Page Size: %lu bytes", PAGE_SIZE); | 118 | pr_warn("Page Size: %lu bytes\n", PAGE_SIZE); |
119 | panic("Potential cache aliasing detected"); | ||
119 | } | 120 | } |
120 | } | 121 | } |
121 | } | 122 | } |
diff --git a/arch/metag/kernel/clock.c b/arch/metag/kernel/clock.c index defc84056f18..6339c9c6d0ab 100644 --- a/arch/metag/kernel/clock.c +++ b/arch/metag/kernel/clock.c | |||
@@ -8,8 +8,10 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/clk.h> | ||
11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
12 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/of.h> | ||
13 | 15 | ||
14 | #include <asm/param.h> | 16 | #include <asm/param.h> |
15 | #include <asm/clock.h> | 17 | #include <asm/clock.h> |
@@ -34,8 +36,63 @@ static unsigned long get_core_freq_default(void) | |||
34 | #endif | 36 | #endif |
35 | } | 37 | } |
36 | 38 | ||
39 | static struct clk *clk_core; | ||
40 | |||
41 | /* Clk based get_core_freq callback. */ | ||
42 | static unsigned long get_core_freq_clk(void) | ||
43 | { | ||
44 | return clk_get_rate(clk_core); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * init_metag_core_clock() - Set up core clock from devicetree. | ||
49 | * | ||
50 | * Checks to see if a "core" clock is provided in the device tree, and overrides | ||
51 | * the get_core_freq callback to use it. | ||
52 | */ | ||
53 | static void __init init_metag_core_clock(void) | ||
54 | { | ||
55 | /* | ||
56 | * See if a core clock is provided by the devicetree (and | ||
57 | * registered by the init callback above). | ||
58 | */ | ||
59 | struct device_node *node; | ||
60 | node = of_find_compatible_node(NULL, NULL, "img,meta"); | ||
61 | if (!node) { | ||
62 | pr_warn("%s: no compatible img,meta DT node found\n", | ||
63 | __func__); | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | clk_core = of_clk_get_by_name(node, "core"); | ||
68 | if (IS_ERR(clk_core)) { | ||
69 | pr_warn("%s: no core clock found in DT\n", | ||
70 | __func__); | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Override the core frequency callback to use | ||
76 | * this clk. | ||
77 | */ | ||
78 | _meta_clock.get_core_freq = get_core_freq_clk; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * init_metag_clocks() - Set up clocks from devicetree. | ||
83 | * | ||
84 | * Set up important clocks from device tree. In particular any needed for clock | ||
85 | * sources. | ||
86 | */ | ||
87 | void __init init_metag_clocks(void) | ||
88 | { | ||
89 | init_metag_core_clock(); | ||
90 | |||
91 | pr_info("Core clock frequency: %lu Hz\n", get_coreclock()); | ||
92 | } | ||
93 | |||
37 | /** | 94 | /** |
38 | * setup_meta_clocks() - Set up the Meta clock. | 95 | * setup_meta_clocks() - Early set up of the Meta clock. |
39 | * @desc: Clock descriptor usually provided by machine description | 96 | * @desc: Clock descriptor usually provided by machine description |
40 | * | 97 | * |
41 | * Ensures all callbacks are valid. | 98 | * Ensures all callbacks are valid. |
diff --git a/arch/metag/kernel/irq.c b/arch/metag/kernel/irq.c index 87707efeb0a3..2a2c9d55187e 100644 --- a/arch/metag/kernel/irq.c +++ b/arch/metag/kernel/irq.c | |||
@@ -25,7 +25,7 @@ static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; | |||
25 | static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; | 25 | static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | struct irq_domain *root_domain; | 28 | static struct irq_domain *root_domain; |
29 | 29 | ||
30 | static unsigned int startup_meta_irq(struct irq_data *data) | 30 | static unsigned int startup_meta_irq(struct irq_data *data) |
31 | { | 31 | { |
@@ -279,11 +279,12 @@ static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) | |||
279 | { | 279 | { |
280 | struct irq_desc *desc = irq_to_desc(irq); | 280 | struct irq_desc *desc = irq_to_desc(irq); |
281 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 281 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
282 | unsigned long flags; | ||
282 | 283 | ||
283 | raw_spin_lock_irq(&desc->lock); | 284 | raw_spin_lock_irqsave(&desc->lock, flags); |
284 | if (chip->irq_set_affinity) | 285 | if (chip->irq_set_affinity) |
285 | chip->irq_set_affinity(data, cpumask_of(cpu), false); | 286 | chip->irq_set_affinity(data, cpumask_of(cpu), false); |
286 | raw_spin_unlock_irq(&desc->lock); | 287 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
287 | } | 288 | } |
288 | 289 | ||
289 | /* | 290 | /* |
diff --git a/arch/metag/kernel/kick.c b/arch/metag/kernel/kick.c index 50fcbec98cd2..beb377621322 100644 --- a/arch/metag/kernel/kick.c +++ b/arch/metag/kernel/kick.c | |||
@@ -26,6 +26,8 @@ | |||
26 | * pass it as an argument. | 26 | * pass it as an argument. |
27 | */ | 27 | */ |
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <linux/hardirq.h> | ||
30 | #include <linux/irq.h> | ||
29 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
30 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
31 | #include <linux/types.h> | 33 | #include <linux/types.h> |
@@ -66,6 +68,7 @@ EXPORT_SYMBOL(kick_unregister_func); | |||
66 | TBIRES | 68 | TBIRES |
67 | kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI) | 69 | kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI) |
68 | { | 70 | { |
71 | struct pt_regs *old_regs; | ||
69 | struct kick_irq_handler *kh; | 72 | struct kick_irq_handler *kh; |
70 | struct list_head *lh; | 73 | struct list_head *lh; |
71 | int handled = 0; | 74 | int handled = 0; |
@@ -79,6 +82,9 @@ kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI) | |||
79 | 82 | ||
80 | trace_hardirqs_off(); | 83 | trace_hardirqs_off(); |
81 | 84 | ||
85 | old_regs = set_irq_regs((struct pt_regs *)State.Sig.pCtx); | ||
86 | irq_enter(); | ||
87 | |||
82 | /* | 88 | /* |
83 | * There is no need to disable interrupts here because we | 89 | * There is no need to disable interrupts here because we |
84 | * can't nest KICK interrupts in a KICK interrupt handler. | 90 | * can't nest KICK interrupts in a KICK interrupt handler. |
@@ -97,5 +103,8 @@ kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI) | |||
97 | 103 | ||
98 | WARN_ON(!handled); | 104 | WARN_ON(!handled); |
99 | 105 | ||
106 | irq_exit(); | ||
107 | set_irq_regs(old_regs); | ||
108 | |||
100 | return tail_end(ret); | 109 | return tail_end(ret); |
101 | } | 110 | } |
diff --git a/arch/metag/kernel/metag_ksyms.c b/arch/metag/kernel/metag_ksyms.c index ec872ef14eb1..215c94ad63ac 100644 --- a/arch/metag/kernel/metag_ksyms.c +++ b/arch/metag/kernel/metag_ksyms.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include <linux/export.h> | 1 | #include <linux/export.h> |
2 | #include <linux/types.h> | ||
2 | 3 | ||
4 | #include <asm/checksum.h> | ||
3 | #include <asm/div64.h> | 5 | #include <asm/div64.h> |
4 | #include <asm/ftrace.h> | 6 | #include <asm/ftrace.h> |
5 | #include <asm/page.h> | 7 | #include <asm/page.h> |
@@ -15,6 +17,9 @@ EXPORT_SYMBOL(max_pfn); | |||
15 | EXPORT_SYMBOL(min_low_pfn); | 17 | EXPORT_SYMBOL(min_low_pfn); |
16 | #endif | 18 | #endif |
17 | 19 | ||
20 | /* Network checksum functions */ | ||
21 | EXPORT_SYMBOL(csum_partial); | ||
22 | |||
18 | /* TBI symbols */ | 23 | /* TBI symbols */ |
19 | EXPORT_SYMBOL(__TBI); | 24 | EXPORT_SYMBOL(__TBI); |
20 | EXPORT_SYMBOL(__TBIFindSeg); | 25 | EXPORT_SYMBOL(__TBIFindSeg); |
diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c index 4f5726f1a55b..c396cd0b425f 100644 --- a/arch/metag/kernel/setup.c +++ b/arch/metag/kernel/setup.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/memblock.h> | 20 | #include <linux/memblock.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/of_fdt.h> | 22 | #include <linux/of_fdt.h> |
23 | #include <linux/of_platform.h> | ||
23 | #include <linux/pfn.h> | 24 | #include <linux/pfn.h> |
24 | #include <linux/root_dev.h> | 25 | #include <linux/root_dev.h> |
25 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
@@ -424,6 +425,9 @@ static int __init customize_machine(void) | |||
424 | /* customizes platform devices, or adds new ones */ | 425 | /* customizes platform devices, or adds new ones */ |
425 | if (machine_desc->init_machine) | 426 | if (machine_desc->init_machine) |
426 | machine_desc->init_machine(); | 427 | machine_desc->init_machine(); |
428 | else | ||
429 | of_platform_populate(NULL, of_default_bus_match_table, NULL, | ||
430 | NULL); | ||
427 | return 0; | 431 | return 0; |
428 | } | 432 | } |
429 | arch_initcall(customize_machine); | 433 | arch_initcall(customize_machine); |
@@ -587,20 +591,20 @@ PTBI pTBI_get(unsigned int cpu) | |||
587 | EXPORT_SYMBOL(pTBI_get); | 591 | EXPORT_SYMBOL(pTBI_get); |
588 | 592 | ||
589 | #if defined(CONFIG_METAG_DSP) && defined(CONFIG_METAG_FPU) | 593 | #if defined(CONFIG_METAG_DSP) && defined(CONFIG_METAG_FPU) |
590 | char capabilites[] = "dsp fpu"; | 594 | static char capabilities[] = "dsp fpu"; |
591 | #elif defined(CONFIG_METAG_DSP) | 595 | #elif defined(CONFIG_METAG_DSP) |
592 | char capabilites[] = "dsp"; | 596 | static char capabilities[] = "dsp"; |
593 | #elif defined(CONFIG_METAG_FPU) | 597 | #elif defined(CONFIG_METAG_FPU) |
594 | char capabilites[] = "fpu"; | 598 | static char capabilities[] = "fpu"; |
595 | #else | 599 | #else |
596 | char capabilites[] = ""; | 600 | static char capabilities[] = ""; |
597 | #endif | 601 | #endif |
598 | 602 | ||
599 | static struct ctl_table caps_kern_table[] = { | 603 | static struct ctl_table caps_kern_table[] = { |
600 | { | 604 | { |
601 | .procname = "capabilities", | 605 | .procname = "capabilities", |
602 | .data = capabilites, | 606 | .data = capabilities, |
603 | .maxlen = sizeof(capabilites), | 607 | .maxlen = sizeof(capabilities), |
604 | .mode = 0444, | 608 | .mode = 0444, |
605 | .proc_handler = proc_dostring, | 609 | .proc_handler = proc_dostring, |
606 | }, | 610 | }, |
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c index f443ec9a7cbe..e413875cf6d2 100644 --- a/arch/metag/kernel/smp.c +++ b/arch/metag/kernel/smp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/atomic.h> | 10 | #include <linux/atomic.h> |
11 | #include <linux/completion.h> | ||
11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
@@ -62,6 +63,8 @@ static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { | |||
62 | 63 | ||
63 | static DEFINE_SPINLOCK(boot_lock); | 64 | static DEFINE_SPINLOCK(boot_lock); |
64 | 65 | ||
66 | static DECLARE_COMPLETION(cpu_running); | ||
67 | |||
65 | /* | 68 | /* |
66 | * "thread" is assumed to be a valid Meta hardware thread ID. | 69 | * "thread" is assumed to be a valid Meta hardware thread ID. |
67 | */ | 70 | */ |
@@ -235,20 +238,12 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
235 | */ | 238 | */ |
236 | ret = boot_secondary(thread, idle); | 239 | ret = boot_secondary(thread, idle); |
237 | if (ret == 0) { | 240 | if (ret == 0) { |
238 | unsigned long timeout; | ||
239 | |||
240 | /* | 241 | /* |
241 | * CPU was successfully started, wait for it | 242 | * CPU was successfully started, wait for it |
242 | * to come online or time out. | 243 | * to come online or time out. |
243 | */ | 244 | */ |
244 | timeout = jiffies + HZ; | 245 | wait_for_completion_timeout(&cpu_running, |
245 | while (time_before(jiffies, timeout)) { | 246 | msecs_to_jiffies(1000)); |
246 | if (cpu_online(cpu)) | ||
247 | break; | ||
248 | |||
249 | udelay(10); | ||
250 | barrier(); | ||
251 | } | ||
252 | 247 | ||
253 | if (!cpu_online(cpu)) | 248 | if (!cpu_online(cpu)) |
254 | ret = -EIO; | 249 | ret = -EIO; |
@@ -276,7 +271,6 @@ static DECLARE_COMPLETION(cpu_killed); | |||
276 | int __cpuexit __cpu_disable(void) | 271 | int __cpuexit __cpu_disable(void) |
277 | { | 272 | { |
278 | unsigned int cpu = smp_processor_id(); | 273 | unsigned int cpu = smp_processor_id(); |
279 | struct task_struct *p; | ||
280 | 274 | ||
281 | /* | 275 | /* |
282 | * Take this CPU offline. Once we clear this, we can't return, | 276 | * Take this CPU offline. Once we clear this, we can't return, |
@@ -296,12 +290,7 @@ int __cpuexit __cpu_disable(void) | |||
296 | flush_cache_all(); | 290 | flush_cache_all(); |
297 | local_flush_tlb_all(); | 291 | local_flush_tlb_all(); |
298 | 292 | ||
299 | read_lock(&tasklist_lock); | 293 | clear_tasks_mm_cpumask(cpu); |
300 | for_each_process(p) { | ||
301 | if (p->mm) | ||
302 | cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); | ||
303 | } | ||
304 | read_unlock(&tasklist_lock); | ||
305 | 294 | ||
306 | return 0; | 295 | return 0; |
307 | } | 296 | } |
@@ -385,12 +374,7 @@ asmlinkage void secondary_start_kernel(void) | |||
385 | 374 | ||
386 | setup_priv(); | 375 | setup_priv(); |
387 | 376 | ||
388 | /* | ||
389 | * Enable local interrupts. | ||
390 | */ | ||
391 | tbi_startup_interrupt(TBID_SIGNUM_TRT); | ||
392 | notify_cpu_starting(cpu); | 377 | notify_cpu_starting(cpu); |
393 | local_irq_enable(); | ||
394 | 378 | ||
395 | pr_info("CPU%u (thread %u): Booted secondary processor\n", | 379 | pr_info("CPU%u (thread %u): Booted secondary processor\n", |
396 | cpu, cpu_2_hwthread_id[cpu]); | 380 | cpu, cpu_2_hwthread_id[cpu]); |
@@ -402,12 +386,13 @@ asmlinkage void secondary_start_kernel(void) | |||
402 | * OK, now it's safe to let the boot CPU continue | 386 | * OK, now it's safe to let the boot CPU continue |
403 | */ | 387 | */ |
404 | set_cpu_online(cpu, true); | 388 | set_cpu_online(cpu, true); |
389 | complete(&cpu_running); | ||
405 | 390 | ||
406 | /* | 391 | /* |
407 | * Check for cache aliasing. | 392 | * Enable local interrupts. |
408 | * Preemption is disabled | ||
409 | */ | 393 | */ |
410 | check_for_cache_aliasing(cpu); | 394 | tbi_startup_interrupt(TBID_SIGNUM_TRT); |
395 | local_irq_enable(); | ||
411 | 396 | ||
412 | /* | 397 | /* |
413 | * OK, it's off to the idle thread for us | 398 | * OK, it's off to the idle thread for us |
diff --git a/arch/metag/kernel/time.c b/arch/metag/kernel/time.c index 17dc10733b2f..f1c8c53dace7 100644 --- a/arch/metag/kernel/time.c +++ b/arch/metag/kernel/time.c | |||
@@ -5,11 +5,21 @@ | |||
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/init.h> | ||
9 | |||
10 | #include <clocksource/metag_generic.h> | 8 | #include <clocksource/metag_generic.h> |
9 | #include <linux/clk-provider.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <asm/clock.h> | ||
11 | 12 | ||
12 | void __init time_init(void) | 13 | void __init time_init(void) |
13 | { | 14 | { |
15 | #ifdef CONFIG_COMMON_CLK | ||
16 | /* Init clocks from device tree */ | ||
17 | of_clk_init(NULL); | ||
18 | #endif | ||
19 | |||
20 | /* Init meta clocks, particularly the core clock */ | ||
21 | init_metag_clocks(); | ||
22 | |||
23 | /* Set up the timer clock sources */ | ||
14 | metag_generic_timer_init(); | 24 | metag_generic_timer_init(); |
15 | } | 25 | } |
diff --git a/arch/metag/kernel/traps.c b/arch/metag/kernel/traps.c index 2ceeaae5b199..c00ade0228ef 100644 --- a/arch/metag/kernel/traps.c +++ b/arch/metag/kernel/traps.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/siginfo.h> | 33 | #include <asm/siginfo.h> |
34 | #include <asm/traps.h> | 34 | #include <asm/traps.h> |
35 | #include <asm/hwthread.h> | 35 | #include <asm/hwthread.h> |
36 | #include <asm/setup.h> | ||
36 | #include <asm/switch.h> | 37 | #include <asm/switch.h> |
37 | #include <asm/user_gateway.h> | 38 | #include <asm/user_gateway.h> |
38 | #include <asm/syscall.h> | 39 | #include <asm/syscall.h> |
@@ -87,8 +88,8 @@ const char *trap_name(int trapno) | |||
87 | 88 | ||
88 | static DEFINE_SPINLOCK(die_lock); | 89 | static DEFINE_SPINLOCK(die_lock); |
89 | 90 | ||
90 | void die(const char *str, struct pt_regs *regs, long err, | 91 | void __noreturn die(const char *str, struct pt_regs *regs, |
91 | unsigned long addr) | 92 | long err, unsigned long addr) |
92 | { | 93 | { |
93 | static int die_counter; | 94 | static int die_counter; |
94 | 95 | ||
diff --git a/arch/metag/lib/checksum.c b/arch/metag/lib/checksum.c index 44d2e1913560..5d6a98a05e9d 100644 --- a/arch/metag/lib/checksum.c +++ b/arch/metag/lib/checksum.c | |||
@@ -124,7 +124,6 @@ __wsum csum_partial(const void *buff, int len, __wsum wsum) | |||
124 | result += 1; | 124 | result += 1; |
125 | return (__force __wsum)result; | 125 | return (__force __wsum)result; |
126 | } | 126 | } |
127 | EXPORT_SYMBOL(csum_partial); | ||
128 | 127 | ||
129 | /* | 128 | /* |
130 | * this routine is used for miscellaneous IP-like checksums, mainly | 129 | * this routine is used for miscellaneous IP-like checksums, mainly |
diff --git a/arch/metag/mm/cache.c b/arch/metag/mm/cache.c index b5d3b2e7c160..a62285284ab8 100644 --- a/arch/metag/mm/cache.c +++ b/arch/metag/mm/cache.c | |||
@@ -45,7 +45,7 @@ static volatile u32 lnkget_testdata[16] __initdata __aligned(64); | |||
45 | 45 | ||
46 | #define LNKGET_CONSTANT 0xdeadbeef | 46 | #define LNKGET_CONSTANT 0xdeadbeef |
47 | 47 | ||
48 | void __init metag_lnkget_probe(void) | 48 | static void __init metag_lnkget_probe(void) |
49 | { | 49 | { |
50 | int temp; | 50 | int temp; |
51 | long flags; | 51 | long flags; |
diff --git a/arch/mips/include/asm/mach-jz4740/dma.h b/arch/mips/include/asm/mach-jz4740/dma.h index 98b4e7c0dbae..509cd5828044 100644 --- a/arch/mips/include/asm/mach-jz4740/dma.h +++ b/arch/mips/include/asm/mach-jz4740/dma.h | |||
@@ -16,8 +16,6 @@ | |||
16 | #ifndef __ASM_MACH_JZ4740_DMA_H__ | 16 | #ifndef __ASM_MACH_JZ4740_DMA_H__ |
17 | #define __ASM_MACH_JZ4740_DMA_H__ | 17 | #define __ASM_MACH_JZ4740_DMA_H__ |
18 | 18 | ||
19 | struct jz4740_dma_chan; | ||
20 | |||
21 | enum jz4740_dma_request_type { | 19 | enum jz4740_dma_request_type { |
22 | JZ4740_DMA_TYPE_AUTO_REQUEST = 8, | 20 | JZ4740_DMA_TYPE_AUTO_REQUEST = 8, |
23 | JZ4740_DMA_TYPE_UART_TRANSMIT = 20, | 21 | JZ4740_DMA_TYPE_UART_TRANSMIT = 20, |
@@ -33,58 +31,4 @@ enum jz4740_dma_request_type { | |||
33 | JZ4740_DMA_TYPE_SLCD = 30, | 31 | JZ4740_DMA_TYPE_SLCD = 30, |
34 | }; | 32 | }; |
35 | 33 | ||
36 | enum jz4740_dma_width { | ||
37 | JZ4740_DMA_WIDTH_32BIT = 0, | ||
38 | JZ4740_DMA_WIDTH_8BIT = 1, | ||
39 | JZ4740_DMA_WIDTH_16BIT = 2, | ||
40 | }; | ||
41 | |||
42 | enum jz4740_dma_transfer_size { | ||
43 | JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0, | ||
44 | JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1, | ||
45 | JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2, | ||
46 | JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3, | ||
47 | JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4, | ||
48 | }; | ||
49 | |||
50 | enum jz4740_dma_flags { | ||
51 | JZ4740_DMA_SRC_AUTOINC = 0x2, | ||
52 | JZ4740_DMA_DST_AUTOINC = 0x1, | ||
53 | }; | ||
54 | |||
55 | enum jz4740_dma_mode { | ||
56 | JZ4740_DMA_MODE_SINGLE = 0, | ||
57 | JZ4740_DMA_MODE_BLOCK = 1, | ||
58 | }; | ||
59 | |||
60 | struct jz4740_dma_config { | ||
61 | enum jz4740_dma_width src_width; | ||
62 | enum jz4740_dma_width dst_width; | ||
63 | enum jz4740_dma_transfer_size transfer_size; | ||
64 | enum jz4740_dma_request_type request_type; | ||
65 | enum jz4740_dma_flags flags; | ||
66 | enum jz4740_dma_mode mode; | ||
67 | }; | ||
68 | |||
69 | typedef void (*jz4740_dma_complete_callback_t)(struct jz4740_dma_chan *, int, void *); | ||
70 | |||
71 | struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name); | ||
72 | void jz4740_dma_free(struct jz4740_dma_chan *dma); | ||
73 | |||
74 | void jz4740_dma_configure(struct jz4740_dma_chan *dma, | ||
75 | const struct jz4740_dma_config *config); | ||
76 | |||
77 | |||
78 | void jz4740_dma_enable(struct jz4740_dma_chan *dma); | ||
79 | void jz4740_dma_disable(struct jz4740_dma_chan *dma); | ||
80 | |||
81 | void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src); | ||
82 | void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst); | ||
83 | void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count); | ||
84 | |||
85 | uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma); | ||
86 | |||
87 | void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma, | ||
88 | jz4740_dma_complete_callback_t cb); | ||
89 | |||
90 | #endif /* __ASM_JZ4740_DMA_H__ */ | 34 | #endif /* __ASM_JZ4740_DMA_H__ */ |
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index 72cfebdb5a47..05988c2d6565 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h | |||
@@ -32,6 +32,7 @@ extern struct platform_device jz4740_codec_device; | |||
32 | extern struct platform_device jz4740_adc_device; | 32 | extern struct platform_device jz4740_adc_device; |
33 | extern struct platform_device jz4740_wdt_device; | 33 | extern struct platform_device jz4740_wdt_device; |
34 | extern struct platform_device jz4740_pwm_device; | 34 | extern struct platform_device jz4740_pwm_device; |
35 | extern struct platform_device jz4740_dma_device; | ||
35 | 36 | ||
36 | void jz4740_serial_device_register(void); | 37 | void jz4740_serial_device_register(void); |
37 | 38 | ||
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index 63bad0e491d0..28e5535dfa9e 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | # Object file lists. | 5 | # Object file lists. |
6 | 6 | ||
7 | obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ | 7 | obj-y += prom.o irq.o time.o reset.o setup.o \ |
8 | gpio.o clock.o platform.o timer.o serial.o | 8 | gpio.o clock.o platform.o timer.o serial.o |
9 | 9 | ||
10 | obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o | 10 | obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o |
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index be2b3deeef1d..8a5ec0eedeb0 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c | |||
@@ -438,6 +438,7 @@ static struct platform_device *jz_platform_devices[] __initdata = { | |||
438 | &jz4740_rtc_device, | 438 | &jz4740_rtc_device, |
439 | &jz4740_adc_device, | 439 | &jz4740_adc_device, |
440 | &jz4740_pwm_device, | 440 | &jz4740_pwm_device, |
441 | &jz4740_dma_device, | ||
441 | &qi_lb60_gpio_keys, | 442 | &qi_lb60_gpio_keys, |
442 | &qi_lb60_pwm_beeper, | 443 | &qi_lb60_pwm_beeper, |
443 | &qi_lb60_charger_device, | 444 | &qi_lb60_charger_device, |
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c index 484d38a0864f..1b5f55426cad 100644 --- a/arch/mips/jz4740/clock.c +++ b/arch/mips/jz4740/clock.c | |||
@@ -687,7 +687,7 @@ static struct clk jz4740_clock_simple_clks[] = { | |||
687 | [3] = { | 687 | [3] = { |
688 | .name = "dma", | 688 | .name = "dma", |
689 | .parent = &jz_clk_high_speed_peripheral.clk, | 689 | .parent = &jz_clk_high_speed_peripheral.clk, |
690 | .gate_bit = JZ_CLOCK_GATE_UART0, | 690 | .gate_bit = JZ_CLOCK_GATE_DMAC, |
691 | .ops = &jz_clk_simple_ops, | 691 | .ops = &jz_clk_simple_ops, |
692 | }, | 692 | }, |
693 | [4] = { | 693 | [4] = { |
diff --git a/arch/mips/jz4740/dma.c b/arch/mips/jz4740/dma.c deleted file mode 100644 index 317ec6fffb12..000000000000 --- a/arch/mips/jz4740/dma.c +++ /dev/null | |||
@@ -1,287 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC DMA support | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <linux/dma-mapping.h> | ||
22 | #include <asm/mach-jz4740/dma.h> | ||
23 | #include <asm/mach-jz4740/base.h> | ||
24 | |||
25 | #define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20) | ||
26 | #define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20) | ||
27 | #define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20) | ||
28 | #define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20) | ||
29 | #define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20) | ||
30 | #define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20) | ||
31 | #define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20) | ||
32 | |||
33 | #define JZ_REG_DMA_CTRL 0x300 | ||
34 | #define JZ_REG_DMA_IRQ 0x304 | ||
35 | #define JZ_REG_DMA_DOORBELL 0x308 | ||
36 | #define JZ_REG_DMA_DOORBELL_SET 0x30C | ||
37 | |||
38 | #define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31) | ||
39 | #define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6) | ||
40 | #define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4) | ||
41 | #define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3) | ||
42 | #define JZ_DMA_STATUS_CTRL_HALT BIT(2) | ||
43 | #define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1) | ||
44 | #define JZ_DMA_STATUS_CTRL_ENABLE BIT(0) | ||
45 | |||
46 | #define JZ_DMA_CMD_SRC_INC BIT(23) | ||
47 | #define JZ_DMA_CMD_DST_INC BIT(22) | ||
48 | #define JZ_DMA_CMD_RDIL_MASK (0xf << 16) | ||
49 | #define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14) | ||
50 | #define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12) | ||
51 | #define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8) | ||
52 | #define JZ_DMA_CMD_BLOCK_MODE BIT(7) | ||
53 | #define JZ_DMA_CMD_DESC_VALID BIT(4) | ||
54 | #define JZ_DMA_CMD_DESC_VALID_MODE BIT(3) | ||
55 | #define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2) | ||
56 | #define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1) | ||
57 | #define JZ_DMA_CMD_LINK_ENABLE BIT(0) | ||
58 | |||
59 | #define JZ_DMA_CMD_FLAGS_OFFSET 22 | ||
60 | #define JZ_DMA_CMD_RDIL_OFFSET 16 | ||
61 | #define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14 | ||
62 | #define JZ_DMA_CMD_DST_WIDTH_OFFSET 12 | ||
63 | #define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8 | ||
64 | #define JZ_DMA_CMD_MODE_OFFSET 7 | ||
65 | |||
66 | #define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8) | ||
67 | #define JZ_DMA_CTRL_HALT BIT(3) | ||
68 | #define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2) | ||
69 | #define JZ_DMA_CTRL_ENABLE BIT(0) | ||
70 | |||
71 | |||
72 | static void __iomem *jz4740_dma_base; | ||
73 | static spinlock_t jz4740_dma_lock; | ||
74 | |||
75 | static inline uint32_t jz4740_dma_read(size_t reg) | ||
76 | { | ||
77 | return readl(jz4740_dma_base + reg); | ||
78 | } | ||
79 | |||
80 | static inline void jz4740_dma_write(size_t reg, uint32_t val) | ||
81 | { | ||
82 | writel(val, jz4740_dma_base + reg); | ||
83 | } | ||
84 | |||
85 | static inline void jz4740_dma_write_mask(size_t reg, uint32_t val, uint32_t mask) | ||
86 | { | ||
87 | uint32_t val2; | ||
88 | val2 = jz4740_dma_read(reg); | ||
89 | val2 &= ~mask; | ||
90 | val2 |= val; | ||
91 | jz4740_dma_write(reg, val2); | ||
92 | } | ||
93 | |||
94 | struct jz4740_dma_chan { | ||
95 | unsigned int id; | ||
96 | void *dev; | ||
97 | const char *name; | ||
98 | |||
99 | enum jz4740_dma_flags flags; | ||
100 | uint32_t transfer_shift; | ||
101 | |||
102 | jz4740_dma_complete_callback_t complete_cb; | ||
103 | |||
104 | unsigned used:1; | ||
105 | }; | ||
106 | |||
107 | #define JZ4740_DMA_CHANNEL(_id) { .id = _id } | ||
108 | |||
109 | struct jz4740_dma_chan jz4740_dma_channels[] = { | ||
110 | JZ4740_DMA_CHANNEL(0), | ||
111 | JZ4740_DMA_CHANNEL(1), | ||
112 | JZ4740_DMA_CHANNEL(2), | ||
113 | JZ4740_DMA_CHANNEL(3), | ||
114 | JZ4740_DMA_CHANNEL(4), | ||
115 | JZ4740_DMA_CHANNEL(5), | ||
116 | }; | ||
117 | |||
118 | struct jz4740_dma_chan *jz4740_dma_request(void *dev, const char *name) | ||
119 | { | ||
120 | unsigned int i; | ||
121 | struct jz4740_dma_chan *dma = NULL; | ||
122 | |||
123 | spin_lock(&jz4740_dma_lock); | ||
124 | |||
125 | for (i = 0; i < ARRAY_SIZE(jz4740_dma_channels); ++i) { | ||
126 | if (!jz4740_dma_channels[i].used) { | ||
127 | dma = &jz4740_dma_channels[i]; | ||
128 | dma->used = 1; | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | spin_unlock(&jz4740_dma_lock); | ||
134 | |||
135 | if (!dma) | ||
136 | return NULL; | ||
137 | |||
138 | dma->dev = dev; | ||
139 | dma->name = name; | ||
140 | |||
141 | return dma; | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(jz4740_dma_request); | ||
144 | |||
145 | void jz4740_dma_configure(struct jz4740_dma_chan *dma, | ||
146 | const struct jz4740_dma_config *config) | ||
147 | { | ||
148 | uint32_t cmd; | ||
149 | |||
150 | switch (config->transfer_size) { | ||
151 | case JZ4740_DMA_TRANSFER_SIZE_2BYTE: | ||
152 | dma->transfer_shift = 1; | ||
153 | break; | ||
154 | case JZ4740_DMA_TRANSFER_SIZE_4BYTE: | ||
155 | dma->transfer_shift = 2; | ||
156 | break; | ||
157 | case JZ4740_DMA_TRANSFER_SIZE_16BYTE: | ||
158 | dma->transfer_shift = 4; | ||
159 | break; | ||
160 | case JZ4740_DMA_TRANSFER_SIZE_32BYTE: | ||
161 | dma->transfer_shift = 5; | ||
162 | break; | ||
163 | default: | ||
164 | dma->transfer_shift = 0; | ||
165 | break; | ||
166 | } | ||
167 | |||
168 | cmd = config->flags << JZ_DMA_CMD_FLAGS_OFFSET; | ||
169 | cmd |= config->src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET; | ||
170 | cmd |= config->dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET; | ||
171 | cmd |= config->transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET; | ||
172 | cmd |= config->mode << JZ_DMA_CMD_MODE_OFFSET; | ||
173 | cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE; | ||
174 | |||
175 | jz4740_dma_write(JZ_REG_DMA_CMD(dma->id), cmd); | ||
176 | jz4740_dma_write(JZ_REG_DMA_STATUS_CTRL(dma->id), 0); | ||
177 | jz4740_dma_write(JZ_REG_DMA_REQ_TYPE(dma->id), config->request_type); | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(jz4740_dma_configure); | ||
180 | |||
181 | void jz4740_dma_set_src_addr(struct jz4740_dma_chan *dma, dma_addr_t src) | ||
182 | { | ||
183 | jz4740_dma_write(JZ_REG_DMA_SRC_ADDR(dma->id), src); | ||
184 | } | ||
185 | EXPORT_SYMBOL_GPL(jz4740_dma_set_src_addr); | ||
186 | |||
187 | void jz4740_dma_set_dst_addr(struct jz4740_dma_chan *dma, dma_addr_t dst) | ||
188 | { | ||
189 | jz4740_dma_write(JZ_REG_DMA_DST_ADDR(dma->id), dst); | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(jz4740_dma_set_dst_addr); | ||
192 | |||
193 | void jz4740_dma_set_transfer_count(struct jz4740_dma_chan *dma, uint32_t count) | ||
194 | { | ||
195 | count >>= dma->transfer_shift; | ||
196 | jz4740_dma_write(JZ_REG_DMA_TRANSFER_COUNT(dma->id), count); | ||
197 | } | ||
198 | EXPORT_SYMBOL_GPL(jz4740_dma_set_transfer_count); | ||
199 | |||
200 | void jz4740_dma_set_complete_cb(struct jz4740_dma_chan *dma, | ||
201 | jz4740_dma_complete_callback_t cb) | ||
202 | { | ||
203 | dma->complete_cb = cb; | ||
204 | } | ||
205 | EXPORT_SYMBOL_GPL(jz4740_dma_set_complete_cb); | ||
206 | |||
207 | void jz4740_dma_free(struct jz4740_dma_chan *dma) | ||
208 | { | ||
209 | dma->dev = NULL; | ||
210 | dma->complete_cb = NULL; | ||
211 | dma->used = 0; | ||
212 | } | ||
213 | EXPORT_SYMBOL_GPL(jz4740_dma_free); | ||
214 | |||
215 | void jz4740_dma_enable(struct jz4740_dma_chan *dma) | ||
216 | { | ||
217 | jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), | ||
218 | JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE, | ||
219 | JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC | | ||
220 | JZ_DMA_STATUS_CTRL_ENABLE); | ||
221 | |||
222 | jz4740_dma_write_mask(JZ_REG_DMA_CTRL, | ||
223 | JZ_DMA_CTRL_ENABLE, | ||
224 | JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE); | ||
225 | } | ||
226 | EXPORT_SYMBOL_GPL(jz4740_dma_enable); | ||
227 | |||
228 | void jz4740_dma_disable(struct jz4740_dma_chan *dma) | ||
229 | { | ||
230 | jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0, | ||
231 | JZ_DMA_STATUS_CTRL_ENABLE); | ||
232 | } | ||
233 | EXPORT_SYMBOL_GPL(jz4740_dma_disable); | ||
234 | |||
235 | uint32_t jz4740_dma_get_residue(const struct jz4740_dma_chan *dma) | ||
236 | { | ||
237 | uint32_t residue; | ||
238 | residue = jz4740_dma_read(JZ_REG_DMA_TRANSFER_COUNT(dma->id)); | ||
239 | return residue << dma->transfer_shift; | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(jz4740_dma_get_residue); | ||
242 | |||
243 | static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma) | ||
244 | { | ||
245 | (void) jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id)); | ||
246 | |||
247 | jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0, | ||
248 | JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE); | ||
249 | |||
250 | if (dma->complete_cb) | ||
251 | dma->complete_cb(dma, 0, dma->dev); | ||
252 | } | ||
253 | |||
254 | static irqreturn_t jz4740_dma_irq(int irq, void *dev_id) | ||
255 | { | ||
256 | uint32_t irq_status; | ||
257 | unsigned int i; | ||
258 | |||
259 | irq_status = readl(jz4740_dma_base + JZ_REG_DMA_IRQ); | ||
260 | |||
261 | for (i = 0; i < 6; ++i) { | ||
262 | if (irq_status & (1 << i)) | ||
263 | jz4740_dma_chan_irq(&jz4740_dma_channels[i]); | ||
264 | } | ||
265 | |||
266 | return IRQ_HANDLED; | ||
267 | } | ||
268 | |||
269 | static int jz4740_dma_init(void) | ||
270 | { | ||
271 | unsigned int ret; | ||
272 | |||
273 | jz4740_dma_base = ioremap(JZ4740_DMAC_BASE_ADDR, 0x400); | ||
274 | |||
275 | if (!jz4740_dma_base) | ||
276 | return -EBUSY; | ||
277 | |||
278 | spin_lock_init(&jz4740_dma_lock); | ||
279 | |||
280 | ret = request_irq(JZ4740_IRQ_DMAC, jz4740_dma_irq, 0, "DMA", NULL); | ||
281 | |||
282 | if (ret) | ||
283 | printk(KERN_ERR "JZ4740 DMA: Failed to request irq: %d\n", ret); | ||
284 | |||
285 | return ret; | ||
286 | } | ||
287 | arch_initcall(jz4740_dma_init); | ||
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index e9348fd26a35..df65677f3d0b 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c | |||
@@ -329,3 +329,24 @@ struct platform_device jz4740_pwm_device = { | |||
329 | .name = "jz4740-pwm", | 329 | .name = "jz4740-pwm", |
330 | .id = -1, | 330 | .id = -1, |
331 | }; | 331 | }; |
332 | |||
333 | /* DMA */ | ||
334 | static struct resource jz4740_dma_resources[] = { | ||
335 | { | ||
336 | .start = JZ4740_DMAC_BASE_ADDR, | ||
337 | .end = JZ4740_DMAC_BASE_ADDR + 0x400 - 1, | ||
338 | .flags = IORESOURCE_MEM, | ||
339 | }, | ||
340 | { | ||
341 | .start = JZ4740_IRQ_DMAC, | ||
342 | .end = JZ4740_IRQ_DMAC, | ||
343 | .flags = IORESOURCE_IRQ, | ||
344 | }, | ||
345 | }; | ||
346 | |||
347 | struct platform_device jz4740_dma_device = { | ||
348 | .name = "jz4740-dma", | ||
349 | .id = -1, | ||
350 | .num_resources = ARRAY_SIZE(jz4740_dma_resources), | ||
351 | .resource = jz4740_dma_resources, | ||
352 | }; | ||
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c index 8c6dc42ecf65..9e5dfbcc00af 100644 --- a/arch/powerpc/platforms/cell/beat_interrupt.c +++ b/arch/powerpc/platforms/cell/beat_interrupt.c | |||
@@ -239,7 +239,7 @@ void __init beatic_init_IRQ(void) | |||
239 | ppc_md.get_irq = beatic_get_irq; | 239 | ppc_md.get_irq = beatic_get_irq; |
240 | 240 | ||
241 | /* Allocate an irq host */ | 241 | /* Allocate an irq host */ |
242 | beatic_host = irq_domain_add_nomap(NULL, 0, &beatic_pic_host_ops, NULL); | 242 | beatic_host = irq_domain_add_nomap(NULL, ~0, &beatic_pic_host_ops, NULL); |
243 | BUG_ON(beatic_host == NULL); | 243 | BUG_ON(beatic_host == NULL); |
244 | irq_set_default_host(beatic_host); | 244 | irq_set_default_host(beatic_host); |
245 | } | 245 | } |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 49c9f9501c21..5cbd4d67d5c4 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -192,7 +192,7 @@ static int psurge_secondary_ipi_init(void) | |||
192 | { | 192 | { |
193 | int rc = -ENOMEM; | 193 | int rc = -ENOMEM; |
194 | 194 | ||
195 | psurge_host = irq_domain_add_nomap(NULL, 0, &psurge_host_ops, NULL); | 195 | psurge_host = irq_domain_add_nomap(NULL, ~0, &psurge_host_ops, NULL); |
196 | 196 | ||
197 | if (psurge_host) | 197 | if (psurge_host) |
198 | psurge_secondary_virq = irq_create_direct_mapping(psurge_host); | 198 | psurge_secondary_virq = irq_create_direct_mapping(psurge_host); |
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index a3a0ed80f17c..7d6ba9db1be9 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile | |||
@@ -3,8 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | avx_supported := $(call as-instr,vpxor %xmm0$(comma)%xmm0$(comma)%xmm0,yes,no) | 5 | avx_supported := $(call as-instr,vpxor %xmm0$(comma)%xmm0$(comma)%xmm0,yes,no) |
6 | avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\ | ||
7 | $(comma)4)$(comma)%ymm2,yes,no) | ||
8 | 6 | ||
9 | obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o | 7 | obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o |
10 | obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o | 8 | obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o |
@@ -29,6 +27,7 @@ obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o | |||
29 | obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o | 27 | obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o |
30 | obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o | 28 | obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o |
31 | obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o | 29 | obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o |
30 | obj-$(CONFIG_CRYPTO_CRCT10DIF_PCLMUL) += crct10dif-pclmul.o | ||
32 | 31 | ||
33 | # These modules require assembler to support AVX. | 32 | # These modules require assembler to support AVX. |
34 | ifeq ($(avx_supported),yes) | 33 | ifeq ($(avx_supported),yes) |
@@ -42,10 +41,8 @@ endif | |||
42 | 41 | ||
43 | # These modules require assembler to support AVX2. | 42 | # These modules require assembler to support AVX2. |
44 | ifeq ($(avx2_supported),yes) | 43 | ifeq ($(avx2_supported),yes) |
45 | obj-$(CONFIG_CRYPTO_BLOWFISH_AVX2_X86_64) += blowfish-avx2.o | ||
46 | obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64) += camellia-aesni-avx2.o | 44 | obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64) += camellia-aesni-avx2.o |
47 | obj-$(CONFIG_CRYPTO_SERPENT_AVX2_X86_64) += serpent-avx2.o | 45 | obj-$(CONFIG_CRYPTO_SERPENT_AVX2_X86_64) += serpent-avx2.o |
48 | obj-$(CONFIG_CRYPTO_TWOFISH_AVX2_X86_64) += twofish-avx2.o | ||
49 | endif | 46 | endif |
50 | 47 | ||
51 | aes-i586-y := aes-i586-asm_32.o aes_glue.o | 48 | aes-i586-y := aes-i586-asm_32.o aes_glue.o |
@@ -73,10 +70,8 @@ ifeq ($(avx_supported),yes) | |||
73 | endif | 70 | endif |
74 | 71 | ||
75 | ifeq ($(avx2_supported),yes) | 72 | ifeq ($(avx2_supported),yes) |
76 | blowfish-avx2-y := blowfish-avx2-asm_64.o blowfish_avx2_glue.o | ||
77 | camellia-aesni-avx2-y := camellia-aesni-avx2-asm_64.o camellia_aesni_avx2_glue.o | 73 | camellia-aesni-avx2-y := camellia-aesni-avx2-asm_64.o camellia_aesni_avx2_glue.o |
78 | serpent-avx2-y := serpent-avx2-asm_64.o serpent_avx2_glue.o | 74 | serpent-avx2-y := serpent-avx2-asm_64.o serpent_avx2_glue.o |
79 | twofish-avx2-y := twofish-avx2-asm_64.o twofish_avx2_glue.o | ||
80 | endif | 75 | endif |
81 | 76 | ||
82 | aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o | 77 | aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o |
@@ -87,3 +82,4 @@ crc32c-intel-$(CONFIG_64BIT) += crc32c-pcl-intel-asm_64.o | |||
87 | crc32-pclmul-y := crc32-pclmul_asm.o crc32-pclmul_glue.o | 82 | crc32-pclmul-y := crc32-pclmul_asm.o crc32-pclmul_glue.o |
88 | sha256-ssse3-y := sha256-ssse3-asm.o sha256-avx-asm.o sha256-avx2-asm.o sha256_ssse3_glue.o | 83 | sha256-ssse3-y := sha256-ssse3-asm.o sha256-avx-asm.o sha256-avx2-asm.o sha256_ssse3_glue.o |
89 | sha512-ssse3-y := sha512-ssse3-asm.o sha512-avx-asm.o sha512-avx2-asm.o sha512_ssse3_glue.o | 84 | sha512-ssse3-y := sha512-ssse3-asm.o sha512-avx-asm.o sha512-avx2-asm.o sha512_ssse3_glue.o |
85 | crct10dif-pclmul-y := crct10dif-pcl-asm_64.o crct10dif-pclmul_glue.o | ||
diff --git a/arch/x86/crypto/blowfish-avx2-asm_64.S b/arch/x86/crypto/blowfish-avx2-asm_64.S deleted file mode 100644 index 784452e0d05d..000000000000 --- a/arch/x86/crypto/blowfish-avx2-asm_64.S +++ /dev/null | |||
@@ -1,449 +0,0 @@ | |||
1 | /* | ||
2 | * x86_64/AVX2 assembler optimized version of Blowfish | ||
3 | * | ||
4 | * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/linkage.h> | ||
14 | |||
15 | .file "blowfish-avx2-asm_64.S" | ||
16 | |||
17 | .data | ||
18 | .align 32 | ||
19 | |||
20 | .Lprefetch_mask: | ||
21 | .long 0*64 | ||
22 | .long 1*64 | ||
23 | .long 2*64 | ||
24 | .long 3*64 | ||
25 | .long 4*64 | ||
26 | .long 5*64 | ||
27 | .long 6*64 | ||
28 | .long 7*64 | ||
29 | |||
30 | .Lbswap32_mask: | ||
31 | .long 0x00010203 | ||
32 | .long 0x04050607 | ||
33 | .long 0x08090a0b | ||
34 | .long 0x0c0d0e0f | ||
35 | |||
36 | .Lbswap128_mask: | ||
37 | .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 | ||
38 | .Lbswap_iv_mask: | ||
39 | .byte 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0 | ||
40 | |||
41 | .text | ||
42 | /* structure of crypto context */ | ||
43 | #define p 0 | ||
44 | #define s0 ((16 + 2) * 4) | ||
45 | #define s1 ((16 + 2 + (1 * 256)) * 4) | ||
46 | #define s2 ((16 + 2 + (2 * 256)) * 4) | ||
47 | #define s3 ((16 + 2 + (3 * 256)) * 4) | ||
48 | |||
49 | /* register macros */ | ||
50 | #define CTX %rdi | ||
51 | #define RIO %rdx | ||
52 | |||
53 | #define RS0 %rax | ||
54 | #define RS1 %r8 | ||
55 | #define RS2 %r9 | ||
56 | #define RS3 %r10 | ||
57 | |||
58 | #define RLOOP %r11 | ||
59 | #define RLOOPd %r11d | ||
60 | |||
61 | #define RXr0 %ymm8 | ||
62 | #define RXr1 %ymm9 | ||
63 | #define RXr2 %ymm10 | ||
64 | #define RXr3 %ymm11 | ||
65 | #define RXl0 %ymm12 | ||
66 | #define RXl1 %ymm13 | ||
67 | #define RXl2 %ymm14 | ||
68 | #define RXl3 %ymm15 | ||
69 | |||
70 | /* temp regs */ | ||
71 | #define RT0 %ymm0 | ||
72 | #define RT0x %xmm0 | ||
73 | #define RT1 %ymm1 | ||
74 | #define RT1x %xmm1 | ||
75 | #define RIDX0 %ymm2 | ||
76 | #define RIDX1 %ymm3 | ||
77 | #define RIDX1x %xmm3 | ||
78 | #define RIDX2 %ymm4 | ||
79 | #define RIDX3 %ymm5 | ||
80 | |||
81 | /* vpgatherdd mask and '-1' */ | ||
82 | #define RNOT %ymm6 | ||
83 | |||
84 | /* byte mask, (-1 >> 24) */ | ||
85 | #define RBYTE %ymm7 | ||
86 | |||
87 | /*********************************************************************** | ||
88 | * 32-way AVX2 blowfish | ||
89 | ***********************************************************************/ | ||
90 | #define F(xl, xr) \ | ||
91 | vpsrld $24, xl, RIDX0; \ | ||
92 | vpsrld $16, xl, RIDX1; \ | ||
93 | vpsrld $8, xl, RIDX2; \ | ||
94 | vpand RBYTE, RIDX1, RIDX1; \ | ||
95 | vpand RBYTE, RIDX2, RIDX2; \ | ||
96 | vpand RBYTE, xl, RIDX3; \ | ||
97 | \ | ||
98 | vpgatherdd RNOT, (RS0, RIDX0, 4), RT0; \ | ||
99 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
100 | vpcmpeqd RIDX0, RIDX0, RIDX0; \ | ||
101 | \ | ||
102 | vpgatherdd RNOT, (RS1, RIDX1, 4), RT1; \ | ||
103 | vpcmpeqd RIDX1, RIDX1, RIDX1; \ | ||
104 | vpaddd RT0, RT1, RT0; \ | ||
105 | \ | ||
106 | vpgatherdd RIDX0, (RS2, RIDX2, 4), RT1; \ | ||
107 | vpxor RT0, RT1, RT0; \ | ||
108 | \ | ||
109 | vpgatherdd RIDX1, (RS3, RIDX3, 4), RT1; \ | ||
110 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
111 | vpaddd RT0, RT1, RT0; \ | ||
112 | \ | ||
113 | vpxor RT0, xr, xr; | ||
114 | |||
115 | #define add_roundkey(xl, nmem) \ | ||
116 | vpbroadcastd nmem, RT0; \ | ||
117 | vpxor RT0, xl ## 0, xl ## 0; \ | ||
118 | vpxor RT0, xl ## 1, xl ## 1; \ | ||
119 | vpxor RT0, xl ## 2, xl ## 2; \ | ||
120 | vpxor RT0, xl ## 3, xl ## 3; | ||
121 | |||
122 | #define round_enc() \ | ||
123 | add_roundkey(RXr, p(CTX,RLOOP,4)); \ | ||
124 | F(RXl0, RXr0); \ | ||
125 | F(RXl1, RXr1); \ | ||
126 | F(RXl2, RXr2); \ | ||
127 | F(RXl3, RXr3); \ | ||
128 | \ | ||
129 | add_roundkey(RXl, p+4(CTX,RLOOP,4)); \ | ||
130 | F(RXr0, RXl0); \ | ||
131 | F(RXr1, RXl1); \ | ||
132 | F(RXr2, RXl2); \ | ||
133 | F(RXr3, RXl3); | ||
134 | |||
135 | #define round_dec() \ | ||
136 | add_roundkey(RXr, p+4*2(CTX,RLOOP,4)); \ | ||
137 | F(RXl0, RXr0); \ | ||
138 | F(RXl1, RXr1); \ | ||
139 | F(RXl2, RXr2); \ | ||
140 | F(RXl3, RXr3); \ | ||
141 | \ | ||
142 | add_roundkey(RXl, p+4(CTX,RLOOP,4)); \ | ||
143 | F(RXr0, RXl0); \ | ||
144 | F(RXr1, RXl1); \ | ||
145 | F(RXr2, RXl2); \ | ||
146 | F(RXr3, RXl3); | ||
147 | |||
148 | #define init_round_constants() \ | ||
149 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
150 | leaq s0(CTX), RS0; \ | ||
151 | leaq s1(CTX), RS1; \ | ||
152 | leaq s2(CTX), RS2; \ | ||
153 | leaq s3(CTX), RS3; \ | ||
154 | vpsrld $24, RNOT, RBYTE; | ||
155 | |||
156 | #define transpose_2x2(x0, x1, t0) \ | ||
157 | vpunpckldq x0, x1, t0; \ | ||
158 | vpunpckhdq x0, x1, x1; \ | ||
159 | \ | ||
160 | vpunpcklqdq t0, x1, x0; \ | ||
161 | vpunpckhqdq t0, x1, x1; | ||
162 | |||
163 | #define read_block(xl, xr) \ | ||
164 | vbroadcasti128 .Lbswap32_mask, RT1; \ | ||
165 | \ | ||
166 | vpshufb RT1, xl ## 0, xl ## 0; \ | ||
167 | vpshufb RT1, xr ## 0, xr ## 0; \ | ||
168 | vpshufb RT1, xl ## 1, xl ## 1; \ | ||
169 | vpshufb RT1, xr ## 1, xr ## 1; \ | ||
170 | vpshufb RT1, xl ## 2, xl ## 2; \ | ||
171 | vpshufb RT1, xr ## 2, xr ## 2; \ | ||
172 | vpshufb RT1, xl ## 3, xl ## 3; \ | ||
173 | vpshufb RT1, xr ## 3, xr ## 3; \ | ||
174 | \ | ||
175 | transpose_2x2(xl ## 0, xr ## 0, RT0); \ | ||
176 | transpose_2x2(xl ## 1, xr ## 1, RT0); \ | ||
177 | transpose_2x2(xl ## 2, xr ## 2, RT0); \ | ||
178 | transpose_2x2(xl ## 3, xr ## 3, RT0); | ||
179 | |||
180 | #define write_block(xl, xr) \ | ||
181 | vbroadcasti128 .Lbswap32_mask, RT1; \ | ||
182 | \ | ||
183 | transpose_2x2(xl ## 0, xr ## 0, RT0); \ | ||
184 | transpose_2x2(xl ## 1, xr ## 1, RT0); \ | ||
185 | transpose_2x2(xl ## 2, xr ## 2, RT0); \ | ||
186 | transpose_2x2(xl ## 3, xr ## 3, RT0); \ | ||
187 | \ | ||
188 | vpshufb RT1, xl ## 0, xl ## 0; \ | ||
189 | vpshufb RT1, xr ## 0, xr ## 0; \ | ||
190 | vpshufb RT1, xl ## 1, xl ## 1; \ | ||
191 | vpshufb RT1, xr ## 1, xr ## 1; \ | ||
192 | vpshufb RT1, xl ## 2, xl ## 2; \ | ||
193 | vpshufb RT1, xr ## 2, xr ## 2; \ | ||
194 | vpshufb RT1, xl ## 3, xl ## 3; \ | ||
195 | vpshufb RT1, xr ## 3, xr ## 3; | ||
196 | |||
197 | .align 8 | ||
198 | __blowfish_enc_blk32: | ||
199 | /* input: | ||
200 | * %rdi: ctx, CTX | ||
201 | * RXl0..4, RXr0..4: plaintext | ||
202 | * output: | ||
203 | * RXl0..4, RXr0..4: ciphertext (RXl <=> RXr swapped) | ||
204 | */ | ||
205 | init_round_constants(); | ||
206 | |||
207 | read_block(RXl, RXr); | ||
208 | |||
209 | movl $1, RLOOPd; | ||
210 | add_roundkey(RXl, p+4*(0)(CTX)); | ||
211 | |||
212 | .align 4 | ||
213 | .L__enc_loop: | ||
214 | round_enc(); | ||
215 | |||
216 | leal 2(RLOOPd), RLOOPd; | ||
217 | cmpl $17, RLOOPd; | ||
218 | jne .L__enc_loop; | ||
219 | |||
220 | add_roundkey(RXr, p+4*(17)(CTX)); | ||
221 | |||
222 | write_block(RXl, RXr); | ||
223 | |||
224 | ret; | ||
225 | ENDPROC(__blowfish_enc_blk32) | ||
226 | |||
227 | .align 8 | ||
228 | __blowfish_dec_blk32: | ||
229 | /* input: | ||
230 | * %rdi: ctx, CTX | ||
231 | * RXl0..4, RXr0..4: ciphertext | ||
232 | * output: | ||
233 | * RXl0..4, RXr0..4: plaintext (RXl <=> RXr swapped) | ||
234 | */ | ||
235 | init_round_constants(); | ||
236 | |||
237 | read_block(RXl, RXr); | ||
238 | |||
239 | movl $14, RLOOPd; | ||
240 | add_roundkey(RXl, p+4*(17)(CTX)); | ||
241 | |||
242 | .align 4 | ||
243 | .L__dec_loop: | ||
244 | round_dec(); | ||
245 | |||
246 | addl $-2, RLOOPd; | ||
247 | jns .L__dec_loop; | ||
248 | |||
249 | add_roundkey(RXr, p+4*(0)(CTX)); | ||
250 | |||
251 | write_block(RXl, RXr); | ||
252 | |||
253 | ret; | ||
254 | ENDPROC(__blowfish_dec_blk32) | ||
255 | |||
256 | ENTRY(blowfish_ecb_enc_32way) | ||
257 | /* input: | ||
258 | * %rdi: ctx, CTX | ||
259 | * %rsi: dst | ||
260 | * %rdx: src | ||
261 | */ | ||
262 | |||
263 | vzeroupper; | ||
264 | |||
265 | vmovdqu 0*32(%rdx), RXl0; | ||
266 | vmovdqu 1*32(%rdx), RXr0; | ||
267 | vmovdqu 2*32(%rdx), RXl1; | ||
268 | vmovdqu 3*32(%rdx), RXr1; | ||
269 | vmovdqu 4*32(%rdx), RXl2; | ||
270 | vmovdqu 5*32(%rdx), RXr2; | ||
271 | vmovdqu 6*32(%rdx), RXl3; | ||
272 | vmovdqu 7*32(%rdx), RXr3; | ||
273 | |||
274 | call __blowfish_enc_blk32; | ||
275 | |||
276 | vmovdqu RXr0, 0*32(%rsi); | ||
277 | vmovdqu RXl0, 1*32(%rsi); | ||
278 | vmovdqu RXr1, 2*32(%rsi); | ||
279 | vmovdqu RXl1, 3*32(%rsi); | ||
280 | vmovdqu RXr2, 4*32(%rsi); | ||
281 | vmovdqu RXl2, 5*32(%rsi); | ||
282 | vmovdqu RXr3, 6*32(%rsi); | ||
283 | vmovdqu RXl3, 7*32(%rsi); | ||
284 | |||
285 | vzeroupper; | ||
286 | |||
287 | ret; | ||
288 | ENDPROC(blowfish_ecb_enc_32way) | ||
289 | |||
290 | ENTRY(blowfish_ecb_dec_32way) | ||
291 | /* input: | ||
292 | * %rdi: ctx, CTX | ||
293 | * %rsi: dst | ||
294 | * %rdx: src | ||
295 | */ | ||
296 | |||
297 | vzeroupper; | ||
298 | |||
299 | vmovdqu 0*32(%rdx), RXl0; | ||
300 | vmovdqu 1*32(%rdx), RXr0; | ||
301 | vmovdqu 2*32(%rdx), RXl1; | ||
302 | vmovdqu 3*32(%rdx), RXr1; | ||
303 | vmovdqu 4*32(%rdx), RXl2; | ||
304 | vmovdqu 5*32(%rdx), RXr2; | ||
305 | vmovdqu 6*32(%rdx), RXl3; | ||
306 | vmovdqu 7*32(%rdx), RXr3; | ||
307 | |||
308 | call __blowfish_dec_blk32; | ||
309 | |||
310 | vmovdqu RXr0, 0*32(%rsi); | ||
311 | vmovdqu RXl0, 1*32(%rsi); | ||
312 | vmovdqu RXr1, 2*32(%rsi); | ||
313 | vmovdqu RXl1, 3*32(%rsi); | ||
314 | vmovdqu RXr2, 4*32(%rsi); | ||
315 | vmovdqu RXl2, 5*32(%rsi); | ||
316 | vmovdqu RXr3, 6*32(%rsi); | ||
317 | vmovdqu RXl3, 7*32(%rsi); | ||
318 | |||
319 | vzeroupper; | ||
320 | |||
321 | ret; | ||
322 | ENDPROC(blowfish_ecb_dec_32way) | ||
323 | |||
324 | ENTRY(blowfish_cbc_dec_32way) | ||
325 | /* input: | ||
326 | * %rdi: ctx, CTX | ||
327 | * %rsi: dst | ||
328 | * %rdx: src | ||
329 | */ | ||
330 | |||
331 | vzeroupper; | ||
332 | |||
333 | vmovdqu 0*32(%rdx), RXl0; | ||
334 | vmovdqu 1*32(%rdx), RXr0; | ||
335 | vmovdqu 2*32(%rdx), RXl1; | ||
336 | vmovdqu 3*32(%rdx), RXr1; | ||
337 | vmovdqu 4*32(%rdx), RXl2; | ||
338 | vmovdqu 5*32(%rdx), RXr2; | ||
339 | vmovdqu 6*32(%rdx), RXl3; | ||
340 | vmovdqu 7*32(%rdx), RXr3; | ||
341 | |||
342 | call __blowfish_dec_blk32; | ||
343 | |||
344 | /* xor with src */ | ||
345 | vmovq (%rdx), RT0x; | ||
346 | vpshufd $0x4f, RT0x, RT0x; | ||
347 | vinserti128 $1, 8(%rdx), RT0, RT0; | ||
348 | vpxor RT0, RXr0, RXr0; | ||
349 | vpxor 0*32+24(%rdx), RXl0, RXl0; | ||
350 | vpxor 1*32+24(%rdx), RXr1, RXr1; | ||
351 | vpxor 2*32+24(%rdx), RXl1, RXl1; | ||
352 | vpxor 3*32+24(%rdx), RXr2, RXr2; | ||
353 | vpxor 4*32+24(%rdx), RXl2, RXl2; | ||
354 | vpxor 5*32+24(%rdx), RXr3, RXr3; | ||
355 | vpxor 6*32+24(%rdx), RXl3, RXl3; | ||
356 | |||
357 | vmovdqu RXr0, (0*32)(%rsi); | ||
358 | vmovdqu RXl0, (1*32)(%rsi); | ||
359 | vmovdqu RXr1, (2*32)(%rsi); | ||
360 | vmovdqu RXl1, (3*32)(%rsi); | ||
361 | vmovdqu RXr2, (4*32)(%rsi); | ||
362 | vmovdqu RXl2, (5*32)(%rsi); | ||
363 | vmovdqu RXr3, (6*32)(%rsi); | ||
364 | vmovdqu RXl3, (7*32)(%rsi); | ||
365 | |||
366 | vzeroupper; | ||
367 | |||
368 | ret; | ||
369 | ENDPROC(blowfish_cbc_dec_32way) | ||
370 | |||
371 | ENTRY(blowfish_ctr_32way) | ||
372 | /* input: | ||
373 | * %rdi: ctx, CTX | ||
374 | * %rsi: dst | ||
375 | * %rdx: src | ||
376 | * %rcx: iv (big endian, 64bit) | ||
377 | */ | ||
378 | |||
379 | vzeroupper; | ||
380 | |||
381 | vpcmpeqd RT0, RT0, RT0; | ||
382 | vpsrldq $8, RT0, RT0; /* a: -1, b: 0, c: -1, d: 0 */ | ||
383 | |||
384 | vpcmpeqd RT1x, RT1x, RT1x; | ||
385 | vpaddq RT1x, RT1x, RT1x; /* a: -2, b: -2 */ | ||
386 | vpxor RIDX0, RIDX0, RIDX0; | ||
387 | vinserti128 $1, RT1x, RIDX0, RIDX0; /* a: 0, b: 0, c: -2, d: -2 */ | ||
388 | |||
389 | vpaddq RIDX0, RT0, RT0; /* a: -1, b: 0, c: -3, d: -2 */ | ||
390 | |||
391 | vpcmpeqd RT1, RT1, RT1; | ||
392 | vpaddq RT1, RT1, RT1; /* a: -2, b: -2, c: -2, d: -2 */ | ||
393 | vpaddq RT1, RT1, RIDX2; /* a: -4, b: -4, c: -4, d: -4 */ | ||
394 | |||
395 | vbroadcasti128 .Lbswap_iv_mask, RIDX0; | ||
396 | vbroadcasti128 .Lbswap128_mask, RIDX1; | ||
397 | |||
398 | /* load IV and byteswap */ | ||
399 | vmovq (%rcx), RT1x; | ||
400 | vinserti128 $1, RT1x, RT1, RT1; /* a: BE, b: 0, c: BE, d: 0 */ | ||
401 | vpshufb RIDX0, RT1, RT1; /* a: LE, b: LE, c: LE, d: LE */ | ||
402 | |||
403 | /* construct IVs */ | ||
404 | vpsubq RT0, RT1, RT1; /* a: le1, b: le0, c: le3, d: le2 */ | ||
405 | vpshufb RIDX1, RT1, RXl0; /* a: be0, b: be1, c: be2, d: be3 */ | ||
406 | vpsubq RIDX2, RT1, RT1; /* le5, le4, le7, le6 */ | ||
407 | vpshufb RIDX1, RT1, RXr0; /* be4, be5, be6, be7 */ | ||
408 | vpsubq RIDX2, RT1, RT1; | ||
409 | vpshufb RIDX1, RT1, RXl1; | ||
410 | vpsubq RIDX2, RT1, RT1; | ||
411 | vpshufb RIDX1, RT1, RXr1; | ||
412 | vpsubq RIDX2, RT1, RT1; | ||
413 | vpshufb RIDX1, RT1, RXl2; | ||
414 | vpsubq RIDX2, RT1, RT1; | ||
415 | vpshufb RIDX1, RT1, RXr2; | ||
416 | vpsubq RIDX2, RT1, RT1; | ||
417 | vpshufb RIDX1, RT1, RXl3; | ||
418 | vpsubq RIDX2, RT1, RT1; | ||
419 | vpshufb RIDX1, RT1, RXr3; | ||
420 | |||
421 | /* store last IV */ | ||
422 | vpsubq RIDX2, RT1, RT1; /* a: le33, b: le32, ... */ | ||
423 | vpshufb RIDX1x, RT1x, RT1x; /* a: be32, ... */ | ||
424 | vmovq RT1x, (%rcx); | ||
425 | |||
426 | call __blowfish_enc_blk32; | ||
427 | |||
428 | /* dst = src ^ iv */ | ||
429 | vpxor 0*32(%rdx), RXr0, RXr0; | ||
430 | vpxor 1*32(%rdx), RXl0, RXl0; | ||
431 | vpxor 2*32(%rdx), RXr1, RXr1; | ||
432 | vpxor 3*32(%rdx), RXl1, RXl1; | ||
433 | vpxor 4*32(%rdx), RXr2, RXr2; | ||
434 | vpxor 5*32(%rdx), RXl2, RXl2; | ||
435 | vpxor 6*32(%rdx), RXr3, RXr3; | ||
436 | vpxor 7*32(%rdx), RXl3, RXl3; | ||
437 | vmovdqu RXr0, (0*32)(%rsi); | ||
438 | vmovdqu RXl0, (1*32)(%rsi); | ||
439 | vmovdqu RXr1, (2*32)(%rsi); | ||
440 | vmovdqu RXl1, (3*32)(%rsi); | ||
441 | vmovdqu RXr2, (4*32)(%rsi); | ||
442 | vmovdqu RXl2, (5*32)(%rsi); | ||
443 | vmovdqu RXr3, (6*32)(%rsi); | ||
444 | vmovdqu RXl3, (7*32)(%rsi); | ||
445 | |||
446 | vzeroupper; | ||
447 | |||
448 | ret; | ||
449 | ENDPROC(blowfish_ctr_32way) | ||
diff --git a/arch/x86/crypto/blowfish_avx2_glue.c b/arch/x86/crypto/blowfish_avx2_glue.c deleted file mode 100644 index 4417e9aea78d..000000000000 --- a/arch/x86/crypto/blowfish_avx2_glue.c +++ /dev/null | |||
@@ -1,585 +0,0 @@ | |||
1 | /* | ||
2 | * Glue Code for x86_64/AVX2 assembler optimized version of Blowfish | ||
3 | * | ||
4 | * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | ||
5 | * | ||
6 | * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: | ||
7 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> | ||
8 | * CTR part based on code (crypto/ctr.c) by: | ||
9 | * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/crypto.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <crypto/algapi.h> | ||
28 | #include <crypto/blowfish.h> | ||
29 | #include <crypto/cryptd.h> | ||
30 | #include <crypto/ctr.h> | ||
31 | #include <asm/i387.h> | ||
32 | #include <asm/xcr.h> | ||
33 | #include <asm/xsave.h> | ||
34 | #include <asm/crypto/blowfish.h> | ||
35 | #include <asm/crypto/ablk_helper.h> | ||
36 | #include <crypto/scatterwalk.h> | ||
37 | |||
38 | #define BF_AVX2_PARALLEL_BLOCKS 32 | ||
39 | |||
40 | /* 32-way AVX2 parallel cipher functions */ | ||
41 | asmlinkage void blowfish_ecb_enc_32way(struct bf_ctx *ctx, u8 *dst, | ||
42 | const u8 *src); | ||
43 | asmlinkage void blowfish_ecb_dec_32way(struct bf_ctx *ctx, u8 *dst, | ||
44 | const u8 *src); | ||
45 | asmlinkage void blowfish_cbc_dec_32way(struct bf_ctx *ctx, u8 *dst, | ||
46 | const u8 *src); | ||
47 | asmlinkage void blowfish_ctr_32way(struct bf_ctx *ctx, u8 *dst, const u8 *src, | ||
48 | __be64 *iv); | ||
49 | |||
50 | static inline bool bf_fpu_begin(bool fpu_enabled, unsigned int nbytes) | ||
51 | { | ||
52 | if (fpu_enabled) | ||
53 | return true; | ||
54 | |||
55 | /* FPU is only used when chunk to be processed is large enough, so | ||
56 | * do not enable FPU until it is necessary. | ||
57 | */ | ||
58 | if (nbytes < BF_BLOCK_SIZE * BF_AVX2_PARALLEL_BLOCKS) | ||
59 | return false; | ||
60 | |||
61 | kernel_fpu_begin(); | ||
62 | return true; | ||
63 | } | ||
64 | |||
65 | static inline void bf_fpu_end(bool fpu_enabled) | ||
66 | { | ||
67 | if (fpu_enabled) | ||
68 | kernel_fpu_end(); | ||
69 | } | ||
70 | |||
71 | static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, | ||
72 | bool enc) | ||
73 | { | ||
74 | bool fpu_enabled = false; | ||
75 | struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
76 | const unsigned int bsize = BF_BLOCK_SIZE; | ||
77 | unsigned int nbytes; | ||
78 | int err; | ||
79 | |||
80 | err = blkcipher_walk_virt(desc, walk); | ||
81 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
82 | |||
83 | while ((nbytes = walk->nbytes)) { | ||
84 | u8 *wsrc = walk->src.virt.addr; | ||
85 | u8 *wdst = walk->dst.virt.addr; | ||
86 | |||
87 | fpu_enabled = bf_fpu_begin(fpu_enabled, nbytes); | ||
88 | |||
89 | /* Process multi-block AVX2 batch */ | ||
90 | if (nbytes >= bsize * BF_AVX2_PARALLEL_BLOCKS) { | ||
91 | do { | ||
92 | if (enc) | ||
93 | blowfish_ecb_enc_32way(ctx, wdst, wsrc); | ||
94 | else | ||
95 | blowfish_ecb_dec_32way(ctx, wdst, wsrc); | ||
96 | |||
97 | wsrc += bsize * BF_AVX2_PARALLEL_BLOCKS; | ||
98 | wdst += bsize * BF_AVX2_PARALLEL_BLOCKS; | ||
99 | nbytes -= bsize * BF_AVX2_PARALLEL_BLOCKS; | ||
100 | } while (nbytes >= bsize * BF_AVX2_PARALLEL_BLOCKS); | ||
101 | |||
102 | if (nbytes < bsize) | ||
103 | goto done; | ||
104 | } | ||
105 | |||
106 | /* Process multi-block batch */ | ||
107 | if (nbytes >= bsize * BF_PARALLEL_BLOCKS) { | ||
108 | do { | ||
109 | if (enc) | ||
110 | blowfish_enc_blk_4way(ctx, wdst, wsrc); | ||
111 | else | ||
112 | blowfish_dec_blk_4way(ctx, wdst, wsrc); | ||
113 | |||
114 | wsrc += bsize * BF_PARALLEL_BLOCKS; | ||
115 | wdst += bsize * BF_PARALLEL_BLOCKS; | ||
116 | nbytes -= bsize * BF_PARALLEL_BLOCKS; | ||
117 | } while (nbytes >= bsize * BF_PARALLEL_BLOCKS); | ||
118 | |||
119 | if (nbytes < bsize) | ||
120 | goto done; | ||
121 | } | ||
122 | |||
123 | /* Handle leftovers */ | ||
124 | do { | ||
125 | if (enc) | ||
126 | blowfish_enc_blk(ctx, wdst, wsrc); | ||
127 | else | ||
128 | blowfish_dec_blk(ctx, wdst, wsrc); | ||
129 | |||
130 | wsrc += bsize; | ||
131 | wdst += bsize; | ||
132 | nbytes -= bsize; | ||
133 | } while (nbytes >= bsize); | ||
134 | |||
135 | done: | ||
136 | err = blkcipher_walk_done(desc, walk, nbytes); | ||
137 | } | ||
138 | |||
139 | bf_fpu_end(fpu_enabled); | ||
140 | return err; | ||
141 | } | ||
142 | |||
143 | static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
144 | struct scatterlist *src, unsigned int nbytes) | ||
145 | { | ||
146 | struct blkcipher_walk walk; | ||
147 | |||
148 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
149 | return ecb_crypt(desc, &walk, true); | ||
150 | } | ||
151 | |||
152 | static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
153 | struct scatterlist *src, unsigned int nbytes) | ||
154 | { | ||
155 | struct blkcipher_walk walk; | ||
156 | |||
157 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
158 | return ecb_crypt(desc, &walk, false); | ||
159 | } | ||
160 | |||
161 | static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, | ||
162 | struct blkcipher_walk *walk) | ||
163 | { | ||
164 | struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
165 | unsigned int bsize = BF_BLOCK_SIZE; | ||
166 | unsigned int nbytes = walk->nbytes; | ||
167 | u64 *src = (u64 *)walk->src.virt.addr; | ||
168 | u64 *dst = (u64 *)walk->dst.virt.addr; | ||
169 | u64 *iv = (u64 *)walk->iv; | ||
170 | |||
171 | do { | ||
172 | *dst = *src ^ *iv; | ||
173 | blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); | ||
174 | iv = dst; | ||
175 | |||
176 | src += 1; | ||
177 | dst += 1; | ||
178 | nbytes -= bsize; | ||
179 | } while (nbytes >= bsize); | ||
180 | |||
181 | *(u64 *)walk->iv = *iv; | ||
182 | return nbytes; | ||
183 | } | ||
184 | |||
185 | static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
186 | struct scatterlist *src, unsigned int nbytes) | ||
187 | { | ||
188 | struct blkcipher_walk walk; | ||
189 | int err; | ||
190 | |||
191 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
192 | err = blkcipher_walk_virt(desc, &walk); | ||
193 | |||
194 | while ((nbytes = walk.nbytes)) { | ||
195 | nbytes = __cbc_encrypt(desc, &walk); | ||
196 | err = blkcipher_walk_done(desc, &walk, nbytes); | ||
197 | } | ||
198 | |||
199 | return err; | ||
200 | } | ||
201 | |||
202 | static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, | ||
203 | struct blkcipher_walk *walk) | ||
204 | { | ||
205 | struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
206 | const unsigned int bsize = BF_BLOCK_SIZE; | ||
207 | unsigned int nbytes = walk->nbytes; | ||
208 | u64 *src = (u64 *)walk->src.virt.addr; | ||
209 | u64 *dst = (u64 *)walk->dst.virt.addr; | ||
210 | u64 last_iv; | ||
211 | int i; | ||
212 | |||
213 | /* Start of the last block. */ | ||
214 | src += nbytes / bsize - 1; | ||
215 | dst += nbytes / bsize - 1; | ||
216 | |||
217 | last_iv = *src; | ||
218 | |||
219 | /* Process multi-block AVX2 batch */ | ||
220 | if (nbytes >= bsize * BF_AVX2_PARALLEL_BLOCKS) { | ||
221 | do { | ||
222 | nbytes -= bsize * (BF_AVX2_PARALLEL_BLOCKS - 1); | ||
223 | src -= BF_AVX2_PARALLEL_BLOCKS - 1; | ||
224 | dst -= BF_AVX2_PARALLEL_BLOCKS - 1; | ||
225 | |||
226 | blowfish_cbc_dec_32way(ctx, (u8 *)dst, (u8 *)src); | ||
227 | |||
228 | nbytes -= bsize; | ||
229 | if (nbytes < bsize) | ||
230 | goto done; | ||
231 | |||
232 | *dst ^= *(src - 1); | ||
233 | src -= 1; | ||
234 | dst -= 1; | ||
235 | } while (nbytes >= bsize * BF_AVX2_PARALLEL_BLOCKS); | ||
236 | |||
237 | if (nbytes < bsize) | ||
238 | goto done; | ||
239 | } | ||
240 | |||
241 | /* Process multi-block batch */ | ||
242 | if (nbytes >= bsize * BF_PARALLEL_BLOCKS) { | ||
243 | u64 ivs[BF_PARALLEL_BLOCKS - 1]; | ||
244 | |||
245 | do { | ||
246 | nbytes -= bsize * (BF_PARALLEL_BLOCKS - 1); | ||
247 | src -= BF_PARALLEL_BLOCKS - 1; | ||
248 | dst -= BF_PARALLEL_BLOCKS - 1; | ||
249 | |||
250 | for (i = 0; i < BF_PARALLEL_BLOCKS - 1; i++) | ||
251 | ivs[i] = src[i]; | ||
252 | |||
253 | blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src); | ||
254 | |||
255 | for (i = 0; i < BF_PARALLEL_BLOCKS - 1; i++) | ||
256 | dst[i + 1] ^= ivs[i]; | ||
257 | |||
258 | nbytes -= bsize; | ||
259 | if (nbytes < bsize) | ||
260 | goto done; | ||
261 | |||
262 | *dst ^= *(src - 1); | ||
263 | src -= 1; | ||
264 | dst -= 1; | ||
265 | } while (nbytes >= bsize * BF_PARALLEL_BLOCKS); | ||
266 | |||
267 | if (nbytes < bsize) | ||
268 | goto done; | ||
269 | } | ||
270 | |||
271 | /* Handle leftovers */ | ||
272 | for (;;) { | ||
273 | blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src); | ||
274 | |||
275 | nbytes -= bsize; | ||
276 | if (nbytes < bsize) | ||
277 | break; | ||
278 | |||
279 | *dst ^= *(src - 1); | ||
280 | src -= 1; | ||
281 | dst -= 1; | ||
282 | } | ||
283 | |||
284 | done: | ||
285 | *dst ^= *(u64 *)walk->iv; | ||
286 | *(u64 *)walk->iv = last_iv; | ||
287 | |||
288 | return nbytes; | ||
289 | } | ||
290 | |||
291 | static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
292 | struct scatterlist *src, unsigned int nbytes) | ||
293 | { | ||
294 | bool fpu_enabled = false; | ||
295 | struct blkcipher_walk walk; | ||
296 | int err; | ||
297 | |||
298 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
299 | err = blkcipher_walk_virt(desc, &walk); | ||
300 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
301 | |||
302 | while ((nbytes = walk.nbytes)) { | ||
303 | fpu_enabled = bf_fpu_begin(fpu_enabled, nbytes); | ||
304 | nbytes = __cbc_decrypt(desc, &walk); | ||
305 | err = blkcipher_walk_done(desc, &walk, nbytes); | ||
306 | } | ||
307 | |||
308 | bf_fpu_end(fpu_enabled); | ||
309 | return err; | ||
310 | } | ||
311 | |||
312 | static void ctr_crypt_final(struct blkcipher_desc *desc, | ||
313 | struct blkcipher_walk *walk) | ||
314 | { | ||
315 | struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
316 | u8 *ctrblk = walk->iv; | ||
317 | u8 keystream[BF_BLOCK_SIZE]; | ||
318 | u8 *src = walk->src.virt.addr; | ||
319 | u8 *dst = walk->dst.virt.addr; | ||
320 | unsigned int nbytes = walk->nbytes; | ||
321 | |||
322 | blowfish_enc_blk(ctx, keystream, ctrblk); | ||
323 | crypto_xor(keystream, src, nbytes); | ||
324 | memcpy(dst, keystream, nbytes); | ||
325 | |||
326 | crypto_inc(ctrblk, BF_BLOCK_SIZE); | ||
327 | } | ||
328 | |||
329 | static unsigned int __ctr_crypt(struct blkcipher_desc *desc, | ||
330 | struct blkcipher_walk *walk) | ||
331 | { | ||
332 | struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
333 | unsigned int bsize = BF_BLOCK_SIZE; | ||
334 | unsigned int nbytes = walk->nbytes; | ||
335 | u64 *src = (u64 *)walk->src.virt.addr; | ||
336 | u64 *dst = (u64 *)walk->dst.virt.addr; | ||
337 | int i; | ||
338 | |||
339 | /* Process multi-block AVX2 batch */ | ||
340 | if (nbytes >= bsize * BF_AVX2_PARALLEL_BLOCKS) { | ||
341 | do { | ||
342 | blowfish_ctr_32way(ctx, (u8 *)dst, (u8 *)src, | ||
343 | (__be64 *)walk->iv); | ||
344 | |||
345 | src += BF_AVX2_PARALLEL_BLOCKS; | ||
346 | dst += BF_AVX2_PARALLEL_BLOCKS; | ||
347 | nbytes -= bsize * BF_AVX2_PARALLEL_BLOCKS; | ||
348 | } while (nbytes >= bsize * BF_AVX2_PARALLEL_BLOCKS); | ||
349 | |||
350 | if (nbytes < bsize) | ||
351 | goto done; | ||
352 | } | ||
353 | |||
354 | /* Process four block batch */ | ||
355 | if (nbytes >= bsize * BF_PARALLEL_BLOCKS) { | ||
356 | __be64 ctrblocks[BF_PARALLEL_BLOCKS]; | ||
357 | u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv); | ||
358 | |||
359 | do { | ||
360 | /* create ctrblks for parallel encrypt */ | ||
361 | for (i = 0; i < BF_PARALLEL_BLOCKS; i++) { | ||
362 | if (dst != src) | ||
363 | dst[i] = src[i]; | ||
364 | |||
365 | ctrblocks[i] = cpu_to_be64(ctrblk++); | ||
366 | } | ||
367 | |||
368 | blowfish_enc_blk_xor_4way(ctx, (u8 *)dst, | ||
369 | (u8 *)ctrblocks); | ||
370 | |||
371 | src += BF_PARALLEL_BLOCKS; | ||
372 | dst += BF_PARALLEL_BLOCKS; | ||
373 | nbytes -= bsize * BF_PARALLEL_BLOCKS; | ||
374 | } while (nbytes >= bsize * BF_PARALLEL_BLOCKS); | ||
375 | |||
376 | *(__be64 *)walk->iv = cpu_to_be64(ctrblk); | ||
377 | |||
378 | if (nbytes < bsize) | ||
379 | goto done; | ||
380 | } | ||
381 | |||
382 | /* Handle leftovers */ | ||
383 | do { | ||
384 | u64 ctrblk; | ||
385 | |||
386 | if (dst != src) | ||
387 | *dst = *src; | ||
388 | |||
389 | ctrblk = *(u64 *)walk->iv; | ||
390 | be64_add_cpu((__be64 *)walk->iv, 1); | ||
391 | |||
392 | blowfish_enc_blk_xor(ctx, (u8 *)dst, (u8 *)&ctrblk); | ||
393 | |||
394 | src += 1; | ||
395 | dst += 1; | ||
396 | } while ((nbytes -= bsize) >= bsize); | ||
397 | |||
398 | done: | ||
399 | return nbytes; | ||
400 | } | ||
401 | |||
402 | static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
403 | struct scatterlist *src, unsigned int nbytes) | ||
404 | { | ||
405 | bool fpu_enabled = false; | ||
406 | struct blkcipher_walk walk; | ||
407 | int err; | ||
408 | |||
409 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
410 | err = blkcipher_walk_virt_block(desc, &walk, BF_BLOCK_SIZE); | ||
411 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
412 | |||
413 | while ((nbytes = walk.nbytes) >= BF_BLOCK_SIZE) { | ||
414 | fpu_enabled = bf_fpu_begin(fpu_enabled, nbytes); | ||
415 | nbytes = __ctr_crypt(desc, &walk); | ||
416 | err = blkcipher_walk_done(desc, &walk, nbytes); | ||
417 | } | ||
418 | |||
419 | bf_fpu_end(fpu_enabled); | ||
420 | |||
421 | if (walk.nbytes) { | ||
422 | ctr_crypt_final(desc, &walk); | ||
423 | err = blkcipher_walk_done(desc, &walk, 0); | ||
424 | } | ||
425 | |||
426 | return err; | ||
427 | } | ||
428 | |||
429 | static struct crypto_alg bf_algs[6] = { { | ||
430 | .cra_name = "__ecb-blowfish-avx2", | ||
431 | .cra_driver_name = "__driver-ecb-blowfish-avx2", | ||
432 | .cra_priority = 0, | ||
433 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
434 | .cra_blocksize = BF_BLOCK_SIZE, | ||
435 | .cra_ctxsize = sizeof(struct bf_ctx), | ||
436 | .cra_alignmask = 0, | ||
437 | .cra_type = &crypto_blkcipher_type, | ||
438 | .cra_module = THIS_MODULE, | ||
439 | .cra_u = { | ||
440 | .blkcipher = { | ||
441 | .min_keysize = BF_MIN_KEY_SIZE, | ||
442 | .max_keysize = BF_MAX_KEY_SIZE, | ||
443 | .setkey = blowfish_setkey, | ||
444 | .encrypt = ecb_encrypt, | ||
445 | .decrypt = ecb_decrypt, | ||
446 | }, | ||
447 | }, | ||
448 | }, { | ||
449 | .cra_name = "__cbc-blowfish-avx2", | ||
450 | .cra_driver_name = "__driver-cbc-blowfish-avx2", | ||
451 | .cra_priority = 0, | ||
452 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
453 | .cra_blocksize = BF_BLOCK_SIZE, | ||
454 | .cra_ctxsize = sizeof(struct bf_ctx), | ||
455 | .cra_alignmask = 0, | ||
456 | .cra_type = &crypto_blkcipher_type, | ||
457 | .cra_module = THIS_MODULE, | ||
458 | .cra_u = { | ||
459 | .blkcipher = { | ||
460 | .min_keysize = BF_MIN_KEY_SIZE, | ||
461 | .max_keysize = BF_MAX_KEY_SIZE, | ||
462 | .setkey = blowfish_setkey, | ||
463 | .encrypt = cbc_encrypt, | ||
464 | .decrypt = cbc_decrypt, | ||
465 | }, | ||
466 | }, | ||
467 | }, { | ||
468 | .cra_name = "__ctr-blowfish-avx2", | ||
469 | .cra_driver_name = "__driver-ctr-blowfish-avx2", | ||
470 | .cra_priority = 0, | ||
471 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
472 | .cra_blocksize = 1, | ||
473 | .cra_ctxsize = sizeof(struct bf_ctx), | ||
474 | .cra_alignmask = 0, | ||
475 | .cra_type = &crypto_blkcipher_type, | ||
476 | .cra_module = THIS_MODULE, | ||
477 | .cra_u = { | ||
478 | .blkcipher = { | ||
479 | .min_keysize = BF_MIN_KEY_SIZE, | ||
480 | .max_keysize = BF_MAX_KEY_SIZE, | ||
481 | .ivsize = BF_BLOCK_SIZE, | ||
482 | .setkey = blowfish_setkey, | ||
483 | .encrypt = ctr_crypt, | ||
484 | .decrypt = ctr_crypt, | ||
485 | }, | ||
486 | }, | ||
487 | }, { | ||
488 | .cra_name = "ecb(blowfish)", | ||
489 | .cra_driver_name = "ecb-blowfish-avx2", | ||
490 | .cra_priority = 400, | ||
491 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
492 | .cra_blocksize = BF_BLOCK_SIZE, | ||
493 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
494 | .cra_alignmask = 0, | ||
495 | .cra_type = &crypto_ablkcipher_type, | ||
496 | .cra_module = THIS_MODULE, | ||
497 | .cra_init = ablk_init, | ||
498 | .cra_exit = ablk_exit, | ||
499 | .cra_u = { | ||
500 | .ablkcipher = { | ||
501 | .min_keysize = BF_MIN_KEY_SIZE, | ||
502 | .max_keysize = BF_MAX_KEY_SIZE, | ||
503 | .setkey = ablk_set_key, | ||
504 | .encrypt = ablk_encrypt, | ||
505 | .decrypt = ablk_decrypt, | ||
506 | }, | ||
507 | }, | ||
508 | }, { | ||
509 | .cra_name = "cbc(blowfish)", | ||
510 | .cra_driver_name = "cbc-blowfish-avx2", | ||
511 | .cra_priority = 400, | ||
512 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
513 | .cra_blocksize = BF_BLOCK_SIZE, | ||
514 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
515 | .cra_alignmask = 0, | ||
516 | .cra_type = &crypto_ablkcipher_type, | ||
517 | .cra_module = THIS_MODULE, | ||
518 | .cra_init = ablk_init, | ||
519 | .cra_exit = ablk_exit, | ||
520 | .cra_u = { | ||
521 | .ablkcipher = { | ||
522 | .min_keysize = BF_MIN_KEY_SIZE, | ||
523 | .max_keysize = BF_MAX_KEY_SIZE, | ||
524 | .ivsize = BF_BLOCK_SIZE, | ||
525 | .setkey = ablk_set_key, | ||
526 | .encrypt = __ablk_encrypt, | ||
527 | .decrypt = ablk_decrypt, | ||
528 | }, | ||
529 | }, | ||
530 | }, { | ||
531 | .cra_name = "ctr(blowfish)", | ||
532 | .cra_driver_name = "ctr-blowfish-avx2", | ||
533 | .cra_priority = 400, | ||
534 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
535 | .cra_blocksize = 1, | ||
536 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
537 | .cra_alignmask = 0, | ||
538 | .cra_type = &crypto_ablkcipher_type, | ||
539 | .cra_module = THIS_MODULE, | ||
540 | .cra_init = ablk_init, | ||
541 | .cra_exit = ablk_exit, | ||
542 | .cra_u = { | ||
543 | .ablkcipher = { | ||
544 | .min_keysize = BF_MIN_KEY_SIZE, | ||
545 | .max_keysize = BF_MAX_KEY_SIZE, | ||
546 | .ivsize = BF_BLOCK_SIZE, | ||
547 | .setkey = ablk_set_key, | ||
548 | .encrypt = ablk_encrypt, | ||
549 | .decrypt = ablk_encrypt, | ||
550 | .geniv = "chainiv", | ||
551 | }, | ||
552 | }, | ||
553 | } }; | ||
554 | |||
555 | |||
556 | static int __init init(void) | ||
557 | { | ||
558 | u64 xcr0; | ||
559 | |||
560 | if (!cpu_has_avx2 || !cpu_has_osxsave) { | ||
561 | pr_info("AVX2 instructions are not detected.\n"); | ||
562 | return -ENODEV; | ||
563 | } | ||
564 | |||
565 | xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); | ||
566 | if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) { | ||
567 | pr_info("AVX detected but unusable.\n"); | ||
568 | return -ENODEV; | ||
569 | } | ||
570 | |||
571 | return crypto_register_algs(bf_algs, ARRAY_SIZE(bf_algs)); | ||
572 | } | ||
573 | |||
574 | static void __exit fini(void) | ||
575 | { | ||
576 | crypto_unregister_algs(bf_algs, ARRAY_SIZE(bf_algs)); | ||
577 | } | ||
578 | |||
579 | module_init(init); | ||
580 | module_exit(fini); | ||
581 | |||
582 | MODULE_LICENSE("GPL"); | ||
583 | MODULE_DESCRIPTION("Blowfish Cipher Algorithm, AVX2 optimized"); | ||
584 | MODULE_ALIAS("blowfish"); | ||
585 | MODULE_ALIAS("blowfish-asm"); | ||
diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c index 3548d76dbaa9..50ec333b70e6 100644 --- a/arch/x86/crypto/blowfish_glue.c +++ b/arch/x86/crypto/blowfish_glue.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Glue Code for assembler optimized version of Blowfish | 2 | * Glue Code for assembler optimized version of Blowfish |
3 | * | 3 | * |
4 | * Copyright © 2011-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> | 4 | * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> |
5 | * | 5 | * |
6 | * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: | 6 | * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: |
7 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> | 7 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> |
@@ -32,24 +32,40 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <crypto/algapi.h> | 34 | #include <crypto/algapi.h> |
35 | #include <asm/crypto/blowfish.h> | ||
36 | 35 | ||
37 | /* regular block cipher functions */ | 36 | /* regular block cipher functions */ |
38 | asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src, | 37 | asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src, |
39 | bool xor); | 38 | bool xor); |
40 | EXPORT_SYMBOL_GPL(__blowfish_enc_blk); | ||
41 | |||
42 | asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src); | 39 | asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src); |
43 | EXPORT_SYMBOL_GPL(blowfish_dec_blk); | ||
44 | 40 | ||
45 | /* 4-way parallel cipher functions */ | 41 | /* 4-way parallel cipher functions */ |
46 | asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst, | 42 | asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst, |
47 | const u8 *src, bool xor); | 43 | const u8 *src, bool xor); |
48 | EXPORT_SYMBOL_GPL(__blowfish_enc_blk_4way); | ||
49 | |||
50 | asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst, | 44 | asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst, |
51 | const u8 *src); | 45 | const u8 *src); |
52 | EXPORT_SYMBOL_GPL(blowfish_dec_blk_4way); | 46 | |
47 | static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src) | ||
48 | { | ||
49 | __blowfish_enc_blk(ctx, dst, src, false); | ||
50 | } | ||
51 | |||
52 | static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst, | ||
53 | const u8 *src) | ||
54 | { | ||
55 | __blowfish_enc_blk(ctx, dst, src, true); | ||
56 | } | ||
57 | |||
58 | static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst, | ||
59 | const u8 *src) | ||
60 | { | ||
61 | __blowfish_enc_blk_4way(ctx, dst, src, false); | ||
62 | } | ||
63 | |||
64 | static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst, | ||
65 | const u8 *src) | ||
66 | { | ||
67 | __blowfish_enc_blk_4way(ctx, dst, src, true); | ||
68 | } | ||
53 | 69 | ||
54 | static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) | 70 | static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) |
55 | { | 71 | { |
diff --git a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S index 91a1878fcc3e..0e0b8863a34b 100644 --- a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S +++ b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S | |||
@@ -51,16 +51,6 @@ | |||
51 | #define ymm14_x xmm14 | 51 | #define ymm14_x xmm14 |
52 | #define ymm15_x xmm15 | 52 | #define ymm15_x xmm15 |
53 | 53 | ||
54 | /* | ||
55 | * AES-NI instructions do not support ymmX registers, so we need splitting and | ||
56 | * merging. | ||
57 | */ | ||
58 | #define vaesenclast256(zero, yreg, tmp) \ | ||
59 | vextracti128 $1, yreg, tmp##_x; \ | ||
60 | vaesenclast zero##_x, yreg##_x, yreg##_x; \ | ||
61 | vaesenclast zero##_x, tmp##_x, tmp##_x; \ | ||
62 | vinserti128 $1, tmp##_x, yreg, yreg; | ||
63 | |||
64 | /********************************************************************** | 54 | /********************************************************************** |
65 | 32-way camellia | 55 | 32-way camellia |
66 | **********************************************************************/ | 56 | **********************************************************************/ |
@@ -79,46 +69,70 @@ | |||
79 | * S-function with AES subbytes \ | 69 | * S-function with AES subbytes \ |
80 | */ \ | 70 | */ \ |
81 | vbroadcasti128 .Linv_shift_row, t4; \ | 71 | vbroadcasti128 .Linv_shift_row, t4; \ |
82 | vpbroadcastb .L0f0f0f0f, t7; \ | 72 | vpbroadcastd .L0f0f0f0f, t7; \ |
83 | vbroadcasti128 .Lpre_tf_lo_s1, t0; \ | 73 | vbroadcasti128 .Lpre_tf_lo_s1, t5; \ |
84 | vbroadcasti128 .Lpre_tf_hi_s1, t1; \ | 74 | vbroadcasti128 .Lpre_tf_hi_s1, t6; \ |
75 | vbroadcasti128 .Lpre_tf_lo_s4, t2; \ | ||
76 | vbroadcasti128 .Lpre_tf_hi_s4, t3; \ | ||
85 | \ | 77 | \ |
86 | /* AES inverse shift rows */ \ | 78 | /* AES inverse shift rows */ \ |
87 | vpshufb t4, x0, x0; \ | 79 | vpshufb t4, x0, x0; \ |
88 | vpshufb t4, x7, x7; \ | 80 | vpshufb t4, x7, x7; \ |
89 | vpshufb t4, x1, x1; \ | ||
90 | vpshufb t4, x4, x4; \ | ||
91 | vpshufb t4, x2, x2; \ | ||
92 | vpshufb t4, x5, x5; \ | ||
93 | vpshufb t4, x3, x3; \ | 81 | vpshufb t4, x3, x3; \ |
94 | vpshufb t4, x6, x6; \ | 82 | vpshufb t4, x6, x6; \ |
83 | vpshufb t4, x2, x2; \ | ||
84 | vpshufb t4, x5, x5; \ | ||
85 | vpshufb t4, x1, x1; \ | ||
86 | vpshufb t4, x4, x4; \ | ||
95 | \ | 87 | \ |
96 | /* prefilter sboxes 1, 2 and 3 */ \ | 88 | /* prefilter sboxes 1, 2 and 3 */ \ |
97 | vbroadcasti128 .Lpre_tf_lo_s4, t2; \ | ||
98 | vbroadcasti128 .Lpre_tf_hi_s4, t3; \ | ||
99 | filter_8bit(x0, t0, t1, t7, t6); \ | ||
100 | filter_8bit(x7, t0, t1, t7, t6); \ | ||
101 | filter_8bit(x1, t0, t1, t7, t6); \ | ||
102 | filter_8bit(x4, t0, t1, t7, t6); \ | ||
103 | filter_8bit(x2, t0, t1, t7, t6); \ | ||
104 | filter_8bit(x5, t0, t1, t7, t6); \ | ||
105 | \ | ||
106 | /* prefilter sbox 4 */ \ | 89 | /* prefilter sbox 4 */ \ |
90 | filter_8bit(x0, t5, t6, t7, t4); \ | ||
91 | filter_8bit(x7, t5, t6, t7, t4); \ | ||
92 | vextracti128 $1, x0, t0##_x; \ | ||
93 | vextracti128 $1, x7, t1##_x; \ | ||
94 | filter_8bit(x3, t2, t3, t7, t4); \ | ||
95 | filter_8bit(x6, t2, t3, t7, t4); \ | ||
96 | vextracti128 $1, x3, t3##_x; \ | ||
97 | vextracti128 $1, x6, t2##_x; \ | ||
98 | filter_8bit(x2, t5, t6, t7, t4); \ | ||
99 | filter_8bit(x5, t5, t6, t7, t4); \ | ||
100 | filter_8bit(x1, t5, t6, t7, t4); \ | ||
101 | filter_8bit(x4, t5, t6, t7, t4); \ | ||
102 | \ | ||
107 | vpxor t4##_x, t4##_x, t4##_x; \ | 103 | vpxor t4##_x, t4##_x, t4##_x; \ |
108 | filter_8bit(x3, t2, t3, t7, t6); \ | ||
109 | filter_8bit(x6, t2, t3, t7, t6); \ | ||
110 | \ | 104 | \ |
111 | /* AES subbytes + AES shift rows */ \ | 105 | /* AES subbytes + AES shift rows */ \ |
106 | vextracti128 $1, x2, t6##_x; \ | ||
107 | vextracti128 $1, x5, t5##_x; \ | ||
108 | vaesenclast t4##_x, x0##_x, x0##_x; \ | ||
109 | vaesenclast t4##_x, t0##_x, t0##_x; \ | ||
110 | vinserti128 $1, t0##_x, x0, x0; \ | ||
111 | vaesenclast t4##_x, x7##_x, x7##_x; \ | ||
112 | vaesenclast t4##_x, t1##_x, t1##_x; \ | ||
113 | vinserti128 $1, t1##_x, x7, x7; \ | ||
114 | vaesenclast t4##_x, x3##_x, x3##_x; \ | ||
115 | vaesenclast t4##_x, t3##_x, t3##_x; \ | ||
116 | vinserti128 $1, t3##_x, x3, x3; \ | ||
117 | vaesenclast t4##_x, x6##_x, x6##_x; \ | ||
118 | vaesenclast t4##_x, t2##_x, t2##_x; \ | ||
119 | vinserti128 $1, t2##_x, x6, x6; \ | ||
120 | vextracti128 $1, x1, t3##_x; \ | ||
121 | vextracti128 $1, x4, t2##_x; \ | ||
112 | vbroadcasti128 .Lpost_tf_lo_s1, t0; \ | 122 | vbroadcasti128 .Lpost_tf_lo_s1, t0; \ |
113 | vbroadcasti128 .Lpost_tf_hi_s1, t1; \ | 123 | vbroadcasti128 .Lpost_tf_hi_s1, t1; \ |
114 | vaesenclast256(t4, x0, t5); \ | 124 | vaesenclast t4##_x, x2##_x, x2##_x; \ |
115 | vaesenclast256(t4, x7, t5); \ | 125 | vaesenclast t4##_x, t6##_x, t6##_x; \ |
116 | vaesenclast256(t4, x1, t5); \ | 126 | vinserti128 $1, t6##_x, x2, x2; \ |
117 | vaesenclast256(t4, x4, t5); \ | 127 | vaesenclast t4##_x, x5##_x, x5##_x; \ |
118 | vaesenclast256(t4, x2, t5); \ | 128 | vaesenclast t4##_x, t5##_x, t5##_x; \ |
119 | vaesenclast256(t4, x5, t5); \ | 129 | vinserti128 $1, t5##_x, x5, x5; \ |
120 | vaesenclast256(t4, x3, t5); \ | 130 | vaesenclast t4##_x, x1##_x, x1##_x; \ |
121 | vaesenclast256(t4, x6, t5); \ | 131 | vaesenclast t4##_x, t3##_x, t3##_x; \ |
132 | vinserti128 $1, t3##_x, x1, x1; \ | ||
133 | vaesenclast t4##_x, x4##_x, x4##_x; \ | ||
134 | vaesenclast t4##_x, t2##_x, t2##_x; \ | ||
135 | vinserti128 $1, t2##_x, x4, x4; \ | ||
122 | \ | 136 | \ |
123 | /* postfilter sboxes 1 and 4 */ \ | 137 | /* postfilter sboxes 1 and 4 */ \ |
124 | vbroadcasti128 .Lpost_tf_lo_s3, t2; \ | 138 | vbroadcasti128 .Lpost_tf_lo_s3, t2; \ |
@@ -139,22 +153,12 @@ | |||
139 | /* postfilter sbox 2 */ \ | 153 | /* postfilter sbox 2 */ \ |
140 | filter_8bit(x1, t4, t5, t7, t2); \ | 154 | filter_8bit(x1, t4, t5, t7, t2); \ |
141 | filter_8bit(x4, t4, t5, t7, t2); \ | 155 | filter_8bit(x4, t4, t5, t7, t2); \ |
156 | vpxor t7, t7, t7; \ | ||
142 | \ | 157 | \ |
143 | vpsrldq $1, t0, t1; \ | 158 | vpsrldq $1, t0, t1; \ |
144 | vpsrldq $2, t0, t2; \ | 159 | vpsrldq $2, t0, t2; \ |
160 | vpshufb t7, t1, t1; \ | ||
145 | vpsrldq $3, t0, t3; \ | 161 | vpsrldq $3, t0, t3; \ |
146 | vpsrldq $4, t0, t4; \ | ||
147 | vpsrldq $5, t0, t5; \ | ||
148 | vpsrldq $6, t0, t6; \ | ||
149 | vpsrldq $7, t0, t7; \ | ||
150 | vpbroadcastb t0##_x, t0; \ | ||
151 | vpbroadcastb t1##_x, t1; \ | ||
152 | vpbroadcastb t2##_x, t2; \ | ||
153 | vpbroadcastb t3##_x, t3; \ | ||
154 | vpbroadcastb t4##_x, t4; \ | ||
155 | vpbroadcastb t6##_x, t6; \ | ||
156 | vpbroadcastb t5##_x, t5; \ | ||
157 | vpbroadcastb t7##_x, t7; \ | ||
158 | \ | 162 | \ |
159 | /* P-function */ \ | 163 | /* P-function */ \ |
160 | vpxor x5, x0, x0; \ | 164 | vpxor x5, x0, x0; \ |
@@ -162,11 +166,21 @@ | |||
162 | vpxor x7, x2, x2; \ | 166 | vpxor x7, x2, x2; \ |
163 | vpxor x4, x3, x3; \ | 167 | vpxor x4, x3, x3; \ |
164 | \ | 168 | \ |
169 | vpshufb t7, t2, t2; \ | ||
170 | vpsrldq $4, t0, t4; \ | ||
171 | vpshufb t7, t3, t3; \ | ||
172 | vpsrldq $5, t0, t5; \ | ||
173 | vpshufb t7, t4, t4; \ | ||
174 | \ | ||
165 | vpxor x2, x4, x4; \ | 175 | vpxor x2, x4, x4; \ |
166 | vpxor x3, x5, x5; \ | 176 | vpxor x3, x5, x5; \ |
167 | vpxor x0, x6, x6; \ | 177 | vpxor x0, x6, x6; \ |
168 | vpxor x1, x7, x7; \ | 178 | vpxor x1, x7, x7; \ |
169 | \ | 179 | \ |
180 | vpsrldq $6, t0, t6; \ | ||
181 | vpshufb t7, t5, t5; \ | ||
182 | vpshufb t7, t6, t6; \ | ||
183 | \ | ||
170 | vpxor x7, x0, x0; \ | 184 | vpxor x7, x0, x0; \ |
171 | vpxor x4, x1, x1; \ | 185 | vpxor x4, x1, x1; \ |
172 | vpxor x5, x2, x2; \ | 186 | vpxor x5, x2, x2; \ |
@@ -179,12 +193,16 @@ | |||
179 | \ | 193 | \ |
180 | /* Add key material and result to CD (x becomes new CD) */ \ | 194 | /* Add key material and result to CD (x becomes new CD) */ \ |
181 | \ | 195 | \ |
182 | vpxor t7, x0, x0; \ | ||
183 | vpxor 4 * 32(mem_cd), x0, x0; \ | ||
184 | \ | ||
185 | vpxor t6, x1, x1; \ | 196 | vpxor t6, x1, x1; \ |
186 | vpxor 5 * 32(mem_cd), x1, x1; \ | 197 | vpxor 5 * 32(mem_cd), x1, x1; \ |
187 | \ | 198 | \ |
199 | vpsrldq $7, t0, t6; \ | ||
200 | vpshufb t7, t0, t0; \ | ||
201 | vpshufb t7, t6, t7; \ | ||
202 | \ | ||
203 | vpxor t7, x0, x0; \ | ||
204 | vpxor 4 * 32(mem_cd), x0, x0; \ | ||
205 | \ | ||
188 | vpxor t5, x2, x2; \ | 206 | vpxor t5, x2, x2; \ |
189 | vpxor 6 * 32(mem_cd), x2, x2; \ | 207 | vpxor 6 * 32(mem_cd), x2, x2; \ |
190 | \ | 208 | \ |
@@ -204,7 +222,7 @@ | |||
204 | vpxor 3 * 32(mem_cd), x7, x7; | 222 | vpxor 3 * 32(mem_cd), x7, x7; |
205 | 223 | ||
206 | /* | 224 | /* |
207 | * Size optimization... with inlined roundsm16 binary would be over 5 times | 225 | * Size optimization... with inlined roundsm32 binary would be over 5 times |
208 | * larger and would only marginally faster. | 226 | * larger and would only marginally faster. |
209 | */ | 227 | */ |
210 | .align 8 | 228 | .align 8 |
@@ -324,13 +342,13 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
324 | */ \ | 342 | */ \ |
325 | vpbroadcastd kll, t0; /* only lowest 32-bit used */ \ | 343 | vpbroadcastd kll, t0; /* only lowest 32-bit used */ \ |
326 | vpxor tt0, tt0, tt0; \ | 344 | vpxor tt0, tt0, tt0; \ |
327 | vpbroadcastb t0##_x, t3; \ | 345 | vpshufb tt0, t0, t3; \ |
328 | vpsrldq $1, t0, t0; \ | 346 | vpsrldq $1, t0, t0; \ |
329 | vpbroadcastb t0##_x, t2; \ | 347 | vpshufb tt0, t0, t2; \ |
330 | vpsrldq $1, t0, t0; \ | 348 | vpsrldq $1, t0, t0; \ |
331 | vpbroadcastb t0##_x, t1; \ | 349 | vpshufb tt0, t0, t1; \ |
332 | vpsrldq $1, t0, t0; \ | 350 | vpsrldq $1, t0, t0; \ |
333 | vpbroadcastb t0##_x, t0; \ | 351 | vpshufb tt0, t0, t0; \ |
334 | \ | 352 | \ |
335 | vpand l0, t0, t0; \ | 353 | vpand l0, t0, t0; \ |
336 | vpand l1, t1, t1; \ | 354 | vpand l1, t1, t1; \ |
@@ -340,6 +358,7 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
340 | rol32_1_32(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \ | 358 | rol32_1_32(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \ |
341 | \ | 359 | \ |
342 | vpxor l4, t0, l4; \ | 360 | vpxor l4, t0, l4; \ |
361 | vpbroadcastd krr, t0; /* only lowest 32-bit used */ \ | ||
343 | vmovdqu l4, 4 * 32(l); \ | 362 | vmovdqu l4, 4 * 32(l); \ |
344 | vpxor l5, t1, l5; \ | 363 | vpxor l5, t1, l5; \ |
345 | vmovdqu l5, 5 * 32(l); \ | 364 | vmovdqu l5, 5 * 32(l); \ |
@@ -354,14 +373,13 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
354 | * rl ^= t2; \ | 373 | * rl ^= t2; \ |
355 | */ \ | 374 | */ \ |
356 | \ | 375 | \ |
357 | vpbroadcastd krr, t0; /* only lowest 32-bit used */ \ | 376 | vpshufb tt0, t0, t3; \ |
358 | vpbroadcastb t0##_x, t3; \ | ||
359 | vpsrldq $1, t0, t0; \ | 377 | vpsrldq $1, t0, t0; \ |
360 | vpbroadcastb t0##_x, t2; \ | 378 | vpshufb tt0, t0, t2; \ |
361 | vpsrldq $1, t0, t0; \ | 379 | vpsrldq $1, t0, t0; \ |
362 | vpbroadcastb t0##_x, t1; \ | 380 | vpshufb tt0, t0, t1; \ |
363 | vpsrldq $1, t0, t0; \ | 381 | vpsrldq $1, t0, t0; \ |
364 | vpbroadcastb t0##_x, t0; \ | 382 | vpshufb tt0, t0, t0; \ |
365 | \ | 383 | \ |
366 | vpor 4 * 32(r), t0, t0; \ | 384 | vpor 4 * 32(r), t0, t0; \ |
367 | vpor 5 * 32(r), t1, t1; \ | 385 | vpor 5 * 32(r), t1, t1; \ |
@@ -373,6 +391,7 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
373 | vpxor 2 * 32(r), t2, t2; \ | 391 | vpxor 2 * 32(r), t2, t2; \ |
374 | vpxor 3 * 32(r), t3, t3; \ | 392 | vpxor 3 * 32(r), t3, t3; \ |
375 | vmovdqu t0, 0 * 32(r); \ | 393 | vmovdqu t0, 0 * 32(r); \ |
394 | vpbroadcastd krl, t0; /* only lowest 32-bit used */ \ | ||
376 | vmovdqu t1, 1 * 32(r); \ | 395 | vmovdqu t1, 1 * 32(r); \ |
377 | vmovdqu t2, 2 * 32(r); \ | 396 | vmovdqu t2, 2 * 32(r); \ |
378 | vmovdqu t3, 3 * 32(r); \ | 397 | vmovdqu t3, 3 * 32(r); \ |
@@ -382,14 +401,13 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
382 | * t2 &= rl; \ | 401 | * t2 &= rl; \ |
383 | * rr ^= rol32(t2, 1); \ | 402 | * rr ^= rol32(t2, 1); \ |
384 | */ \ | 403 | */ \ |
385 | vpbroadcastd krl, t0; /* only lowest 32-bit used */ \ | 404 | vpshufb tt0, t0, t3; \ |
386 | vpbroadcastb t0##_x, t3; \ | ||
387 | vpsrldq $1, t0, t0; \ | 405 | vpsrldq $1, t0, t0; \ |
388 | vpbroadcastb t0##_x, t2; \ | 406 | vpshufb tt0, t0, t2; \ |
389 | vpsrldq $1, t0, t0; \ | 407 | vpsrldq $1, t0, t0; \ |
390 | vpbroadcastb t0##_x, t1; \ | 408 | vpshufb tt0, t0, t1; \ |
391 | vpsrldq $1, t0, t0; \ | 409 | vpsrldq $1, t0, t0; \ |
392 | vpbroadcastb t0##_x, t0; \ | 410 | vpshufb tt0, t0, t0; \ |
393 | \ | 411 | \ |
394 | vpand 0 * 32(r), t0, t0; \ | 412 | vpand 0 * 32(r), t0, t0; \ |
395 | vpand 1 * 32(r), t1, t1; \ | 413 | vpand 1 * 32(r), t1, t1; \ |
@@ -403,6 +421,7 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
403 | vpxor 6 * 32(r), t2, t2; \ | 421 | vpxor 6 * 32(r), t2, t2; \ |
404 | vpxor 7 * 32(r), t3, t3; \ | 422 | vpxor 7 * 32(r), t3, t3; \ |
405 | vmovdqu t0, 4 * 32(r); \ | 423 | vmovdqu t0, 4 * 32(r); \ |
424 | vpbroadcastd klr, t0; /* only lowest 32-bit used */ \ | ||
406 | vmovdqu t1, 5 * 32(r); \ | 425 | vmovdqu t1, 5 * 32(r); \ |
407 | vmovdqu t2, 6 * 32(r); \ | 426 | vmovdqu t2, 6 * 32(r); \ |
408 | vmovdqu t3, 7 * 32(r); \ | 427 | vmovdqu t3, 7 * 32(r); \ |
@@ -413,14 +432,13 @@ ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) | |||
413 | * ll ^= t0; \ | 432 | * ll ^= t0; \ |
414 | */ \ | 433 | */ \ |
415 | \ | 434 | \ |
416 | vpbroadcastd klr, t0; /* only lowest 32-bit used */ \ | 435 | vpshufb tt0, t0, t3; \ |
417 | vpbroadcastb t0##_x, t3; \ | ||
418 | vpsrldq $1, t0, t0; \ | 436 | vpsrldq $1, t0, t0; \ |
419 | vpbroadcastb t0##_x, t2; \ | 437 | vpshufb tt0, t0, t2; \ |
420 | vpsrldq $1, t0, t0; \ | 438 | vpsrldq $1, t0, t0; \ |
421 | vpbroadcastb t0##_x, t1; \ | 439 | vpshufb tt0, t0, t1; \ |
422 | vpsrldq $1, t0, t0; \ | 440 | vpsrldq $1, t0, t0; \ |
423 | vpbroadcastb t0##_x, t0; \ | 441 | vpshufb tt0, t0, t0; \ |
424 | \ | 442 | \ |
425 | vpor l4, t0, t0; \ | 443 | vpor l4, t0, t0; \ |
426 | vpor l5, t1, t1; \ | 444 | vpor l5, t1, t1; \ |
diff --git a/arch/x86/crypto/crct10dif-pcl-asm_64.S b/arch/x86/crypto/crct10dif-pcl-asm_64.S new file mode 100644 index 000000000000..35e97569d05f --- /dev/null +++ b/arch/x86/crypto/crct10dif-pcl-asm_64.S | |||
@@ -0,0 +1,643 @@ | |||
1 | ######################################################################## | ||
2 | # Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions | ||
3 | # | ||
4 | # Copyright (c) 2013, Intel Corporation | ||
5 | # | ||
6 | # Authors: | ||
7 | # Erdinc Ozturk <erdinc.ozturk@intel.com> | ||
8 | # Vinodh Gopal <vinodh.gopal@intel.com> | ||
9 | # James Guilford <james.guilford@intel.com> | ||
10 | # Tim Chen <tim.c.chen@linux.intel.com> | ||
11 | # | ||
12 | # This software is available to you under a choice of one of two | ||
13 | # licenses. You may choose to be licensed under the terms of the GNU | ||
14 | # General Public License (GPL) Version 2, available from the file | ||
15 | # COPYING in the main directory of this source tree, or the | ||
16 | # OpenIB.org BSD license below: | ||
17 | # | ||
18 | # Redistribution and use in source and binary forms, with or without | ||
19 | # modification, are permitted provided that the following conditions are | ||
20 | # met: | ||
21 | # | ||
22 | # * Redistributions of source code must retain the above copyright | ||
23 | # notice, this list of conditions and the following disclaimer. | ||
24 | # | ||
25 | # * Redistributions in binary form must reproduce the above copyright | ||
26 | # notice, this list of conditions and the following disclaimer in the | ||
27 | # documentation and/or other materials provided with the | ||
28 | # distribution. | ||
29 | # | ||
30 | # * Neither the name of the Intel Corporation nor the names of its | ||
31 | # contributors may be used to endorse or promote products derived from | ||
32 | # this software without specific prior written permission. | ||
33 | # | ||
34 | # | ||
35 | # THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY | ||
36 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
37 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
38 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR | ||
39 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
40 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
41 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
42 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
43 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
44 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
45 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
46 | ######################################################################## | ||
47 | # Function API: | ||
48 | # UINT16 crc_t10dif_pcl( | ||
49 | # UINT16 init_crc, //initial CRC value, 16 bits | ||
50 | # const unsigned char *buf, //buffer pointer to calculate CRC on | ||
51 | # UINT64 len //buffer length in bytes (64-bit data) | ||
52 | # ); | ||
53 | # | ||
54 | # Reference paper titled "Fast CRC Computation for Generic | ||
55 | # Polynomials Using PCLMULQDQ Instruction" | ||
56 | # URL: http://www.intel.com/content/dam/www/public/us/en/documents | ||
57 | # /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf | ||
58 | # | ||
59 | # | ||
60 | |||
61 | #include <linux/linkage.h> | ||
62 | |||
63 | .text | ||
64 | |||
65 | #define arg1 %rdi | ||
66 | #define arg2 %rsi | ||
67 | #define arg3 %rdx | ||
68 | |||
69 | #define arg1_low32 %edi | ||
70 | |||
71 | ENTRY(crc_t10dif_pcl) | ||
72 | .align 16 | ||
73 | |||
74 | # adjust the 16-bit initial_crc value, scale it to 32 bits | ||
75 | shl $16, arg1_low32 | ||
76 | |||
77 | # Allocate Stack Space | ||
78 | mov %rsp, %rcx | ||
79 | sub $16*2, %rsp | ||
80 | # align stack to 16 byte boundary | ||
81 | and $~(0x10 - 1), %rsp | ||
82 | |||
83 | # check if smaller than 256 | ||
84 | cmp $256, arg3 | ||
85 | |||
86 | # for sizes less than 128, we can't fold 64B at a time... | ||
87 | jl _less_than_128 | ||
88 | |||
89 | |||
90 | # load the initial crc value | ||
91 | movd arg1_low32, %xmm10 # initial crc | ||
92 | |||
93 | # crc value does not need to be byte-reflected, but it needs | ||
94 | # to be moved to the high part of the register. | ||
95 | # because data will be byte-reflected and will align with | ||
96 | # initial crc at correct place. | ||
97 | pslldq $12, %xmm10 | ||
98 | |||
99 | movdqa SHUF_MASK(%rip), %xmm11 | ||
100 | # receive the initial 64B data, xor the initial crc value | ||
101 | movdqu 16*0(arg2), %xmm0 | ||
102 | movdqu 16*1(arg2), %xmm1 | ||
103 | movdqu 16*2(arg2), %xmm2 | ||
104 | movdqu 16*3(arg2), %xmm3 | ||
105 | movdqu 16*4(arg2), %xmm4 | ||
106 | movdqu 16*5(arg2), %xmm5 | ||
107 | movdqu 16*6(arg2), %xmm6 | ||
108 | movdqu 16*7(arg2), %xmm7 | ||
109 | |||
110 | pshufb %xmm11, %xmm0 | ||
111 | # XOR the initial_crc value | ||
112 | pxor %xmm10, %xmm0 | ||
113 | pshufb %xmm11, %xmm1 | ||
114 | pshufb %xmm11, %xmm2 | ||
115 | pshufb %xmm11, %xmm3 | ||
116 | pshufb %xmm11, %xmm4 | ||
117 | pshufb %xmm11, %xmm5 | ||
118 | pshufb %xmm11, %xmm6 | ||
119 | pshufb %xmm11, %xmm7 | ||
120 | |||
121 | movdqa rk3(%rip), %xmm10 #xmm10 has rk3 and rk4 | ||
122 | #imm value of pclmulqdq instruction | ||
123 | #will determine which constant to use | ||
124 | |||
125 | ################################################################# | ||
126 | # we subtract 256 instead of 128 to save one instruction from the loop | ||
127 | sub $256, arg3 | ||
128 | |||
129 | # at this section of the code, there is 64*x+y (0<=y<64) bytes of | ||
130 | # buffer. The _fold_64_B_loop will fold 64B at a time | ||
131 | # until we have 64+y Bytes of buffer | ||
132 | |||
133 | |||
134 | # fold 64B at a time. This section of the code folds 4 xmm | ||
135 | # registers in parallel | ||
136 | _fold_64_B_loop: | ||
137 | |||
138 | # update the buffer pointer | ||
139 | add $128, arg2 # buf += 64# | ||
140 | |||
141 | movdqu 16*0(arg2), %xmm9 | ||
142 | movdqu 16*1(arg2), %xmm12 | ||
143 | pshufb %xmm11, %xmm9 | ||
144 | pshufb %xmm11, %xmm12 | ||
145 | movdqa %xmm0, %xmm8 | ||
146 | movdqa %xmm1, %xmm13 | ||
147 | pclmulqdq $0x0 , %xmm10, %xmm0 | ||
148 | pclmulqdq $0x11, %xmm10, %xmm8 | ||
149 | pclmulqdq $0x0 , %xmm10, %xmm1 | ||
150 | pclmulqdq $0x11, %xmm10, %xmm13 | ||
151 | pxor %xmm9 , %xmm0 | ||
152 | xorps %xmm8 , %xmm0 | ||
153 | pxor %xmm12, %xmm1 | ||
154 | xorps %xmm13, %xmm1 | ||
155 | |||
156 | movdqu 16*2(arg2), %xmm9 | ||
157 | movdqu 16*3(arg2), %xmm12 | ||
158 | pshufb %xmm11, %xmm9 | ||
159 | pshufb %xmm11, %xmm12 | ||
160 | movdqa %xmm2, %xmm8 | ||
161 | movdqa %xmm3, %xmm13 | ||
162 | pclmulqdq $0x0, %xmm10, %xmm2 | ||
163 | pclmulqdq $0x11, %xmm10, %xmm8 | ||
164 | pclmulqdq $0x0, %xmm10, %xmm3 | ||
165 | pclmulqdq $0x11, %xmm10, %xmm13 | ||
166 | pxor %xmm9 , %xmm2 | ||
167 | xorps %xmm8 , %xmm2 | ||
168 | pxor %xmm12, %xmm3 | ||
169 | xorps %xmm13, %xmm3 | ||
170 | |||
171 | movdqu 16*4(arg2), %xmm9 | ||
172 | movdqu 16*5(arg2), %xmm12 | ||
173 | pshufb %xmm11, %xmm9 | ||
174 | pshufb %xmm11, %xmm12 | ||
175 | movdqa %xmm4, %xmm8 | ||
176 | movdqa %xmm5, %xmm13 | ||
177 | pclmulqdq $0x0, %xmm10, %xmm4 | ||
178 | pclmulqdq $0x11, %xmm10, %xmm8 | ||
179 | pclmulqdq $0x0, %xmm10, %xmm5 | ||
180 | pclmulqdq $0x11, %xmm10, %xmm13 | ||
181 | pxor %xmm9 , %xmm4 | ||
182 | xorps %xmm8 , %xmm4 | ||
183 | pxor %xmm12, %xmm5 | ||
184 | xorps %xmm13, %xmm5 | ||
185 | |||
186 | movdqu 16*6(arg2), %xmm9 | ||
187 | movdqu 16*7(arg2), %xmm12 | ||
188 | pshufb %xmm11, %xmm9 | ||
189 | pshufb %xmm11, %xmm12 | ||
190 | movdqa %xmm6 , %xmm8 | ||
191 | movdqa %xmm7 , %xmm13 | ||
192 | pclmulqdq $0x0 , %xmm10, %xmm6 | ||
193 | pclmulqdq $0x11, %xmm10, %xmm8 | ||
194 | pclmulqdq $0x0 , %xmm10, %xmm7 | ||
195 | pclmulqdq $0x11, %xmm10, %xmm13 | ||
196 | pxor %xmm9 , %xmm6 | ||
197 | xorps %xmm8 , %xmm6 | ||
198 | pxor %xmm12, %xmm7 | ||
199 | xorps %xmm13, %xmm7 | ||
200 | |||
201 | sub $128, arg3 | ||
202 | |||
203 | # check if there is another 64B in the buffer to be able to fold | ||
204 | jge _fold_64_B_loop | ||
205 | ################################################################## | ||
206 | |||
207 | |||
208 | add $128, arg2 | ||
209 | # at this point, the buffer pointer is pointing at the last y Bytes | ||
210 | # of the buffer the 64B of folded data is in 4 of the xmm | ||
211 | # registers: xmm0, xmm1, xmm2, xmm3 | ||
212 | |||
213 | |||
214 | # fold the 8 xmm registers to 1 xmm register with different constants | ||
215 | |||
216 | movdqa rk9(%rip), %xmm10 | ||
217 | movdqa %xmm0, %xmm8 | ||
218 | pclmulqdq $0x11, %xmm10, %xmm0 | ||
219 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
220 | pxor %xmm8, %xmm7 | ||
221 | xorps %xmm0, %xmm7 | ||
222 | |||
223 | movdqa rk11(%rip), %xmm10 | ||
224 | movdqa %xmm1, %xmm8 | ||
225 | pclmulqdq $0x11, %xmm10, %xmm1 | ||
226 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
227 | pxor %xmm8, %xmm7 | ||
228 | xorps %xmm1, %xmm7 | ||
229 | |||
230 | movdqa rk13(%rip), %xmm10 | ||
231 | movdqa %xmm2, %xmm8 | ||
232 | pclmulqdq $0x11, %xmm10, %xmm2 | ||
233 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
234 | pxor %xmm8, %xmm7 | ||
235 | pxor %xmm2, %xmm7 | ||
236 | |||
237 | movdqa rk15(%rip), %xmm10 | ||
238 | movdqa %xmm3, %xmm8 | ||
239 | pclmulqdq $0x11, %xmm10, %xmm3 | ||
240 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
241 | pxor %xmm8, %xmm7 | ||
242 | xorps %xmm3, %xmm7 | ||
243 | |||
244 | movdqa rk17(%rip), %xmm10 | ||
245 | movdqa %xmm4, %xmm8 | ||
246 | pclmulqdq $0x11, %xmm10, %xmm4 | ||
247 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
248 | pxor %xmm8, %xmm7 | ||
249 | pxor %xmm4, %xmm7 | ||
250 | |||
251 | movdqa rk19(%rip), %xmm10 | ||
252 | movdqa %xmm5, %xmm8 | ||
253 | pclmulqdq $0x11, %xmm10, %xmm5 | ||
254 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
255 | pxor %xmm8, %xmm7 | ||
256 | xorps %xmm5, %xmm7 | ||
257 | |||
258 | movdqa rk1(%rip), %xmm10 #xmm10 has rk1 and rk2 | ||
259 | #imm value of pclmulqdq instruction | ||
260 | #will determine which constant to use | ||
261 | movdqa %xmm6, %xmm8 | ||
262 | pclmulqdq $0x11, %xmm10, %xmm6 | ||
263 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
264 | pxor %xmm8, %xmm7 | ||
265 | pxor %xmm6, %xmm7 | ||
266 | |||
267 | |||
268 | # instead of 64, we add 48 to the loop counter to save 1 instruction | ||
269 | # from the loop instead of a cmp instruction, we use the negative | ||
270 | # flag with the jl instruction | ||
271 | add $128-16, arg3 | ||
272 | jl _final_reduction_for_128 | ||
273 | |||
274 | # now we have 16+y bytes left to reduce. 16 Bytes is in register xmm7 | ||
275 | # and the rest is in memory. We can fold 16 bytes at a time if y>=16 | ||
276 | # continue folding 16B at a time | ||
277 | |||
278 | _16B_reduction_loop: | ||
279 | movdqa %xmm7, %xmm8 | ||
280 | pclmulqdq $0x11, %xmm10, %xmm7 | ||
281 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
282 | pxor %xmm8, %xmm7 | ||
283 | movdqu (arg2), %xmm0 | ||
284 | pshufb %xmm11, %xmm0 | ||
285 | pxor %xmm0 , %xmm7 | ||
286 | add $16, arg2 | ||
287 | sub $16, arg3 | ||
288 | # instead of a cmp instruction, we utilize the flags with the | ||
289 | # jge instruction equivalent of: cmp arg3, 16-16 | ||
290 | # check if there is any more 16B in the buffer to be able to fold | ||
291 | jge _16B_reduction_loop | ||
292 | |||
293 | #now we have 16+z bytes left to reduce, where 0<= z < 16. | ||
294 | #first, we reduce the data in the xmm7 register | ||
295 | |||
296 | |||
297 | _final_reduction_for_128: | ||
298 | # check if any more data to fold. If not, compute the CRC of | ||
299 | # the final 128 bits | ||
300 | add $16, arg3 | ||
301 | je _128_done | ||
302 | |||
303 | # here we are getting data that is less than 16 bytes. | ||
304 | # since we know that there was data before the pointer, we can | ||
305 | # offset the input pointer before the actual point, to receive | ||
306 | # exactly 16 bytes. after that the registers need to be adjusted. | ||
307 | _get_last_two_xmms: | ||
308 | movdqa %xmm7, %xmm2 | ||
309 | |||
310 | movdqu -16(arg2, arg3), %xmm1 | ||
311 | pshufb %xmm11, %xmm1 | ||
312 | |||
313 | # get rid of the extra data that was loaded before | ||
314 | # load the shift constant | ||
315 | lea pshufb_shf_table+16(%rip), %rax | ||
316 | sub arg3, %rax | ||
317 | movdqu (%rax), %xmm0 | ||
318 | |||
319 | # shift xmm2 to the left by arg3 bytes | ||
320 | pshufb %xmm0, %xmm2 | ||
321 | |||
322 | # shift xmm7 to the right by 16-arg3 bytes | ||
323 | pxor mask1(%rip), %xmm0 | ||
324 | pshufb %xmm0, %xmm7 | ||
325 | pblendvb %xmm2, %xmm1 #xmm0 is implicit | ||
326 | |||
327 | # fold 16 Bytes | ||
328 | movdqa %xmm1, %xmm2 | ||
329 | movdqa %xmm7, %xmm8 | ||
330 | pclmulqdq $0x11, %xmm10, %xmm7 | ||
331 | pclmulqdq $0x0 , %xmm10, %xmm8 | ||
332 | pxor %xmm8, %xmm7 | ||
333 | pxor %xmm2, %xmm7 | ||
334 | |||
335 | _128_done: | ||
336 | # compute crc of a 128-bit value | ||
337 | movdqa rk5(%rip), %xmm10 # rk5 and rk6 in xmm10 | ||
338 | movdqa %xmm7, %xmm0 | ||
339 | |||
340 | #64b fold | ||
341 | pclmulqdq $0x1, %xmm10, %xmm7 | ||
342 | pslldq $8 , %xmm0 | ||
343 | pxor %xmm0, %xmm7 | ||
344 | |||
345 | #32b fold | ||
346 | movdqa %xmm7, %xmm0 | ||
347 | |||
348 | pand mask2(%rip), %xmm0 | ||
349 | |||
350 | psrldq $12, %xmm7 | ||
351 | pclmulqdq $0x10, %xmm10, %xmm7 | ||
352 | pxor %xmm0, %xmm7 | ||
353 | |||
354 | #barrett reduction | ||
355 | _barrett: | ||
356 | movdqa rk7(%rip), %xmm10 # rk7 and rk8 in xmm10 | ||
357 | movdqa %xmm7, %xmm0 | ||
358 | pclmulqdq $0x01, %xmm10, %xmm7 | ||
359 | pslldq $4, %xmm7 | ||
360 | pclmulqdq $0x11, %xmm10, %xmm7 | ||
361 | |||
362 | pslldq $4, %xmm7 | ||
363 | pxor %xmm0, %xmm7 | ||
364 | pextrd $1, %xmm7, %eax | ||
365 | |||
366 | _cleanup: | ||
367 | # scale the result back to 16 bits | ||
368 | shr $16, %eax | ||
369 | mov %rcx, %rsp | ||
370 | ret | ||
371 | |||
372 | ######################################################################## | ||
373 | |||
374 | .align 16 | ||
375 | _less_than_128: | ||
376 | |||
377 | # check if there is enough buffer to be able to fold 16B at a time | ||
378 | cmp $32, arg3 | ||
379 | jl _less_than_32 | ||
380 | movdqa SHUF_MASK(%rip), %xmm11 | ||
381 | |||
382 | # now if there is, load the constants | ||
383 | movdqa rk1(%rip), %xmm10 # rk1 and rk2 in xmm10 | ||
384 | |||
385 | movd arg1_low32, %xmm0 # get the initial crc value | ||
386 | pslldq $12, %xmm0 # align it to its correct place | ||
387 | movdqu (arg2), %xmm7 # load the plaintext | ||
388 | pshufb %xmm11, %xmm7 # byte-reflect the plaintext | ||
389 | pxor %xmm0, %xmm7 | ||
390 | |||
391 | |||
392 | # update the buffer pointer | ||
393 | add $16, arg2 | ||
394 | |||
395 | # update the counter. subtract 32 instead of 16 to save one | ||
396 | # instruction from the loop | ||
397 | sub $32, arg3 | ||
398 | |||
399 | jmp _16B_reduction_loop | ||
400 | |||
401 | |||
402 | .align 16 | ||
403 | _less_than_32: | ||
404 | # mov initial crc to the return value. this is necessary for | ||
405 | # zero-length buffers. | ||
406 | mov arg1_low32, %eax | ||
407 | test arg3, arg3 | ||
408 | je _cleanup | ||
409 | |||
410 | movdqa SHUF_MASK(%rip), %xmm11 | ||
411 | |||
412 | movd arg1_low32, %xmm0 # get the initial crc value | ||
413 | pslldq $12, %xmm0 # align it to its correct place | ||
414 | |||
415 | cmp $16, arg3 | ||
416 | je _exact_16_left | ||
417 | jl _less_than_16_left | ||
418 | |||
419 | movdqu (arg2), %xmm7 # load the plaintext | ||
420 | pshufb %xmm11, %xmm7 # byte-reflect the plaintext | ||
421 | pxor %xmm0 , %xmm7 # xor the initial crc value | ||
422 | add $16, arg2 | ||
423 | sub $16, arg3 | ||
424 | movdqa rk1(%rip), %xmm10 # rk1 and rk2 in xmm10 | ||
425 | jmp _get_last_two_xmms | ||
426 | |||
427 | |||
428 | .align 16 | ||
429 | _less_than_16_left: | ||
430 | # use stack space to load data less than 16 bytes, zero-out | ||
431 | # the 16B in memory first. | ||
432 | |||
433 | pxor %xmm1, %xmm1 | ||
434 | mov %rsp, %r11 | ||
435 | movdqa %xmm1, (%r11) | ||
436 | |||
437 | cmp $4, arg3 | ||
438 | jl _only_less_than_4 | ||
439 | |||
440 | # backup the counter value | ||
441 | mov arg3, %r9 | ||
442 | cmp $8, arg3 | ||
443 | jl _less_than_8_left | ||
444 | |||
445 | # load 8 Bytes | ||
446 | mov (arg2), %rax | ||
447 | mov %rax, (%r11) | ||
448 | add $8, %r11 | ||
449 | sub $8, arg3 | ||
450 | add $8, arg2 | ||
451 | _less_than_8_left: | ||
452 | |||
453 | cmp $4, arg3 | ||
454 | jl _less_than_4_left | ||
455 | |||
456 | # load 4 Bytes | ||
457 | mov (arg2), %eax | ||
458 | mov %eax, (%r11) | ||
459 | add $4, %r11 | ||
460 | sub $4, arg3 | ||
461 | add $4, arg2 | ||
462 | _less_than_4_left: | ||
463 | |||
464 | cmp $2, arg3 | ||
465 | jl _less_than_2_left | ||
466 | |||
467 | # load 2 Bytes | ||
468 | mov (arg2), %ax | ||
469 | mov %ax, (%r11) | ||
470 | add $2, %r11 | ||
471 | sub $2, arg3 | ||
472 | add $2, arg2 | ||
473 | _less_than_2_left: | ||
474 | cmp $1, arg3 | ||
475 | jl _zero_left | ||
476 | |||
477 | # load 1 Byte | ||
478 | mov (arg2), %al | ||
479 | mov %al, (%r11) | ||
480 | _zero_left: | ||
481 | movdqa (%rsp), %xmm7 | ||
482 | pshufb %xmm11, %xmm7 | ||
483 | pxor %xmm0 , %xmm7 # xor the initial crc value | ||
484 | |||
485 | # shl r9, 4 | ||
486 | lea pshufb_shf_table+16(%rip), %rax | ||
487 | sub %r9, %rax | ||
488 | movdqu (%rax), %xmm0 | ||
489 | pxor mask1(%rip), %xmm0 | ||
490 | |||
491 | pshufb %xmm0, %xmm7 | ||
492 | jmp _128_done | ||
493 | |||
494 | .align 16 | ||
495 | _exact_16_left: | ||
496 | movdqu (arg2), %xmm7 | ||
497 | pshufb %xmm11, %xmm7 | ||
498 | pxor %xmm0 , %xmm7 # xor the initial crc value | ||
499 | |||
500 | jmp _128_done | ||
501 | |||
502 | _only_less_than_4: | ||
503 | cmp $3, arg3 | ||
504 | jl _only_less_than_3 | ||
505 | |||
506 | # load 3 Bytes | ||
507 | mov (arg2), %al | ||
508 | mov %al, (%r11) | ||
509 | |||
510 | mov 1(arg2), %al | ||
511 | mov %al, 1(%r11) | ||
512 | |||
513 | mov 2(arg2), %al | ||
514 | mov %al, 2(%r11) | ||
515 | |||
516 | movdqa (%rsp), %xmm7 | ||
517 | pshufb %xmm11, %xmm7 | ||
518 | pxor %xmm0 , %xmm7 # xor the initial crc value | ||
519 | |||
520 | psrldq $5, %xmm7 | ||
521 | |||
522 | jmp _barrett | ||
523 | _only_less_than_3: | ||
524 | cmp $2, arg3 | ||
525 | jl _only_less_than_2 | ||
526 | |||
527 | # load 2 Bytes | ||
528 | mov (arg2), %al | ||
529 | mov %al, (%r11) | ||
530 | |||
531 | mov 1(arg2), %al | ||
532 | mov %al, 1(%r11) | ||
533 | |||
534 | movdqa (%rsp), %xmm7 | ||
535 | pshufb %xmm11, %xmm7 | ||
536 | pxor %xmm0 , %xmm7 # xor the initial crc value | ||
537 | |||
538 | psrldq $6, %xmm7 | ||
539 | |||
540 | jmp _barrett | ||
541 | _only_less_than_2: | ||
542 | |||
543 | # load 1 Byte | ||
544 | mov (arg2), %al | ||
545 | mov %al, (%r11) | ||
546 | |||
547 | movdqa (%rsp), %xmm7 | ||
548 | pshufb %xmm11, %xmm7 | ||
549 | pxor %xmm0 , %xmm7 # xor the initial crc value | ||
550 | |||
551 | psrldq $7, %xmm7 | ||
552 | |||
553 | jmp _barrett | ||
554 | |||
555 | ENDPROC(crc_t10dif_pcl) | ||
556 | |||
557 | .data | ||
558 | |||
559 | # precomputed constants | ||
560 | # these constants are precomputed from the poly: | ||
561 | # 0x8bb70000 (0x8bb7 scaled to 32 bits) | ||
562 | .align 16 | ||
563 | # Q = 0x18BB70000 | ||
564 | # rk1 = 2^(32*3) mod Q << 32 | ||
565 | # rk2 = 2^(32*5) mod Q << 32 | ||
566 | # rk3 = 2^(32*15) mod Q << 32 | ||
567 | # rk4 = 2^(32*17) mod Q << 32 | ||
568 | # rk5 = 2^(32*3) mod Q << 32 | ||
569 | # rk6 = 2^(32*2) mod Q << 32 | ||
570 | # rk7 = floor(2^64/Q) | ||
571 | # rk8 = Q | ||
572 | rk1: | ||
573 | .quad 0x2d56000000000000 | ||
574 | rk2: | ||
575 | .quad 0x06df000000000000 | ||
576 | rk3: | ||
577 | .quad 0x9d9d000000000000 | ||
578 | rk4: | ||
579 | .quad 0x7cf5000000000000 | ||
580 | rk5: | ||
581 | .quad 0x2d56000000000000 | ||
582 | rk6: | ||
583 | .quad 0x1368000000000000 | ||
584 | rk7: | ||
585 | .quad 0x00000001f65a57f8 | ||
586 | rk8: | ||
587 | .quad 0x000000018bb70000 | ||
588 | |||
589 | rk9: | ||
590 | .quad 0xceae000000000000 | ||
591 | rk10: | ||
592 | .quad 0xbfd6000000000000 | ||
593 | rk11: | ||
594 | .quad 0x1e16000000000000 | ||
595 | rk12: | ||
596 | .quad 0x713c000000000000 | ||
597 | rk13: | ||
598 | .quad 0xf7f9000000000000 | ||
599 | rk14: | ||
600 | .quad 0x80a6000000000000 | ||
601 | rk15: | ||
602 | .quad 0x044c000000000000 | ||
603 | rk16: | ||
604 | .quad 0xe658000000000000 | ||
605 | rk17: | ||
606 | .quad 0xad18000000000000 | ||
607 | rk18: | ||
608 | .quad 0xa497000000000000 | ||
609 | rk19: | ||
610 | .quad 0x6ee3000000000000 | ||
611 | rk20: | ||
612 | .quad 0xe7b5000000000000 | ||
613 | |||
614 | |||
615 | |||
616 | mask1: | ||
617 | .octa 0x80808080808080808080808080808080 | ||
618 | mask2: | ||
619 | .octa 0x00000000FFFFFFFFFFFFFFFFFFFFFFFF | ||
620 | |||
621 | SHUF_MASK: | ||
622 | .octa 0x000102030405060708090A0B0C0D0E0F | ||
623 | |||
624 | pshufb_shf_table: | ||
625 | # use these values for shift constants for the pshufb instruction | ||
626 | # different alignments result in values as shown: | ||
627 | # DDQ 0x008f8e8d8c8b8a898887868584838281 # shl 15 (16-1) / shr1 | ||
628 | # DDQ 0x01008f8e8d8c8b8a8988878685848382 # shl 14 (16-3) / shr2 | ||
629 | # DDQ 0x0201008f8e8d8c8b8a89888786858483 # shl 13 (16-4) / shr3 | ||
630 | # DDQ 0x030201008f8e8d8c8b8a898887868584 # shl 12 (16-4) / shr4 | ||
631 | # DDQ 0x04030201008f8e8d8c8b8a8988878685 # shl 11 (16-5) / shr5 | ||
632 | # DDQ 0x0504030201008f8e8d8c8b8a89888786 # shl 10 (16-6) / shr6 | ||
633 | # DDQ 0x060504030201008f8e8d8c8b8a898887 # shl 9 (16-7) / shr7 | ||
634 | # DDQ 0x07060504030201008f8e8d8c8b8a8988 # shl 8 (16-8) / shr8 | ||
635 | # DDQ 0x0807060504030201008f8e8d8c8b8a89 # shl 7 (16-9) / shr9 | ||
636 | # DDQ 0x090807060504030201008f8e8d8c8b8a # shl 6 (16-10) / shr10 | ||
637 | # DDQ 0x0a090807060504030201008f8e8d8c8b # shl 5 (16-11) / shr11 | ||
638 | # DDQ 0x0b0a090807060504030201008f8e8d8c # shl 4 (16-12) / shr12 | ||
639 | # DDQ 0x0c0b0a090807060504030201008f8e8d # shl 3 (16-13) / shr13 | ||
640 | # DDQ 0x0d0c0b0a090807060504030201008f8e # shl 2 (16-14) / shr14 | ||
641 | # DDQ 0x0e0d0c0b0a090807060504030201008f # shl 1 (16-15) / shr15 | ||
642 | .octa 0x8f8e8d8c8b8a89888786858483828100 | ||
643 | .octa 0x000e0d0c0b0a09080706050403020100 | ||
diff --git a/arch/x86/crypto/crct10dif-pclmul_glue.c b/arch/x86/crypto/crct10dif-pclmul_glue.c new file mode 100644 index 000000000000..7845d7fd54c0 --- /dev/null +++ b/arch/x86/crypto/crct10dif-pclmul_glue.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * T10 Data Integrity Field CRC16 Crypto Transform using PCLMULQDQ Instructions | ||
5 | * | ||
6 | * Copyright (C) 2013 Intel Corporation | ||
7 | * Author: Tim Chen <tim.c.chen@linux.intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
15 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
17 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
18 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
19 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | * SOFTWARE. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/types.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/crc-t10dif.h> | ||
28 | #include <crypto/internal/hash.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <asm/i387.h> | ||
33 | #include <asm/cpufeature.h> | ||
34 | #include <asm/cpu_device_id.h> | ||
35 | |||
36 | asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf, | ||
37 | size_t len); | ||
38 | |||
39 | struct chksum_desc_ctx { | ||
40 | __u16 crc; | ||
41 | }; | ||
42 | |||
43 | /* | ||
44 | * Steps through buffer one byte at at time, calculates reflected | ||
45 | * crc using table. | ||
46 | */ | ||
47 | |||
48 | static int chksum_init(struct shash_desc *desc) | ||
49 | { | ||
50 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
51 | |||
52 | ctx->crc = 0; | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int chksum_update(struct shash_desc *desc, const u8 *data, | ||
58 | unsigned int length) | ||
59 | { | ||
60 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
61 | |||
62 | if (irq_fpu_usable()) { | ||
63 | kernel_fpu_begin(); | ||
64 | ctx->crc = crc_t10dif_pcl(ctx->crc, data, length); | ||
65 | kernel_fpu_end(); | ||
66 | } else | ||
67 | ctx->crc = crc_t10dif_generic(ctx->crc, data, length); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int chksum_final(struct shash_desc *desc, u8 *out) | ||
72 | { | ||
73 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
74 | |||
75 | *(__u16 *)out = ctx->crc; | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int __chksum_finup(__u16 *crcp, const u8 *data, unsigned int len, | ||
80 | u8 *out) | ||
81 | { | ||
82 | if (irq_fpu_usable()) { | ||
83 | kernel_fpu_begin(); | ||
84 | *(__u16 *)out = crc_t10dif_pcl(*crcp, data, len); | ||
85 | kernel_fpu_end(); | ||
86 | } else | ||
87 | *(__u16 *)out = crc_t10dif_generic(*crcp, data, len); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int chksum_finup(struct shash_desc *desc, const u8 *data, | ||
92 | unsigned int len, u8 *out) | ||
93 | { | ||
94 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
95 | |||
96 | return __chksum_finup(&ctx->crc, data, len, out); | ||
97 | } | ||
98 | |||
99 | static int chksum_digest(struct shash_desc *desc, const u8 *data, | ||
100 | unsigned int length, u8 *out) | ||
101 | { | ||
102 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
103 | |||
104 | return __chksum_finup(&ctx->crc, data, length, out); | ||
105 | } | ||
106 | |||
107 | static struct shash_alg alg = { | ||
108 | .digestsize = CRC_T10DIF_DIGEST_SIZE, | ||
109 | .init = chksum_init, | ||
110 | .update = chksum_update, | ||
111 | .final = chksum_final, | ||
112 | .finup = chksum_finup, | ||
113 | .digest = chksum_digest, | ||
114 | .descsize = sizeof(struct chksum_desc_ctx), | ||
115 | .base = { | ||
116 | .cra_name = "crct10dif", | ||
117 | .cra_driver_name = "crct10dif-pclmul", | ||
118 | .cra_priority = 200, | ||
119 | .cra_blocksize = CRC_T10DIF_BLOCK_SIZE, | ||
120 | .cra_module = THIS_MODULE, | ||
121 | } | ||
122 | }; | ||
123 | |||
124 | static const struct x86_cpu_id crct10dif_cpu_id[] = { | ||
125 | X86_FEATURE_MATCH(X86_FEATURE_PCLMULQDQ), | ||
126 | {} | ||
127 | }; | ||
128 | MODULE_DEVICE_TABLE(x86cpu, crct10dif_cpu_id); | ||
129 | |||
130 | static int __init crct10dif_intel_mod_init(void) | ||
131 | { | ||
132 | if (!x86_match_cpu(crct10dif_cpu_id)) | ||
133 | return -ENODEV; | ||
134 | |||
135 | return crypto_register_shash(&alg); | ||
136 | } | ||
137 | |||
138 | static void __exit crct10dif_intel_mod_fini(void) | ||
139 | { | ||
140 | crypto_unregister_shash(&alg); | ||
141 | } | ||
142 | |||
143 | module_init(crct10dif_intel_mod_init); | ||
144 | module_exit(crct10dif_intel_mod_fini); | ||
145 | |||
146 | MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>"); | ||
147 | MODULE_DESCRIPTION("T10 DIF CRC calculation accelerated with PCLMULQDQ."); | ||
148 | MODULE_LICENSE("GPL"); | ||
149 | |||
150 | MODULE_ALIAS("crct10dif"); | ||
151 | MODULE_ALIAS("crct10dif-pclmul"); | ||
diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c index 597d4da69656..50226c4b86ed 100644 --- a/arch/x86/crypto/sha256_ssse3_glue.c +++ b/arch/x86/crypto/sha256_ssse3_glue.c | |||
@@ -187,7 +187,36 @@ static int sha256_ssse3_import(struct shash_desc *desc, const void *in) | |||
187 | return 0; | 187 | return 0; |
188 | } | 188 | } |
189 | 189 | ||
190 | static struct shash_alg alg = { | 190 | static int sha224_ssse3_init(struct shash_desc *desc) |
191 | { | ||
192 | struct sha256_state *sctx = shash_desc_ctx(desc); | ||
193 | |||
194 | sctx->state[0] = SHA224_H0; | ||
195 | sctx->state[1] = SHA224_H1; | ||
196 | sctx->state[2] = SHA224_H2; | ||
197 | sctx->state[3] = SHA224_H3; | ||
198 | sctx->state[4] = SHA224_H4; | ||
199 | sctx->state[5] = SHA224_H5; | ||
200 | sctx->state[6] = SHA224_H6; | ||
201 | sctx->state[7] = SHA224_H7; | ||
202 | sctx->count = 0; | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int sha224_ssse3_final(struct shash_desc *desc, u8 *hash) | ||
208 | { | ||
209 | u8 D[SHA256_DIGEST_SIZE]; | ||
210 | |||
211 | sha256_ssse3_final(desc, D); | ||
212 | |||
213 | memcpy(hash, D, SHA224_DIGEST_SIZE); | ||
214 | memset(D, 0, SHA256_DIGEST_SIZE); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static struct shash_alg algs[] = { { | ||
191 | .digestsize = SHA256_DIGEST_SIZE, | 220 | .digestsize = SHA256_DIGEST_SIZE, |
192 | .init = sha256_ssse3_init, | 221 | .init = sha256_ssse3_init, |
193 | .update = sha256_ssse3_update, | 222 | .update = sha256_ssse3_update, |
@@ -204,7 +233,24 @@ static struct shash_alg alg = { | |||
204 | .cra_blocksize = SHA256_BLOCK_SIZE, | 233 | .cra_blocksize = SHA256_BLOCK_SIZE, |
205 | .cra_module = THIS_MODULE, | 234 | .cra_module = THIS_MODULE, |
206 | } | 235 | } |
207 | }; | 236 | }, { |
237 | .digestsize = SHA224_DIGEST_SIZE, | ||
238 | .init = sha224_ssse3_init, | ||
239 | .update = sha256_ssse3_update, | ||
240 | .final = sha224_ssse3_final, | ||
241 | .export = sha256_ssse3_export, | ||
242 | .import = sha256_ssse3_import, | ||
243 | .descsize = sizeof(struct sha256_state), | ||
244 | .statesize = sizeof(struct sha256_state), | ||
245 | .base = { | ||
246 | .cra_name = "sha224", | ||
247 | .cra_driver_name = "sha224-ssse3", | ||
248 | .cra_priority = 150, | ||
249 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
250 | .cra_blocksize = SHA224_BLOCK_SIZE, | ||
251 | .cra_module = THIS_MODULE, | ||
252 | } | ||
253 | } }; | ||
208 | 254 | ||
209 | #ifdef CONFIG_AS_AVX | 255 | #ifdef CONFIG_AS_AVX |
210 | static bool __init avx_usable(void) | 256 | static bool __init avx_usable(void) |
@@ -227,7 +273,7 @@ static bool __init avx_usable(void) | |||
227 | 273 | ||
228 | static int __init sha256_ssse3_mod_init(void) | 274 | static int __init sha256_ssse3_mod_init(void) |
229 | { | 275 | { |
230 | /* test for SSE3 first */ | 276 | /* test for SSSE3 first */ |
231 | if (cpu_has_ssse3) | 277 | if (cpu_has_ssse3) |
232 | sha256_transform_asm = sha256_transform_ssse3; | 278 | sha256_transform_asm = sha256_transform_ssse3; |
233 | 279 | ||
@@ -254,7 +300,7 @@ static int __init sha256_ssse3_mod_init(void) | |||
254 | else | 300 | else |
255 | #endif | 301 | #endif |
256 | pr_info("Using SSSE3 optimized SHA-256 implementation\n"); | 302 | pr_info("Using SSSE3 optimized SHA-256 implementation\n"); |
257 | return crypto_register_shash(&alg); | 303 | return crypto_register_shashes(algs, ARRAY_SIZE(algs)); |
258 | } | 304 | } |
259 | pr_info("Neither AVX nor SSSE3 is available/usable.\n"); | 305 | pr_info("Neither AVX nor SSSE3 is available/usable.\n"); |
260 | 306 | ||
@@ -263,7 +309,7 @@ static int __init sha256_ssse3_mod_init(void) | |||
263 | 309 | ||
264 | static void __exit sha256_ssse3_mod_fini(void) | 310 | static void __exit sha256_ssse3_mod_fini(void) |
265 | { | 311 | { |
266 | crypto_unregister_shash(&alg); | 312 | crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); |
267 | } | 313 | } |
268 | 314 | ||
269 | module_init(sha256_ssse3_mod_init); | 315 | module_init(sha256_ssse3_mod_init); |
@@ -273,3 +319,4 @@ MODULE_LICENSE("GPL"); | |||
273 | MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated"); | 319 | MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated"); |
274 | 320 | ||
275 | MODULE_ALIAS("sha256"); | 321 | MODULE_ALIAS("sha256"); |
322 | MODULE_ALIAS("sha384"); | ||
diff --git a/arch/x86/crypto/sha512_ssse3_glue.c b/arch/x86/crypto/sha512_ssse3_glue.c index 6cbd8df348d2..f30cd10293f0 100644 --- a/arch/x86/crypto/sha512_ssse3_glue.c +++ b/arch/x86/crypto/sha512_ssse3_glue.c | |||
@@ -194,7 +194,37 @@ static int sha512_ssse3_import(struct shash_desc *desc, const void *in) | |||
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | 196 | ||
197 | static struct shash_alg alg = { | 197 | static int sha384_ssse3_init(struct shash_desc *desc) |
198 | { | ||
199 | struct sha512_state *sctx = shash_desc_ctx(desc); | ||
200 | |||
201 | sctx->state[0] = SHA384_H0; | ||
202 | sctx->state[1] = SHA384_H1; | ||
203 | sctx->state[2] = SHA384_H2; | ||
204 | sctx->state[3] = SHA384_H3; | ||
205 | sctx->state[4] = SHA384_H4; | ||
206 | sctx->state[5] = SHA384_H5; | ||
207 | sctx->state[6] = SHA384_H6; | ||
208 | sctx->state[7] = SHA384_H7; | ||
209 | |||
210 | sctx->count[0] = sctx->count[1] = 0; | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int sha384_ssse3_final(struct shash_desc *desc, u8 *hash) | ||
216 | { | ||
217 | u8 D[SHA512_DIGEST_SIZE]; | ||
218 | |||
219 | sha512_ssse3_final(desc, D); | ||
220 | |||
221 | memcpy(hash, D, SHA384_DIGEST_SIZE); | ||
222 | memset(D, 0, SHA512_DIGEST_SIZE); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static struct shash_alg algs[] = { { | ||
198 | .digestsize = SHA512_DIGEST_SIZE, | 228 | .digestsize = SHA512_DIGEST_SIZE, |
199 | .init = sha512_ssse3_init, | 229 | .init = sha512_ssse3_init, |
200 | .update = sha512_ssse3_update, | 230 | .update = sha512_ssse3_update, |
@@ -211,7 +241,24 @@ static struct shash_alg alg = { | |||
211 | .cra_blocksize = SHA512_BLOCK_SIZE, | 241 | .cra_blocksize = SHA512_BLOCK_SIZE, |
212 | .cra_module = THIS_MODULE, | 242 | .cra_module = THIS_MODULE, |
213 | } | 243 | } |
214 | }; | 244 | }, { |
245 | .digestsize = SHA384_DIGEST_SIZE, | ||
246 | .init = sha384_ssse3_init, | ||
247 | .update = sha512_ssse3_update, | ||
248 | .final = sha384_ssse3_final, | ||
249 | .export = sha512_ssse3_export, | ||
250 | .import = sha512_ssse3_import, | ||
251 | .descsize = sizeof(struct sha512_state), | ||
252 | .statesize = sizeof(struct sha512_state), | ||
253 | .base = { | ||
254 | .cra_name = "sha384", | ||
255 | .cra_driver_name = "sha384-ssse3", | ||
256 | .cra_priority = 150, | ||
257 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
258 | .cra_blocksize = SHA384_BLOCK_SIZE, | ||
259 | .cra_module = THIS_MODULE, | ||
260 | } | ||
261 | } }; | ||
215 | 262 | ||
216 | #ifdef CONFIG_AS_AVX | 263 | #ifdef CONFIG_AS_AVX |
217 | static bool __init avx_usable(void) | 264 | static bool __init avx_usable(void) |
@@ -234,7 +281,7 @@ static bool __init avx_usable(void) | |||
234 | 281 | ||
235 | static int __init sha512_ssse3_mod_init(void) | 282 | static int __init sha512_ssse3_mod_init(void) |
236 | { | 283 | { |
237 | /* test for SSE3 first */ | 284 | /* test for SSSE3 first */ |
238 | if (cpu_has_ssse3) | 285 | if (cpu_has_ssse3) |
239 | sha512_transform_asm = sha512_transform_ssse3; | 286 | sha512_transform_asm = sha512_transform_ssse3; |
240 | 287 | ||
@@ -261,7 +308,7 @@ static int __init sha512_ssse3_mod_init(void) | |||
261 | else | 308 | else |
262 | #endif | 309 | #endif |
263 | pr_info("Using SSSE3 optimized SHA-512 implementation\n"); | 310 | pr_info("Using SSSE3 optimized SHA-512 implementation\n"); |
264 | return crypto_register_shash(&alg); | 311 | return crypto_register_shashes(algs, ARRAY_SIZE(algs)); |
265 | } | 312 | } |
266 | pr_info("Neither AVX nor SSSE3 is available/usable.\n"); | 313 | pr_info("Neither AVX nor SSSE3 is available/usable.\n"); |
267 | 314 | ||
@@ -270,7 +317,7 @@ static int __init sha512_ssse3_mod_init(void) | |||
270 | 317 | ||
271 | static void __exit sha512_ssse3_mod_fini(void) | 318 | static void __exit sha512_ssse3_mod_fini(void) |
272 | { | 319 | { |
273 | crypto_unregister_shash(&alg); | 320 | crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); |
274 | } | 321 | } |
275 | 322 | ||
276 | module_init(sha512_ssse3_mod_init); | 323 | module_init(sha512_ssse3_mod_init); |
@@ -280,3 +327,4 @@ MODULE_LICENSE("GPL"); | |||
280 | MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, Supplemental SSE3 accelerated"); | 327 | MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, Supplemental SSE3 accelerated"); |
281 | 328 | ||
282 | MODULE_ALIAS("sha512"); | 329 | MODULE_ALIAS("sha512"); |
330 | MODULE_ALIAS("sha384"); | ||
diff --git a/arch/x86/crypto/twofish-avx2-asm_64.S b/arch/x86/crypto/twofish-avx2-asm_64.S deleted file mode 100644 index e1a83b9cd389..000000000000 --- a/arch/x86/crypto/twofish-avx2-asm_64.S +++ /dev/null | |||
@@ -1,600 +0,0 @@ | |||
1 | /* | ||
2 | * x86_64/AVX2 assembler optimized version of Twofish | ||
3 | * | ||
4 | * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/linkage.h> | ||
14 | #include "glue_helper-asm-avx2.S" | ||
15 | |||
16 | .file "twofish-avx2-asm_64.S" | ||
17 | |||
18 | .data | ||
19 | .align 16 | ||
20 | |||
21 | .Lvpshufb_mask0: | ||
22 | .long 0x80808000 | ||
23 | .long 0x80808004 | ||
24 | .long 0x80808008 | ||
25 | .long 0x8080800c | ||
26 | |||
27 | .Lbswap128_mask: | ||
28 | .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 | ||
29 | .Lxts_gf128mul_and_shl1_mask_0: | ||
30 | .byte 0x87, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 | ||
31 | .Lxts_gf128mul_and_shl1_mask_1: | ||
32 | .byte 0x0e, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 | ||
33 | |||
34 | .text | ||
35 | |||
36 | /* structure of crypto context */ | ||
37 | #define s0 0 | ||
38 | #define s1 1024 | ||
39 | #define s2 2048 | ||
40 | #define s3 3072 | ||
41 | #define w 4096 | ||
42 | #define k 4128 | ||
43 | |||
44 | /* register macros */ | ||
45 | #define CTX %rdi | ||
46 | |||
47 | #define RS0 CTX | ||
48 | #define RS1 %r8 | ||
49 | #define RS2 %r9 | ||
50 | #define RS3 %r10 | ||
51 | #define RK %r11 | ||
52 | #define RW %rax | ||
53 | #define RROUND %r12 | ||
54 | #define RROUNDd %r12d | ||
55 | |||
56 | #define RA0 %ymm8 | ||
57 | #define RB0 %ymm9 | ||
58 | #define RC0 %ymm10 | ||
59 | #define RD0 %ymm11 | ||
60 | #define RA1 %ymm12 | ||
61 | #define RB1 %ymm13 | ||
62 | #define RC1 %ymm14 | ||
63 | #define RD1 %ymm15 | ||
64 | |||
65 | /* temp regs */ | ||
66 | #define RX0 %ymm0 | ||
67 | #define RY0 %ymm1 | ||
68 | #define RX1 %ymm2 | ||
69 | #define RY1 %ymm3 | ||
70 | #define RT0 %ymm4 | ||
71 | #define RIDX %ymm5 | ||
72 | |||
73 | #define RX0x %xmm0 | ||
74 | #define RY0x %xmm1 | ||
75 | #define RX1x %xmm2 | ||
76 | #define RY1x %xmm3 | ||
77 | #define RT0x %xmm4 | ||
78 | |||
79 | /* vpgatherdd mask and '-1' */ | ||
80 | #define RNOT %ymm6 | ||
81 | |||
82 | /* byte mask, (-1 >> 24) */ | ||
83 | #define RBYTE %ymm7 | ||
84 | |||
85 | /********************************************************************** | ||
86 | 16-way AVX2 twofish | ||
87 | **********************************************************************/ | ||
88 | #define init_round_constants() \ | ||
89 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
90 | vpsrld $24, RNOT, RBYTE; \ | ||
91 | leaq k(CTX), RK; \ | ||
92 | leaq w(CTX), RW; \ | ||
93 | leaq s1(CTX), RS1; \ | ||
94 | leaq s2(CTX), RS2; \ | ||
95 | leaq s3(CTX), RS3; \ | ||
96 | |||
97 | #define g16(ab, rs0, rs1, rs2, rs3, xy) \ | ||
98 | vpand RBYTE, ab ## 0, RIDX; \ | ||
99 | vpgatherdd RNOT, (rs0, RIDX, 4), xy ## 0; \ | ||
100 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
101 | \ | ||
102 | vpand RBYTE, ab ## 1, RIDX; \ | ||
103 | vpgatherdd RNOT, (rs0, RIDX, 4), xy ## 1; \ | ||
104 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
105 | \ | ||
106 | vpsrld $8, ab ## 0, RIDX; \ | ||
107 | vpand RBYTE, RIDX, RIDX; \ | ||
108 | vpgatherdd RNOT, (rs1, RIDX, 4), RT0; \ | ||
109 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
110 | vpxor RT0, xy ## 0, xy ## 0; \ | ||
111 | \ | ||
112 | vpsrld $8, ab ## 1, RIDX; \ | ||
113 | vpand RBYTE, RIDX, RIDX; \ | ||
114 | vpgatherdd RNOT, (rs1, RIDX, 4), RT0; \ | ||
115 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
116 | vpxor RT0, xy ## 1, xy ## 1; \ | ||
117 | \ | ||
118 | vpsrld $16, ab ## 0, RIDX; \ | ||
119 | vpand RBYTE, RIDX, RIDX; \ | ||
120 | vpgatherdd RNOT, (rs2, RIDX, 4), RT0; \ | ||
121 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
122 | vpxor RT0, xy ## 0, xy ## 0; \ | ||
123 | \ | ||
124 | vpsrld $16, ab ## 1, RIDX; \ | ||
125 | vpand RBYTE, RIDX, RIDX; \ | ||
126 | vpgatherdd RNOT, (rs2, RIDX, 4), RT0; \ | ||
127 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
128 | vpxor RT0, xy ## 1, xy ## 1; \ | ||
129 | \ | ||
130 | vpsrld $24, ab ## 0, RIDX; \ | ||
131 | vpgatherdd RNOT, (rs3, RIDX, 4), RT0; \ | ||
132 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
133 | vpxor RT0, xy ## 0, xy ## 0; \ | ||
134 | \ | ||
135 | vpsrld $24, ab ## 1, RIDX; \ | ||
136 | vpgatherdd RNOT, (rs3, RIDX, 4), RT0; \ | ||
137 | vpcmpeqd RNOT, RNOT, RNOT; \ | ||
138 | vpxor RT0, xy ## 1, xy ## 1; | ||
139 | |||
140 | #define g1_16(a, x) \ | ||
141 | g16(a, RS0, RS1, RS2, RS3, x); | ||
142 | |||
143 | #define g2_16(b, y) \ | ||
144 | g16(b, RS1, RS2, RS3, RS0, y); | ||
145 | |||
146 | #define encrypt_round_end16(a, b, c, d, nk) \ | ||
147 | vpaddd RY0, RX0, RX0; \ | ||
148 | vpaddd RX0, RY0, RY0; \ | ||
149 | vpbroadcastd nk(RK,RROUND,8), RT0; \ | ||
150 | vpaddd RT0, RX0, RX0; \ | ||
151 | vpbroadcastd 4+nk(RK,RROUND,8), RT0; \ | ||
152 | vpaddd RT0, RY0, RY0; \ | ||
153 | \ | ||
154 | vpxor RY0, d ## 0, d ## 0; \ | ||
155 | \ | ||
156 | vpxor RX0, c ## 0, c ## 0; \ | ||
157 | vpsrld $1, c ## 0, RT0; \ | ||
158 | vpslld $31, c ## 0, c ## 0; \ | ||
159 | vpor RT0, c ## 0, c ## 0; \ | ||
160 | \ | ||
161 | vpaddd RY1, RX1, RX1; \ | ||
162 | vpaddd RX1, RY1, RY1; \ | ||
163 | vpbroadcastd nk(RK,RROUND,8), RT0; \ | ||
164 | vpaddd RT0, RX1, RX1; \ | ||
165 | vpbroadcastd 4+nk(RK,RROUND,8), RT0; \ | ||
166 | vpaddd RT0, RY1, RY1; \ | ||
167 | \ | ||
168 | vpxor RY1, d ## 1, d ## 1; \ | ||
169 | \ | ||
170 | vpxor RX1, c ## 1, c ## 1; \ | ||
171 | vpsrld $1, c ## 1, RT0; \ | ||
172 | vpslld $31, c ## 1, c ## 1; \ | ||
173 | vpor RT0, c ## 1, c ## 1; \ | ||
174 | |||
175 | #define encrypt_round16(a, b, c, d, nk) \ | ||
176 | g2_16(b, RY); \ | ||
177 | \ | ||
178 | vpslld $1, b ## 0, RT0; \ | ||
179 | vpsrld $31, b ## 0, b ## 0; \ | ||
180 | vpor RT0, b ## 0, b ## 0; \ | ||
181 | \ | ||
182 | vpslld $1, b ## 1, RT0; \ | ||
183 | vpsrld $31, b ## 1, b ## 1; \ | ||
184 | vpor RT0, b ## 1, b ## 1; \ | ||
185 | \ | ||
186 | g1_16(a, RX); \ | ||
187 | \ | ||
188 | encrypt_round_end16(a, b, c, d, nk); | ||
189 | |||
190 | #define encrypt_round_first16(a, b, c, d, nk) \ | ||
191 | vpslld $1, d ## 0, RT0; \ | ||
192 | vpsrld $31, d ## 0, d ## 0; \ | ||
193 | vpor RT0, d ## 0, d ## 0; \ | ||
194 | \ | ||
195 | vpslld $1, d ## 1, RT0; \ | ||
196 | vpsrld $31, d ## 1, d ## 1; \ | ||
197 | vpor RT0, d ## 1, d ## 1; \ | ||
198 | \ | ||
199 | encrypt_round16(a, b, c, d, nk); | ||
200 | |||
201 | #define encrypt_round_last16(a, b, c, d, nk) \ | ||
202 | g2_16(b, RY); \ | ||
203 | \ | ||
204 | g1_16(a, RX); \ | ||
205 | \ | ||
206 | encrypt_round_end16(a, b, c, d, nk); | ||
207 | |||
208 | #define decrypt_round_end16(a, b, c, d, nk) \ | ||
209 | vpaddd RY0, RX0, RX0; \ | ||
210 | vpaddd RX0, RY0, RY0; \ | ||
211 | vpbroadcastd nk(RK,RROUND,8), RT0; \ | ||
212 | vpaddd RT0, RX0, RX0; \ | ||
213 | vpbroadcastd 4+nk(RK,RROUND,8), RT0; \ | ||
214 | vpaddd RT0, RY0, RY0; \ | ||
215 | \ | ||
216 | vpxor RX0, c ## 0, c ## 0; \ | ||
217 | \ | ||
218 | vpxor RY0, d ## 0, d ## 0; \ | ||
219 | vpsrld $1, d ## 0, RT0; \ | ||
220 | vpslld $31, d ## 0, d ## 0; \ | ||
221 | vpor RT0, d ## 0, d ## 0; \ | ||
222 | \ | ||
223 | vpaddd RY1, RX1, RX1; \ | ||
224 | vpaddd RX1, RY1, RY1; \ | ||
225 | vpbroadcastd nk(RK,RROUND,8), RT0; \ | ||
226 | vpaddd RT0, RX1, RX1; \ | ||
227 | vpbroadcastd 4+nk(RK,RROUND,8), RT0; \ | ||
228 | vpaddd RT0, RY1, RY1; \ | ||
229 | \ | ||
230 | vpxor RX1, c ## 1, c ## 1; \ | ||
231 | \ | ||
232 | vpxor RY1, d ## 1, d ## 1; \ | ||
233 | vpsrld $1, d ## 1, RT0; \ | ||
234 | vpslld $31, d ## 1, d ## 1; \ | ||
235 | vpor RT0, d ## 1, d ## 1; | ||
236 | |||
237 | #define decrypt_round16(a, b, c, d, nk) \ | ||
238 | g1_16(a, RX); \ | ||
239 | \ | ||
240 | vpslld $1, a ## 0, RT0; \ | ||
241 | vpsrld $31, a ## 0, a ## 0; \ | ||
242 | vpor RT0, a ## 0, a ## 0; \ | ||
243 | \ | ||
244 | vpslld $1, a ## 1, RT0; \ | ||
245 | vpsrld $31, a ## 1, a ## 1; \ | ||
246 | vpor RT0, a ## 1, a ## 1; \ | ||
247 | \ | ||
248 | g2_16(b, RY); \ | ||
249 | \ | ||
250 | decrypt_round_end16(a, b, c, d, nk); | ||
251 | |||
252 | #define decrypt_round_first16(a, b, c, d, nk) \ | ||
253 | vpslld $1, c ## 0, RT0; \ | ||
254 | vpsrld $31, c ## 0, c ## 0; \ | ||
255 | vpor RT0, c ## 0, c ## 0; \ | ||
256 | \ | ||
257 | vpslld $1, c ## 1, RT0; \ | ||
258 | vpsrld $31, c ## 1, c ## 1; \ | ||
259 | vpor RT0, c ## 1, c ## 1; \ | ||
260 | \ | ||
261 | decrypt_round16(a, b, c, d, nk) | ||
262 | |||
263 | #define decrypt_round_last16(a, b, c, d, nk) \ | ||
264 | g1_16(a, RX); \ | ||
265 | \ | ||
266 | g2_16(b, RY); \ | ||
267 | \ | ||
268 | decrypt_round_end16(a, b, c, d, nk); | ||
269 | |||
270 | #define encrypt_cycle16() \ | ||
271 | encrypt_round16(RA, RB, RC, RD, 0); \ | ||
272 | encrypt_round16(RC, RD, RA, RB, 8); | ||
273 | |||
274 | #define encrypt_cycle_first16() \ | ||
275 | encrypt_round_first16(RA, RB, RC, RD, 0); \ | ||
276 | encrypt_round16(RC, RD, RA, RB, 8); | ||
277 | |||
278 | #define encrypt_cycle_last16() \ | ||
279 | encrypt_round16(RA, RB, RC, RD, 0); \ | ||
280 | encrypt_round_last16(RC, RD, RA, RB, 8); | ||
281 | |||
282 | #define decrypt_cycle16(n) \ | ||
283 | decrypt_round16(RC, RD, RA, RB, 8); \ | ||
284 | decrypt_round16(RA, RB, RC, RD, 0); | ||
285 | |||
286 | #define decrypt_cycle_first16(n) \ | ||
287 | decrypt_round_first16(RC, RD, RA, RB, 8); \ | ||
288 | decrypt_round16(RA, RB, RC, RD, 0); | ||
289 | |||
290 | #define decrypt_cycle_last16(n) \ | ||
291 | decrypt_round16(RC, RD, RA, RB, 8); \ | ||
292 | decrypt_round_last16(RA, RB, RC, RD, 0); | ||
293 | |||
294 | #define transpose_4x4(x0,x1,x2,x3,t1,t2) \ | ||
295 | vpunpckhdq x1, x0, t2; \ | ||
296 | vpunpckldq x1, x0, x0; \ | ||
297 | \ | ||
298 | vpunpckldq x3, x2, t1; \ | ||
299 | vpunpckhdq x3, x2, x2; \ | ||
300 | \ | ||
301 | vpunpckhqdq t1, x0, x1; \ | ||
302 | vpunpcklqdq t1, x0, x0; \ | ||
303 | \ | ||
304 | vpunpckhqdq x2, t2, x3; \ | ||
305 | vpunpcklqdq x2, t2, x2; | ||
306 | |||
307 | #define read_blocks8(offs,a,b,c,d) \ | ||
308 | transpose_4x4(a, b, c, d, RX0, RY0); | ||
309 | |||
310 | #define write_blocks8(offs,a,b,c,d) \ | ||
311 | transpose_4x4(a, b, c, d, RX0, RY0); | ||
312 | |||
313 | #define inpack_enc8(a,b,c,d) \ | ||
314 | vpbroadcastd 4*0(RW), RT0; \ | ||
315 | vpxor RT0, a, a; \ | ||
316 | \ | ||
317 | vpbroadcastd 4*1(RW), RT0; \ | ||
318 | vpxor RT0, b, b; \ | ||
319 | \ | ||
320 | vpbroadcastd 4*2(RW), RT0; \ | ||
321 | vpxor RT0, c, c; \ | ||
322 | \ | ||
323 | vpbroadcastd 4*3(RW), RT0; \ | ||
324 | vpxor RT0, d, d; | ||
325 | |||
326 | #define outunpack_enc8(a,b,c,d) \ | ||
327 | vpbroadcastd 4*4(RW), RX0; \ | ||
328 | vpbroadcastd 4*5(RW), RY0; \ | ||
329 | vpxor RX0, c, RX0; \ | ||
330 | vpxor RY0, d, RY0; \ | ||
331 | \ | ||
332 | vpbroadcastd 4*6(RW), RT0; \ | ||
333 | vpxor RT0, a, c; \ | ||
334 | vpbroadcastd 4*7(RW), RT0; \ | ||
335 | vpxor RT0, b, d; \ | ||
336 | \ | ||
337 | vmovdqa RX0, a; \ | ||
338 | vmovdqa RY0, b; | ||
339 | |||
340 | #define inpack_dec8(a,b,c,d) \ | ||
341 | vpbroadcastd 4*4(RW), RX0; \ | ||
342 | vpbroadcastd 4*5(RW), RY0; \ | ||
343 | vpxor RX0, a, RX0; \ | ||
344 | vpxor RY0, b, RY0; \ | ||
345 | \ | ||
346 | vpbroadcastd 4*6(RW), RT0; \ | ||
347 | vpxor RT0, c, a; \ | ||
348 | vpbroadcastd 4*7(RW), RT0; \ | ||
349 | vpxor RT0, d, b; \ | ||
350 | \ | ||
351 | vmovdqa RX0, c; \ | ||
352 | vmovdqa RY0, d; | ||
353 | |||
354 | #define outunpack_dec8(a,b,c,d) \ | ||
355 | vpbroadcastd 4*0(RW), RT0; \ | ||
356 | vpxor RT0, a, a; \ | ||
357 | \ | ||
358 | vpbroadcastd 4*1(RW), RT0; \ | ||
359 | vpxor RT0, b, b; \ | ||
360 | \ | ||
361 | vpbroadcastd 4*2(RW), RT0; \ | ||
362 | vpxor RT0, c, c; \ | ||
363 | \ | ||
364 | vpbroadcastd 4*3(RW), RT0; \ | ||
365 | vpxor RT0, d, d; | ||
366 | |||
367 | #define read_blocks16(a,b,c,d) \ | ||
368 | read_blocks8(0, a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
369 | read_blocks8(8, a ## 1, b ## 1, c ## 1, d ## 1); | ||
370 | |||
371 | #define write_blocks16(a,b,c,d) \ | ||
372 | write_blocks8(0, a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
373 | write_blocks8(8, a ## 1, b ## 1, c ## 1, d ## 1); | ||
374 | |||
375 | #define xor_blocks16(a,b,c,d) \ | ||
376 | xor_blocks8(0, a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
377 | xor_blocks8(8, a ## 1, b ## 1, c ## 1, d ## 1); | ||
378 | |||
379 | #define inpack_enc16(a,b,c,d) \ | ||
380 | inpack_enc8(a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
381 | inpack_enc8(a ## 1, b ## 1, c ## 1, d ## 1); | ||
382 | |||
383 | #define outunpack_enc16(a,b,c,d) \ | ||
384 | outunpack_enc8(a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
385 | outunpack_enc8(a ## 1, b ## 1, c ## 1, d ## 1); | ||
386 | |||
387 | #define inpack_dec16(a,b,c,d) \ | ||
388 | inpack_dec8(a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
389 | inpack_dec8(a ## 1, b ## 1, c ## 1, d ## 1); | ||
390 | |||
391 | #define outunpack_dec16(a,b,c,d) \ | ||
392 | outunpack_dec8(a ## 0, b ## 0, c ## 0, d ## 0); \ | ||
393 | outunpack_dec8(a ## 1, b ## 1, c ## 1, d ## 1); | ||
394 | |||
395 | .align 8 | ||
396 | __twofish_enc_blk16: | ||
397 | /* input: | ||
398 | * %rdi: ctx, CTX | ||
399 | * RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: plaintext | ||
400 | * output: | ||
401 | * RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: ciphertext | ||
402 | */ | ||
403 | init_round_constants(); | ||
404 | |||
405 | read_blocks16(RA, RB, RC, RD); | ||
406 | inpack_enc16(RA, RB, RC, RD); | ||
407 | |||
408 | xorl RROUNDd, RROUNDd; | ||
409 | encrypt_cycle_first16(); | ||
410 | movl $2, RROUNDd; | ||
411 | |||
412 | .align 4 | ||
413 | .L__enc_loop: | ||
414 | encrypt_cycle16(); | ||
415 | |||
416 | addl $2, RROUNDd; | ||
417 | cmpl $14, RROUNDd; | ||
418 | jne .L__enc_loop; | ||
419 | |||
420 | encrypt_cycle_last16(); | ||
421 | |||
422 | outunpack_enc16(RA, RB, RC, RD); | ||
423 | write_blocks16(RA, RB, RC, RD); | ||
424 | |||
425 | ret; | ||
426 | ENDPROC(__twofish_enc_blk16) | ||
427 | |||
428 | .align 8 | ||
429 | __twofish_dec_blk16: | ||
430 | /* input: | ||
431 | * %rdi: ctx, CTX | ||
432 | * RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: ciphertext | ||
433 | * output: | ||
434 | * RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: plaintext | ||
435 | */ | ||
436 | init_round_constants(); | ||
437 | |||
438 | read_blocks16(RA, RB, RC, RD); | ||
439 | inpack_dec16(RA, RB, RC, RD); | ||
440 | |||
441 | movl $14, RROUNDd; | ||
442 | decrypt_cycle_first16(); | ||
443 | movl $12, RROUNDd; | ||
444 | |||
445 | .align 4 | ||
446 | .L__dec_loop: | ||
447 | decrypt_cycle16(); | ||
448 | |||
449 | addl $-2, RROUNDd; | ||
450 | jnz .L__dec_loop; | ||
451 | |||
452 | decrypt_cycle_last16(); | ||
453 | |||
454 | outunpack_dec16(RA, RB, RC, RD); | ||
455 | write_blocks16(RA, RB, RC, RD); | ||
456 | |||
457 | ret; | ||
458 | ENDPROC(__twofish_dec_blk16) | ||
459 | |||
460 | ENTRY(twofish_ecb_enc_16way) | ||
461 | /* input: | ||
462 | * %rdi: ctx, CTX | ||
463 | * %rsi: dst | ||
464 | * %rdx: src | ||
465 | */ | ||
466 | |||
467 | vzeroupper; | ||
468 | pushq %r12; | ||
469 | |||
470 | load_16way(%rdx, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
471 | |||
472 | call __twofish_enc_blk16; | ||
473 | |||
474 | store_16way(%rsi, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
475 | |||
476 | popq %r12; | ||
477 | vzeroupper; | ||
478 | |||
479 | ret; | ||
480 | ENDPROC(twofish_ecb_enc_16way) | ||
481 | |||
482 | ENTRY(twofish_ecb_dec_16way) | ||
483 | /* input: | ||
484 | * %rdi: ctx, CTX | ||
485 | * %rsi: dst | ||
486 | * %rdx: src | ||
487 | */ | ||
488 | |||
489 | vzeroupper; | ||
490 | pushq %r12; | ||
491 | |||
492 | load_16way(%rdx, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
493 | |||
494 | call __twofish_dec_blk16; | ||
495 | |||
496 | store_16way(%rsi, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
497 | |||
498 | popq %r12; | ||
499 | vzeroupper; | ||
500 | |||
501 | ret; | ||
502 | ENDPROC(twofish_ecb_dec_16way) | ||
503 | |||
504 | ENTRY(twofish_cbc_dec_16way) | ||
505 | /* input: | ||
506 | * %rdi: ctx, CTX | ||
507 | * %rsi: dst | ||
508 | * %rdx: src | ||
509 | */ | ||
510 | |||
511 | vzeroupper; | ||
512 | pushq %r12; | ||
513 | |||
514 | load_16way(%rdx, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
515 | |||
516 | call __twofish_dec_blk16; | ||
517 | |||
518 | store_cbc_16way(%rdx, %rsi, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1, | ||
519 | RX0); | ||
520 | |||
521 | popq %r12; | ||
522 | vzeroupper; | ||
523 | |||
524 | ret; | ||
525 | ENDPROC(twofish_cbc_dec_16way) | ||
526 | |||
527 | ENTRY(twofish_ctr_16way) | ||
528 | /* input: | ||
529 | * %rdi: ctx, CTX | ||
530 | * %rsi: dst (16 blocks) | ||
531 | * %rdx: src (16 blocks) | ||
532 | * %rcx: iv (little endian, 128bit) | ||
533 | */ | ||
534 | |||
535 | vzeroupper; | ||
536 | pushq %r12; | ||
537 | |||
538 | load_ctr_16way(%rcx, .Lbswap128_mask, RA0, RB0, RC0, RD0, RA1, RB1, RC1, | ||
539 | RD1, RX0, RX0x, RX1, RX1x, RY0, RY0x, RY1, RY1x, RNOT, | ||
540 | RBYTE); | ||
541 | |||
542 | call __twofish_enc_blk16; | ||
543 | |||
544 | store_ctr_16way(%rdx, %rsi, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
545 | |||
546 | popq %r12; | ||
547 | vzeroupper; | ||
548 | |||
549 | ret; | ||
550 | ENDPROC(twofish_ctr_16way) | ||
551 | |||
552 | .align 8 | ||
553 | twofish_xts_crypt_16way: | ||
554 | /* input: | ||
555 | * %rdi: ctx, CTX | ||
556 | * %rsi: dst (16 blocks) | ||
557 | * %rdx: src (16 blocks) | ||
558 | * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) | ||
559 | * %r8: pointer to __twofish_enc_blk16 or __twofish_dec_blk16 | ||
560 | */ | ||
561 | |||
562 | vzeroupper; | ||
563 | pushq %r12; | ||
564 | |||
565 | load_xts_16way(%rcx, %rdx, %rsi, RA0, RB0, RC0, RD0, RA1, RB1, RC1, | ||
566 | RD1, RX0, RX0x, RX1, RX1x, RY0, RY0x, RY1, RY1x, RNOT, | ||
567 | .Lxts_gf128mul_and_shl1_mask_0, | ||
568 | .Lxts_gf128mul_and_shl1_mask_1); | ||
569 | |||
570 | call *%r8; | ||
571 | |||
572 | store_xts_16way(%rsi, RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1); | ||
573 | |||
574 | popq %r12; | ||
575 | vzeroupper; | ||
576 | |||
577 | ret; | ||
578 | ENDPROC(twofish_xts_crypt_16way) | ||
579 | |||
580 | ENTRY(twofish_xts_enc_16way) | ||
581 | /* input: | ||
582 | * %rdi: ctx, CTX | ||
583 | * %rsi: dst (16 blocks) | ||
584 | * %rdx: src (16 blocks) | ||
585 | * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) | ||
586 | */ | ||
587 | leaq __twofish_enc_blk16, %r8; | ||
588 | jmp twofish_xts_crypt_16way; | ||
589 | ENDPROC(twofish_xts_enc_16way) | ||
590 | |||
591 | ENTRY(twofish_xts_dec_16way) | ||
592 | /* input: | ||
593 | * %rdi: ctx, CTX | ||
594 | * %rsi: dst (16 blocks) | ||
595 | * %rdx: src (16 blocks) | ||
596 | * %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸)) | ||
597 | */ | ||
598 | leaq __twofish_dec_blk16, %r8; | ||
599 | jmp twofish_xts_crypt_16way; | ||
600 | ENDPROC(twofish_xts_dec_16way) | ||
diff --git a/arch/x86/crypto/twofish_avx2_glue.c b/arch/x86/crypto/twofish_avx2_glue.c deleted file mode 100644 index ce33b5be64ee..000000000000 --- a/arch/x86/crypto/twofish_avx2_glue.c +++ /dev/null | |||
@@ -1,584 +0,0 @@ | |||
1 | /* | ||
2 | * Glue Code for x86_64/AVX2 assembler optimized version of Twofish | ||
3 | * | ||
4 | * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/crypto.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <crypto/algapi.h> | ||
18 | #include <crypto/ctr.h> | ||
19 | #include <crypto/twofish.h> | ||
20 | #include <crypto/lrw.h> | ||
21 | #include <crypto/xts.h> | ||
22 | #include <asm/xcr.h> | ||
23 | #include <asm/xsave.h> | ||
24 | #include <asm/crypto/twofish.h> | ||
25 | #include <asm/crypto/ablk_helper.h> | ||
26 | #include <asm/crypto/glue_helper.h> | ||
27 | #include <crypto/scatterwalk.h> | ||
28 | |||
29 | #define TF_AVX2_PARALLEL_BLOCKS 16 | ||
30 | |||
31 | /* 16-way AVX2 parallel cipher functions */ | ||
32 | asmlinkage void twofish_ecb_enc_16way(struct twofish_ctx *ctx, u8 *dst, | ||
33 | const u8 *src); | ||
34 | asmlinkage void twofish_ecb_dec_16way(struct twofish_ctx *ctx, u8 *dst, | ||
35 | const u8 *src); | ||
36 | asmlinkage void twofish_cbc_dec_16way(void *ctx, u128 *dst, const u128 *src); | ||
37 | |||
38 | asmlinkage void twofish_ctr_16way(void *ctx, u128 *dst, const u128 *src, | ||
39 | le128 *iv); | ||
40 | |||
41 | asmlinkage void twofish_xts_enc_16way(struct twofish_ctx *ctx, u8 *dst, | ||
42 | const u8 *src, le128 *iv); | ||
43 | asmlinkage void twofish_xts_dec_16way(struct twofish_ctx *ctx, u8 *dst, | ||
44 | const u8 *src, le128 *iv); | ||
45 | |||
46 | static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, | ||
47 | const u8 *src) | ||
48 | { | ||
49 | __twofish_enc_blk_3way(ctx, dst, src, false); | ||
50 | } | ||
51 | |||
52 | static const struct common_glue_ctx twofish_enc = { | ||
53 | .num_funcs = 4, | ||
54 | .fpu_blocks_limit = 8, | ||
55 | |||
56 | .funcs = { { | ||
57 | .num_blocks = 16, | ||
58 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_16way) } | ||
59 | }, { | ||
60 | .num_blocks = 8, | ||
61 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_8way) } | ||
62 | }, { | ||
63 | .num_blocks = 3, | ||
64 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) } | ||
65 | }, { | ||
66 | .num_blocks = 1, | ||
67 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) } | ||
68 | } } | ||
69 | }; | ||
70 | |||
71 | static const struct common_glue_ctx twofish_ctr = { | ||
72 | .num_funcs = 4, | ||
73 | .fpu_blocks_limit = 8, | ||
74 | |||
75 | .funcs = { { | ||
76 | .num_blocks = 16, | ||
77 | .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_16way) } | ||
78 | }, { | ||
79 | .num_blocks = 8, | ||
80 | .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_8way) } | ||
81 | }, { | ||
82 | .num_blocks = 3, | ||
83 | .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) } | ||
84 | }, { | ||
85 | .num_blocks = 1, | ||
86 | .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr) } | ||
87 | } } | ||
88 | }; | ||
89 | |||
90 | static const struct common_glue_ctx twofish_enc_xts = { | ||
91 | .num_funcs = 3, | ||
92 | .fpu_blocks_limit = 8, | ||
93 | |||
94 | .funcs = { { | ||
95 | .num_blocks = 16, | ||
96 | .fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc_16way) } | ||
97 | }, { | ||
98 | .num_blocks = 8, | ||
99 | .fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc_8way) } | ||
100 | }, { | ||
101 | .num_blocks = 1, | ||
102 | .fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc) } | ||
103 | } } | ||
104 | }; | ||
105 | |||
106 | static const struct common_glue_ctx twofish_dec = { | ||
107 | .num_funcs = 4, | ||
108 | .fpu_blocks_limit = 8, | ||
109 | |||
110 | .funcs = { { | ||
111 | .num_blocks = 16, | ||
112 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_16way) } | ||
113 | }, { | ||
114 | .num_blocks = 8, | ||
115 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_8way) } | ||
116 | }, { | ||
117 | .num_blocks = 3, | ||
118 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) } | ||
119 | }, { | ||
120 | .num_blocks = 1, | ||
121 | .fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) } | ||
122 | } } | ||
123 | }; | ||
124 | |||
125 | static const struct common_glue_ctx twofish_dec_cbc = { | ||
126 | .num_funcs = 4, | ||
127 | .fpu_blocks_limit = 8, | ||
128 | |||
129 | .funcs = { { | ||
130 | .num_blocks = 16, | ||
131 | .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_16way) } | ||
132 | }, { | ||
133 | .num_blocks = 8, | ||
134 | .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_8way) } | ||
135 | }, { | ||
136 | .num_blocks = 3, | ||
137 | .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) } | ||
138 | }, { | ||
139 | .num_blocks = 1, | ||
140 | .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) } | ||
141 | } } | ||
142 | }; | ||
143 | |||
144 | static const struct common_glue_ctx twofish_dec_xts = { | ||
145 | .num_funcs = 3, | ||
146 | .fpu_blocks_limit = 8, | ||
147 | |||
148 | .funcs = { { | ||
149 | .num_blocks = 16, | ||
150 | .fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec_16way) } | ||
151 | }, { | ||
152 | .num_blocks = 8, | ||
153 | .fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec_8way) } | ||
154 | }, { | ||
155 | .num_blocks = 1, | ||
156 | .fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec) } | ||
157 | } } | ||
158 | }; | ||
159 | |||
160 | static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
161 | struct scatterlist *src, unsigned int nbytes) | ||
162 | { | ||
163 | return glue_ecb_crypt_128bit(&twofish_enc, desc, dst, src, nbytes); | ||
164 | } | ||
165 | |||
166 | static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
167 | struct scatterlist *src, unsigned int nbytes) | ||
168 | { | ||
169 | return glue_ecb_crypt_128bit(&twofish_dec, desc, dst, src, nbytes); | ||
170 | } | ||
171 | |||
172 | static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
173 | struct scatterlist *src, unsigned int nbytes) | ||
174 | { | ||
175 | return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(twofish_enc_blk), desc, | ||
176 | dst, src, nbytes); | ||
177 | } | ||
178 | |||
179 | static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
180 | struct scatterlist *src, unsigned int nbytes) | ||
181 | { | ||
182 | return glue_cbc_decrypt_128bit(&twofish_dec_cbc, desc, dst, src, | ||
183 | nbytes); | ||
184 | } | ||
185 | |||
186 | static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
187 | struct scatterlist *src, unsigned int nbytes) | ||
188 | { | ||
189 | return glue_ctr_crypt_128bit(&twofish_ctr, desc, dst, src, nbytes); | ||
190 | } | ||
191 | |||
192 | static inline bool twofish_fpu_begin(bool fpu_enabled, unsigned int nbytes) | ||
193 | { | ||
194 | /* since reusing AVX functions, starts using FPU at 8 parallel blocks */ | ||
195 | return glue_fpu_begin(TF_BLOCK_SIZE, 8, NULL, fpu_enabled, nbytes); | ||
196 | } | ||
197 | |||
198 | static inline void twofish_fpu_end(bool fpu_enabled) | ||
199 | { | ||
200 | glue_fpu_end(fpu_enabled); | ||
201 | } | ||
202 | |||
203 | struct crypt_priv { | ||
204 | struct twofish_ctx *ctx; | ||
205 | bool fpu_enabled; | ||
206 | }; | ||
207 | |||
208 | static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) | ||
209 | { | ||
210 | const unsigned int bsize = TF_BLOCK_SIZE; | ||
211 | struct crypt_priv *ctx = priv; | ||
212 | int i; | ||
213 | |||
214 | ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes); | ||
215 | |||
216 | while (nbytes >= TF_AVX2_PARALLEL_BLOCKS * bsize) { | ||
217 | twofish_ecb_enc_16way(ctx->ctx, srcdst, srcdst); | ||
218 | srcdst += bsize * TF_AVX2_PARALLEL_BLOCKS; | ||
219 | nbytes -= bsize * TF_AVX2_PARALLEL_BLOCKS; | ||
220 | } | ||
221 | |||
222 | while (nbytes >= 8 * bsize) { | ||
223 | twofish_ecb_enc_8way(ctx->ctx, srcdst, srcdst); | ||
224 | srcdst += bsize * 8; | ||
225 | nbytes -= bsize * 8; | ||
226 | } | ||
227 | |||
228 | while (nbytes >= 3 * bsize) { | ||
229 | twofish_enc_blk_3way(ctx->ctx, srcdst, srcdst); | ||
230 | srcdst += bsize * 3; | ||
231 | nbytes -= bsize * 3; | ||
232 | } | ||
233 | |||
234 | for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) | ||
235 | twofish_enc_blk(ctx->ctx, srcdst, srcdst); | ||
236 | } | ||
237 | |||
238 | static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes) | ||
239 | { | ||
240 | const unsigned int bsize = TF_BLOCK_SIZE; | ||
241 | struct crypt_priv *ctx = priv; | ||
242 | int i; | ||
243 | |||
244 | ctx->fpu_enabled = twofish_fpu_begin(ctx->fpu_enabled, nbytes); | ||
245 | |||
246 | while (nbytes >= TF_AVX2_PARALLEL_BLOCKS * bsize) { | ||
247 | twofish_ecb_dec_16way(ctx->ctx, srcdst, srcdst); | ||
248 | srcdst += bsize * TF_AVX2_PARALLEL_BLOCKS; | ||
249 | nbytes -= bsize * TF_AVX2_PARALLEL_BLOCKS; | ||
250 | } | ||
251 | |||
252 | while (nbytes >= 8 * bsize) { | ||
253 | twofish_ecb_dec_8way(ctx->ctx, srcdst, srcdst); | ||
254 | srcdst += bsize * 8; | ||
255 | nbytes -= bsize * 8; | ||
256 | } | ||
257 | |||
258 | while (nbytes >= 3 * bsize) { | ||
259 | twofish_dec_blk_3way(ctx->ctx, srcdst, srcdst); | ||
260 | srcdst += bsize * 3; | ||
261 | nbytes -= bsize * 3; | ||
262 | } | ||
263 | |||
264 | for (i = 0; i < nbytes / bsize; i++, srcdst += bsize) | ||
265 | twofish_dec_blk(ctx->ctx, srcdst, srcdst); | ||
266 | } | ||
267 | |||
268 | static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
269 | struct scatterlist *src, unsigned int nbytes) | ||
270 | { | ||
271 | struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
272 | be128 buf[TF_AVX2_PARALLEL_BLOCKS]; | ||
273 | struct crypt_priv crypt_ctx = { | ||
274 | .ctx = &ctx->twofish_ctx, | ||
275 | .fpu_enabled = false, | ||
276 | }; | ||
277 | struct lrw_crypt_req req = { | ||
278 | .tbuf = buf, | ||
279 | .tbuflen = sizeof(buf), | ||
280 | |||
281 | .table_ctx = &ctx->lrw_table, | ||
282 | .crypt_ctx = &crypt_ctx, | ||
283 | .crypt_fn = encrypt_callback, | ||
284 | }; | ||
285 | int ret; | ||
286 | |||
287 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
288 | ret = lrw_crypt(desc, dst, src, nbytes, &req); | ||
289 | twofish_fpu_end(crypt_ctx.fpu_enabled); | ||
290 | |||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
295 | struct scatterlist *src, unsigned int nbytes) | ||
296 | { | ||
297 | struct twofish_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
298 | be128 buf[TF_AVX2_PARALLEL_BLOCKS]; | ||
299 | struct crypt_priv crypt_ctx = { | ||
300 | .ctx = &ctx->twofish_ctx, | ||
301 | .fpu_enabled = false, | ||
302 | }; | ||
303 | struct lrw_crypt_req req = { | ||
304 | .tbuf = buf, | ||
305 | .tbuflen = sizeof(buf), | ||
306 | |||
307 | .table_ctx = &ctx->lrw_table, | ||
308 | .crypt_ctx = &crypt_ctx, | ||
309 | .crypt_fn = decrypt_callback, | ||
310 | }; | ||
311 | int ret; | ||
312 | |||
313 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
314 | ret = lrw_crypt(desc, dst, src, nbytes, &req); | ||
315 | twofish_fpu_end(crypt_ctx.fpu_enabled); | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
321 | struct scatterlist *src, unsigned int nbytes) | ||
322 | { | ||
323 | struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
324 | |||
325 | return glue_xts_crypt_128bit(&twofish_enc_xts, desc, dst, src, nbytes, | ||
326 | XTS_TWEAK_CAST(twofish_enc_blk), | ||
327 | &ctx->tweak_ctx, &ctx->crypt_ctx); | ||
328 | } | ||
329 | |||
330 | static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
331 | struct scatterlist *src, unsigned int nbytes) | ||
332 | { | ||
333 | struct twofish_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
334 | |||
335 | return glue_xts_crypt_128bit(&twofish_dec_xts, desc, dst, src, nbytes, | ||
336 | XTS_TWEAK_CAST(twofish_enc_blk), | ||
337 | &ctx->tweak_ctx, &ctx->crypt_ctx); | ||
338 | } | ||
339 | |||
340 | static struct crypto_alg tf_algs[10] = { { | ||
341 | .cra_name = "__ecb-twofish-avx2", | ||
342 | .cra_driver_name = "__driver-ecb-twofish-avx2", | ||
343 | .cra_priority = 0, | ||
344 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
345 | .cra_blocksize = TF_BLOCK_SIZE, | ||
346 | .cra_ctxsize = sizeof(struct twofish_ctx), | ||
347 | .cra_alignmask = 0, | ||
348 | .cra_type = &crypto_blkcipher_type, | ||
349 | .cra_module = THIS_MODULE, | ||
350 | .cra_u = { | ||
351 | .blkcipher = { | ||
352 | .min_keysize = TF_MIN_KEY_SIZE, | ||
353 | .max_keysize = TF_MAX_KEY_SIZE, | ||
354 | .setkey = twofish_setkey, | ||
355 | .encrypt = ecb_encrypt, | ||
356 | .decrypt = ecb_decrypt, | ||
357 | }, | ||
358 | }, | ||
359 | }, { | ||
360 | .cra_name = "__cbc-twofish-avx2", | ||
361 | .cra_driver_name = "__driver-cbc-twofish-avx2", | ||
362 | .cra_priority = 0, | ||
363 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
364 | .cra_blocksize = TF_BLOCK_SIZE, | ||
365 | .cra_ctxsize = sizeof(struct twofish_ctx), | ||
366 | .cra_alignmask = 0, | ||
367 | .cra_type = &crypto_blkcipher_type, | ||
368 | .cra_module = THIS_MODULE, | ||
369 | .cra_u = { | ||
370 | .blkcipher = { | ||
371 | .min_keysize = TF_MIN_KEY_SIZE, | ||
372 | .max_keysize = TF_MAX_KEY_SIZE, | ||
373 | .setkey = twofish_setkey, | ||
374 | .encrypt = cbc_encrypt, | ||
375 | .decrypt = cbc_decrypt, | ||
376 | }, | ||
377 | }, | ||
378 | }, { | ||
379 | .cra_name = "__ctr-twofish-avx2", | ||
380 | .cra_driver_name = "__driver-ctr-twofish-avx2", | ||
381 | .cra_priority = 0, | ||
382 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
383 | .cra_blocksize = 1, | ||
384 | .cra_ctxsize = sizeof(struct twofish_ctx), | ||
385 | .cra_alignmask = 0, | ||
386 | .cra_type = &crypto_blkcipher_type, | ||
387 | .cra_module = THIS_MODULE, | ||
388 | .cra_u = { | ||
389 | .blkcipher = { | ||
390 | .min_keysize = TF_MIN_KEY_SIZE, | ||
391 | .max_keysize = TF_MAX_KEY_SIZE, | ||
392 | .ivsize = TF_BLOCK_SIZE, | ||
393 | .setkey = twofish_setkey, | ||
394 | .encrypt = ctr_crypt, | ||
395 | .decrypt = ctr_crypt, | ||
396 | }, | ||
397 | }, | ||
398 | }, { | ||
399 | .cra_name = "__lrw-twofish-avx2", | ||
400 | .cra_driver_name = "__driver-lrw-twofish-avx2", | ||
401 | .cra_priority = 0, | ||
402 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
403 | .cra_blocksize = TF_BLOCK_SIZE, | ||
404 | .cra_ctxsize = sizeof(struct twofish_lrw_ctx), | ||
405 | .cra_alignmask = 0, | ||
406 | .cra_type = &crypto_blkcipher_type, | ||
407 | .cra_module = THIS_MODULE, | ||
408 | .cra_exit = lrw_twofish_exit_tfm, | ||
409 | .cra_u = { | ||
410 | .blkcipher = { | ||
411 | .min_keysize = TF_MIN_KEY_SIZE + | ||
412 | TF_BLOCK_SIZE, | ||
413 | .max_keysize = TF_MAX_KEY_SIZE + | ||
414 | TF_BLOCK_SIZE, | ||
415 | .ivsize = TF_BLOCK_SIZE, | ||
416 | .setkey = lrw_twofish_setkey, | ||
417 | .encrypt = lrw_encrypt, | ||
418 | .decrypt = lrw_decrypt, | ||
419 | }, | ||
420 | }, | ||
421 | }, { | ||
422 | .cra_name = "__xts-twofish-avx2", | ||
423 | .cra_driver_name = "__driver-xts-twofish-avx2", | ||
424 | .cra_priority = 0, | ||
425 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
426 | .cra_blocksize = TF_BLOCK_SIZE, | ||
427 | .cra_ctxsize = sizeof(struct twofish_xts_ctx), | ||
428 | .cra_alignmask = 0, | ||
429 | .cra_type = &crypto_blkcipher_type, | ||
430 | .cra_module = THIS_MODULE, | ||
431 | .cra_u = { | ||
432 | .blkcipher = { | ||
433 | .min_keysize = TF_MIN_KEY_SIZE * 2, | ||
434 | .max_keysize = TF_MAX_KEY_SIZE * 2, | ||
435 | .ivsize = TF_BLOCK_SIZE, | ||
436 | .setkey = xts_twofish_setkey, | ||
437 | .encrypt = xts_encrypt, | ||
438 | .decrypt = xts_decrypt, | ||
439 | }, | ||
440 | }, | ||
441 | }, { | ||
442 | .cra_name = "ecb(twofish)", | ||
443 | .cra_driver_name = "ecb-twofish-avx2", | ||
444 | .cra_priority = 500, | ||
445 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
446 | .cra_blocksize = TF_BLOCK_SIZE, | ||
447 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
448 | .cra_alignmask = 0, | ||
449 | .cra_type = &crypto_ablkcipher_type, | ||
450 | .cra_module = THIS_MODULE, | ||
451 | .cra_init = ablk_init, | ||
452 | .cra_exit = ablk_exit, | ||
453 | .cra_u = { | ||
454 | .ablkcipher = { | ||
455 | .min_keysize = TF_MIN_KEY_SIZE, | ||
456 | .max_keysize = TF_MAX_KEY_SIZE, | ||
457 | .setkey = ablk_set_key, | ||
458 | .encrypt = ablk_encrypt, | ||
459 | .decrypt = ablk_decrypt, | ||
460 | }, | ||
461 | }, | ||
462 | }, { | ||
463 | .cra_name = "cbc(twofish)", | ||
464 | .cra_driver_name = "cbc-twofish-avx2", | ||
465 | .cra_priority = 500, | ||
466 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
467 | .cra_blocksize = TF_BLOCK_SIZE, | ||
468 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
469 | .cra_alignmask = 0, | ||
470 | .cra_type = &crypto_ablkcipher_type, | ||
471 | .cra_module = THIS_MODULE, | ||
472 | .cra_init = ablk_init, | ||
473 | .cra_exit = ablk_exit, | ||
474 | .cra_u = { | ||
475 | .ablkcipher = { | ||
476 | .min_keysize = TF_MIN_KEY_SIZE, | ||
477 | .max_keysize = TF_MAX_KEY_SIZE, | ||
478 | .ivsize = TF_BLOCK_SIZE, | ||
479 | .setkey = ablk_set_key, | ||
480 | .encrypt = __ablk_encrypt, | ||
481 | .decrypt = ablk_decrypt, | ||
482 | }, | ||
483 | }, | ||
484 | }, { | ||
485 | .cra_name = "ctr(twofish)", | ||
486 | .cra_driver_name = "ctr-twofish-avx2", | ||
487 | .cra_priority = 500, | ||
488 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
489 | .cra_blocksize = 1, | ||
490 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
491 | .cra_alignmask = 0, | ||
492 | .cra_type = &crypto_ablkcipher_type, | ||
493 | .cra_module = THIS_MODULE, | ||
494 | .cra_init = ablk_init, | ||
495 | .cra_exit = ablk_exit, | ||
496 | .cra_u = { | ||
497 | .ablkcipher = { | ||
498 | .min_keysize = TF_MIN_KEY_SIZE, | ||
499 | .max_keysize = TF_MAX_KEY_SIZE, | ||
500 | .ivsize = TF_BLOCK_SIZE, | ||
501 | .setkey = ablk_set_key, | ||
502 | .encrypt = ablk_encrypt, | ||
503 | .decrypt = ablk_encrypt, | ||
504 | .geniv = "chainiv", | ||
505 | }, | ||
506 | }, | ||
507 | }, { | ||
508 | .cra_name = "lrw(twofish)", | ||
509 | .cra_driver_name = "lrw-twofish-avx2", | ||
510 | .cra_priority = 500, | ||
511 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
512 | .cra_blocksize = TF_BLOCK_SIZE, | ||
513 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
514 | .cra_alignmask = 0, | ||
515 | .cra_type = &crypto_ablkcipher_type, | ||
516 | .cra_module = THIS_MODULE, | ||
517 | .cra_init = ablk_init, | ||
518 | .cra_exit = ablk_exit, | ||
519 | .cra_u = { | ||
520 | .ablkcipher = { | ||
521 | .min_keysize = TF_MIN_KEY_SIZE + | ||
522 | TF_BLOCK_SIZE, | ||
523 | .max_keysize = TF_MAX_KEY_SIZE + | ||
524 | TF_BLOCK_SIZE, | ||
525 | .ivsize = TF_BLOCK_SIZE, | ||
526 | .setkey = ablk_set_key, | ||
527 | .encrypt = ablk_encrypt, | ||
528 | .decrypt = ablk_decrypt, | ||
529 | }, | ||
530 | }, | ||
531 | }, { | ||
532 | .cra_name = "xts(twofish)", | ||
533 | .cra_driver_name = "xts-twofish-avx2", | ||
534 | .cra_priority = 500, | ||
535 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
536 | .cra_blocksize = TF_BLOCK_SIZE, | ||
537 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
538 | .cra_alignmask = 0, | ||
539 | .cra_type = &crypto_ablkcipher_type, | ||
540 | .cra_module = THIS_MODULE, | ||
541 | .cra_init = ablk_init, | ||
542 | .cra_exit = ablk_exit, | ||
543 | .cra_u = { | ||
544 | .ablkcipher = { | ||
545 | .min_keysize = TF_MIN_KEY_SIZE * 2, | ||
546 | .max_keysize = TF_MAX_KEY_SIZE * 2, | ||
547 | .ivsize = TF_BLOCK_SIZE, | ||
548 | .setkey = ablk_set_key, | ||
549 | .encrypt = ablk_encrypt, | ||
550 | .decrypt = ablk_decrypt, | ||
551 | }, | ||
552 | }, | ||
553 | } }; | ||
554 | |||
555 | static int __init init(void) | ||
556 | { | ||
557 | u64 xcr0; | ||
558 | |||
559 | if (!cpu_has_avx2 || !cpu_has_osxsave) { | ||
560 | pr_info("AVX2 instructions are not detected.\n"); | ||
561 | return -ENODEV; | ||
562 | } | ||
563 | |||
564 | xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); | ||
565 | if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) { | ||
566 | pr_info("AVX2 detected but unusable.\n"); | ||
567 | return -ENODEV; | ||
568 | } | ||
569 | |||
570 | return crypto_register_algs(tf_algs, ARRAY_SIZE(tf_algs)); | ||
571 | } | ||
572 | |||
573 | static void __exit fini(void) | ||
574 | { | ||
575 | crypto_unregister_algs(tf_algs, ARRAY_SIZE(tf_algs)); | ||
576 | } | ||
577 | |||
578 | module_init(init); | ||
579 | module_exit(fini); | ||
580 | |||
581 | MODULE_LICENSE("GPL"); | ||
582 | MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX2 optimized"); | ||
583 | MODULE_ALIAS("twofish"); | ||
584 | MODULE_ALIAS("twofish-asm"); | ||
diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c index 2047a562f6b3..a62ba541884e 100644 --- a/arch/x86/crypto/twofish_avx_glue.c +++ b/arch/x86/crypto/twofish_avx_glue.c | |||
@@ -50,26 +50,18 @@ | |||
50 | /* 8-way parallel cipher functions */ | 50 | /* 8-way parallel cipher functions */ |
51 | asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst, | 51 | asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst, |
52 | const u8 *src); | 52 | const u8 *src); |
53 | EXPORT_SYMBOL_GPL(twofish_ecb_enc_8way); | ||
54 | |||
55 | asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst, | 53 | asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst, |
56 | const u8 *src); | 54 | const u8 *src); |
57 | EXPORT_SYMBOL_GPL(twofish_ecb_dec_8way); | ||
58 | 55 | ||
59 | asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst, | 56 | asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst, |
60 | const u8 *src); | 57 | const u8 *src); |
61 | EXPORT_SYMBOL_GPL(twofish_cbc_dec_8way); | ||
62 | |||
63 | asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst, | 58 | asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst, |
64 | const u8 *src, le128 *iv); | 59 | const u8 *src, le128 *iv); |
65 | EXPORT_SYMBOL_GPL(twofish_ctr_8way); | ||
66 | 60 | ||
67 | asmlinkage void twofish_xts_enc_8way(struct twofish_ctx *ctx, u8 *dst, | 61 | asmlinkage void twofish_xts_enc_8way(struct twofish_ctx *ctx, u8 *dst, |
68 | const u8 *src, le128 *iv); | 62 | const u8 *src, le128 *iv); |
69 | EXPORT_SYMBOL_GPL(twofish_xts_enc_8way); | ||
70 | asmlinkage void twofish_xts_dec_8way(struct twofish_ctx *ctx, u8 *dst, | 63 | asmlinkage void twofish_xts_dec_8way(struct twofish_ctx *ctx, u8 *dst, |
71 | const u8 *src, le128 *iv); | 64 | const u8 *src, le128 *iv); |
72 | EXPORT_SYMBOL_GPL(twofish_xts_dec_8way); | ||
73 | 65 | ||
74 | static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, | 66 | static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, |
75 | const u8 *src) | 67 | const u8 *src) |
@@ -77,19 +69,17 @@ static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, | |||
77 | __twofish_enc_blk_3way(ctx, dst, src, false); | 69 | __twofish_enc_blk_3way(ctx, dst, src, false); |
78 | } | 70 | } |
79 | 71 | ||
80 | void twofish_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv) | 72 | static void twofish_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv) |
81 | { | 73 | { |
82 | glue_xts_crypt_128bit_one(ctx, dst, src, iv, | 74 | glue_xts_crypt_128bit_one(ctx, dst, src, iv, |
83 | GLUE_FUNC_CAST(twofish_enc_blk)); | 75 | GLUE_FUNC_CAST(twofish_enc_blk)); |
84 | } | 76 | } |
85 | EXPORT_SYMBOL_GPL(twofish_xts_enc); | ||
86 | 77 | ||
87 | void twofish_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv) | 78 | static void twofish_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv) |
88 | { | 79 | { |
89 | glue_xts_crypt_128bit_one(ctx, dst, src, iv, | 80 | glue_xts_crypt_128bit_one(ctx, dst, src, iv, |
90 | GLUE_FUNC_CAST(twofish_dec_blk)); | 81 | GLUE_FUNC_CAST(twofish_dec_blk)); |
91 | } | 82 | } |
92 | EXPORT_SYMBOL_GPL(twofish_xts_dec); | ||
93 | 83 | ||
94 | 84 | ||
95 | static const struct common_glue_ctx twofish_enc = { | 85 | static const struct common_glue_ctx twofish_enc = { |
diff --git a/arch/x86/include/asm/crypto/blowfish.h b/arch/x86/include/asm/crypto/blowfish.h deleted file mode 100644 index f097b2face10..000000000000 --- a/arch/x86/include/asm/crypto/blowfish.h +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | #ifndef ASM_X86_BLOWFISH_H | ||
2 | #define ASM_X86_BLOWFISH_H | ||
3 | |||
4 | #include <linux/crypto.h> | ||
5 | #include <crypto/blowfish.h> | ||
6 | |||
7 | #define BF_PARALLEL_BLOCKS 4 | ||
8 | |||
9 | /* regular block cipher functions */ | ||
10 | asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src, | ||
11 | bool xor); | ||
12 | asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src); | ||
13 | |||
14 | /* 4-way parallel cipher functions */ | ||
15 | asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst, | ||
16 | const u8 *src, bool xor); | ||
17 | asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst, | ||
18 | const u8 *src); | ||
19 | |||
20 | static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src) | ||
21 | { | ||
22 | __blowfish_enc_blk(ctx, dst, src, false); | ||
23 | } | ||
24 | |||
25 | static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst, | ||
26 | const u8 *src) | ||
27 | { | ||
28 | __blowfish_enc_blk(ctx, dst, src, true); | ||
29 | } | ||
30 | |||
31 | static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst, | ||
32 | const u8 *src) | ||
33 | { | ||
34 | __blowfish_enc_blk_4way(ctx, dst, src, false); | ||
35 | } | ||
36 | |||
37 | static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst, | ||
38 | const u8 *src) | ||
39 | { | ||
40 | __blowfish_enc_blk_4way(ctx, dst, src, true); | ||
41 | } | ||
42 | |||
43 | #endif | ||
diff --git a/arch/x86/include/asm/crypto/twofish.h b/arch/x86/include/asm/crypto/twofish.h index e655c6029b45..878c51ceebb5 100644 --- a/arch/x86/include/asm/crypto/twofish.h +++ b/arch/x86/include/asm/crypto/twofish.h | |||
@@ -28,20 +28,6 @@ asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst, | |||
28 | asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, | 28 | asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst, |
29 | const u8 *src); | 29 | const u8 *src); |
30 | 30 | ||
31 | /* 8-way parallel cipher functions */ | ||
32 | asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst, | ||
33 | const u8 *src); | ||
34 | asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst, | ||
35 | const u8 *src); | ||
36 | asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst, | ||
37 | const u8 *src); | ||
38 | asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst, | ||
39 | const u8 *src, le128 *iv); | ||
40 | asmlinkage void twofish_xts_enc_8way(struct twofish_ctx *ctx, u8 *dst, | ||
41 | const u8 *src, le128 *iv); | ||
42 | asmlinkage void twofish_xts_dec_8way(struct twofish_ctx *ctx, u8 *dst, | ||
43 | const u8 *src, le128 *iv); | ||
44 | |||
45 | /* helpers from twofish_x86_64-3way module */ | 31 | /* helpers from twofish_x86_64-3way module */ |
46 | extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src); | 32 | extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src); |
47 | extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, | 33 | extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, |
@@ -57,8 +43,4 @@ extern void lrw_twofish_exit_tfm(struct crypto_tfm *tfm); | |||
57 | extern int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, | 43 | extern int xts_twofish_setkey(struct crypto_tfm *tfm, const u8 *key, |
58 | unsigned int keylen); | 44 | unsigned int keylen); |
59 | 45 | ||
60 | /* helpers from twofish-avx module */ | ||
61 | extern void twofish_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv); | ||
62 | extern void twofish_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv); | ||
63 | |||
64 | #endif /* ASM_X86_TWOFISH_H */ | 46 | #endif /* ASM_X86_TWOFISH_H */ |
diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h index d354fb781c57..a55c7efcc4ed 100644 --- a/arch/x86/include/asm/mc146818rtc.h +++ b/arch/x86/include/asm/mc146818rtc.h | |||
@@ -95,8 +95,8 @@ static inline unsigned char current_lock_cmos_reg(void) | |||
95 | unsigned char rtc_cmos_read(unsigned char addr); | 95 | unsigned char rtc_cmos_read(unsigned char addr); |
96 | void rtc_cmos_write(unsigned char val, unsigned char addr); | 96 | void rtc_cmos_write(unsigned char val, unsigned char addr); |
97 | 97 | ||
98 | extern int mach_set_rtc_mmss(unsigned long nowtime); | 98 | extern int mach_set_rtc_mmss(const struct timespec *now); |
99 | extern unsigned long mach_get_cmos_time(void); | 99 | extern void mach_get_cmos_time(struct timespec *now); |
100 | 100 | ||
101 | #define RTC_IRQ 8 | 101 | #define RTC_IRQ 8 |
102 | 102 | ||
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/mrst-vrtc.h index 73668abdbedf..1e69a75412a4 100644 --- a/arch/x86/include/asm/mrst-vrtc.h +++ b/arch/x86/include/asm/mrst-vrtc.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | extern unsigned char vrtc_cmos_read(unsigned char reg); | 4 | extern unsigned char vrtc_cmos_read(unsigned char reg); |
5 | extern void vrtc_cmos_write(unsigned char val, unsigned char reg); | 5 | extern void vrtc_cmos_write(unsigned char val, unsigned char reg); |
6 | extern unsigned long vrtc_get_time(void); | 6 | extern void vrtc_get_time(struct timespec *now); |
7 | extern int vrtc_set_mmss(unsigned long nowtime); | 7 | extern int vrtc_set_mmss(const struct timespec *now); |
8 | 8 | ||
9 | #endif | 9 | #endif |
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index d8d99222b36a..828a1565ba57 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
@@ -142,6 +142,8 @@ struct x86_cpuinit_ops { | |||
142 | void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node); | 142 | void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node); |
143 | }; | 143 | }; |
144 | 144 | ||
145 | struct timespec; | ||
146 | |||
145 | /** | 147 | /** |
146 | * struct x86_platform_ops - platform specific runtime functions | 148 | * struct x86_platform_ops - platform specific runtime functions |
147 | * @calibrate_tsc: calibrate TSC | 149 | * @calibrate_tsc: calibrate TSC |
@@ -156,8 +158,8 @@ struct x86_cpuinit_ops { | |||
156 | */ | 158 | */ |
157 | struct x86_platform_ops { | 159 | struct x86_platform_ops { |
158 | unsigned long (*calibrate_tsc)(void); | 160 | unsigned long (*calibrate_tsc)(void); |
159 | unsigned long (*get_wallclock)(void); | 161 | void (*get_wallclock)(struct timespec *ts); |
160 | int (*set_wallclock)(unsigned long nowtime); | 162 | int (*set_wallclock)(const struct timespec *ts); |
161 | void (*iommu_shutdown)(void); | 163 | void (*iommu_shutdown)(void); |
162 | bool (*is_untracked_pat_range)(u64 start, u64 end); | 164 | bool (*is_untracked_pat_range)(u64 start, u64 end); |
163 | void (*nmi_init)(void); | 165 | void (*nmi_init)(void); |
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index b1581527a236..4934890e4db2 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c | |||
@@ -364,9 +364,7 @@ static void dt_add_ioapic_domain(unsigned int ioapic_num, | |||
364 | * and assigned so we can keep the 1:1 mapping which the ioapic | 364 | * and assigned so we can keep the 1:1 mapping which the ioapic |
365 | * is having. | 365 | * is having. |
366 | */ | 366 | */ |
367 | ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY); | 367 | irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY); |
368 | if (ret) | ||
369 | pr_err("Error mapping legacy IRQs: %d\n", ret); | ||
370 | 368 | ||
371 | if (num > NR_IRQS_LEGACY) { | 369 | if (num > NR_IRQS_LEGACY) { |
372 | ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY, | 370 | ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY, |
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 3dd37ebd591b..1f354f4b602b 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c | |||
@@ -48,10 +48,9 @@ static struct pvclock_wall_clock wall_clock; | |||
48 | * have elapsed since the hypervisor wrote the data. So we try to account for | 48 | * have elapsed since the hypervisor wrote the data. So we try to account for |
49 | * that with system time | 49 | * that with system time |
50 | */ | 50 | */ |
51 | static unsigned long kvm_get_wallclock(void) | 51 | static void kvm_get_wallclock(struct timespec *now) |
52 | { | 52 | { |
53 | struct pvclock_vcpu_time_info *vcpu_time; | 53 | struct pvclock_vcpu_time_info *vcpu_time; |
54 | struct timespec ts; | ||
55 | int low, high; | 54 | int low, high; |
56 | int cpu; | 55 | int cpu; |
57 | 56 | ||
@@ -64,14 +63,12 @@ static unsigned long kvm_get_wallclock(void) | |||
64 | cpu = smp_processor_id(); | 63 | cpu = smp_processor_id(); |
65 | 64 | ||
66 | vcpu_time = &hv_clock[cpu].pvti; | 65 | vcpu_time = &hv_clock[cpu].pvti; |
67 | pvclock_read_wallclock(&wall_clock, vcpu_time, &ts); | 66 | pvclock_read_wallclock(&wall_clock, vcpu_time, now); |
68 | 67 | ||
69 | preempt_enable(); | 68 | preempt_enable(); |
70 | |||
71 | return ts.tv_sec; | ||
72 | } | 69 | } |
73 | 70 | ||
74 | static int kvm_set_wallclock(unsigned long now) | 71 | static int kvm_set_wallclock(const struct timespec *now) |
75 | { | 72 | { |
76 | return -1; | 73 | return -1; |
77 | } | 74 | } |
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 198eb201ed3b..0aa29394ed6f 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c | |||
@@ -38,8 +38,9 @@ EXPORT_SYMBOL(rtc_lock); | |||
38 | * jump to the next second precisely 500 ms later. Check the Motorola | 38 | * jump to the next second precisely 500 ms later. Check the Motorola |
39 | * MC146818A or Dallas DS12887 data sheet for details. | 39 | * MC146818A or Dallas DS12887 data sheet for details. |
40 | */ | 40 | */ |
41 | int mach_set_rtc_mmss(unsigned long nowtime) | 41 | int mach_set_rtc_mmss(const struct timespec *now) |
42 | { | 42 | { |
43 | unsigned long nowtime = now->tv_sec; | ||
43 | struct rtc_time tm; | 44 | struct rtc_time tm; |
44 | int retval = 0; | 45 | int retval = 0; |
45 | 46 | ||
@@ -58,7 +59,7 @@ int mach_set_rtc_mmss(unsigned long nowtime) | |||
58 | return retval; | 59 | return retval; |
59 | } | 60 | } |
60 | 61 | ||
61 | unsigned long mach_get_cmos_time(void) | 62 | void mach_get_cmos_time(struct timespec *now) |
62 | { | 63 | { |
63 | unsigned int status, year, mon, day, hour, min, sec, century = 0; | 64 | unsigned int status, year, mon, day, hour, min, sec, century = 0; |
64 | unsigned long flags; | 65 | unsigned long flags; |
@@ -107,7 +108,8 @@ unsigned long mach_get_cmos_time(void) | |||
107 | } else | 108 | } else |
108 | year += CMOS_YEARS_OFFS; | 109 | year += CMOS_YEARS_OFFS; |
109 | 110 | ||
110 | return mktime(year, mon, day, hour, min, sec); | 111 | now->tv_sec = mktime(year, mon, day, hour, min, sec); |
112 | now->tv_nsec = 0; | ||
111 | } | 113 | } |
112 | 114 | ||
113 | /* Routines for accessing the CMOS RAM/RTC. */ | 115 | /* Routines for accessing the CMOS RAM/RTC. */ |
@@ -135,18 +137,13 @@ EXPORT_SYMBOL(rtc_cmos_write); | |||
135 | 137 | ||
136 | int update_persistent_clock(struct timespec now) | 138 | int update_persistent_clock(struct timespec now) |
137 | { | 139 | { |
138 | return x86_platform.set_wallclock(now.tv_sec); | 140 | return x86_platform.set_wallclock(&now); |
139 | } | 141 | } |
140 | 142 | ||
141 | /* not static: needed by APM */ | 143 | /* not static: needed by APM */ |
142 | void read_persistent_clock(struct timespec *ts) | 144 | void read_persistent_clock(struct timespec *ts) |
143 | { | 145 | { |
144 | unsigned long retval; | 146 | x86_platform.get_wallclock(ts); |
145 | |||
146 | retval = x86_platform.get_wallclock(); | ||
147 | |||
148 | ts->tv_sec = retval; | ||
149 | ts->tv_nsec = 0; | ||
150 | } | 147 | } |
151 | 148 | ||
152 | 149 | ||
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index d482bcaf61c1..6a22c19da663 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -882,9 +882,9 @@ int lguest_setup_irq(unsigned int irq) | |||
882 | * It would be far better for everyone if the Guest had its own clock, but | 882 | * It would be far better for everyone if the Guest had its own clock, but |
883 | * until then the Host gives us the time on every interrupt. | 883 | * until then the Host gives us the time on every interrupt. |
884 | */ | 884 | */ |
885 | static unsigned long lguest_get_wallclock(void) | 885 | static void lguest_get_wallclock(struct timespec *now) |
886 | { | 886 | { |
887 | return lguest_data.time.tv_sec; | 887 | *now = lguest_data.time; |
888 | } | 888 | } |
889 | 889 | ||
890 | /* | 890 | /* |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b410b71bdcf7..c8d5577044bb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -274,8 +274,9 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm, | |||
274 | return status; | 274 | return status; |
275 | } | 275 | } |
276 | 276 | ||
277 | int efi_set_rtc_mmss(unsigned long nowtime) | 277 | int efi_set_rtc_mmss(const struct timespec *now) |
278 | { | 278 | { |
279 | unsigned long nowtime = now->tv_sec; | ||
279 | efi_status_t status; | 280 | efi_status_t status; |
280 | efi_time_t eft; | 281 | efi_time_t eft; |
281 | efi_time_cap_t cap; | 282 | efi_time_cap_t cap; |
@@ -310,7 +311,7 @@ int efi_set_rtc_mmss(unsigned long nowtime) | |||
310 | return 0; | 311 | return 0; |
311 | } | 312 | } |
312 | 313 | ||
313 | unsigned long efi_get_time(void) | 314 | void efi_get_time(struct timespec *now) |
314 | { | 315 | { |
315 | efi_status_t status; | 316 | efi_status_t status; |
316 | efi_time_t eft; | 317 | efi_time_t eft; |
@@ -320,8 +321,9 @@ unsigned long efi_get_time(void) | |||
320 | if (status != EFI_SUCCESS) | 321 | if (status != EFI_SUCCESS) |
321 | pr_err("Oops: efitime: can't read time!\n"); | 322 | pr_err("Oops: efitime: can't read time!\n"); |
322 | 323 | ||
323 | return mktime(eft.year, eft.month, eft.day, eft.hour, | 324 | now->tv_sec = mktime(eft.year, eft.month, eft.day, eft.hour, |
324 | eft.minute, eft.second); | 325 | eft.minute, eft.second); |
326 | now->tv_nsec = 0; | ||
325 | } | 327 | } |
326 | 328 | ||
327 | /* | 329 | /* |
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c index d62b0a3b5c14..5e355b134ba4 100644 --- a/arch/x86/platform/mrst/vrtc.c +++ b/arch/x86/platform/mrst/vrtc.c | |||
@@ -56,7 +56,7 @@ void vrtc_cmos_write(unsigned char val, unsigned char reg) | |||
56 | } | 56 | } |
57 | EXPORT_SYMBOL_GPL(vrtc_cmos_write); | 57 | EXPORT_SYMBOL_GPL(vrtc_cmos_write); |
58 | 58 | ||
59 | unsigned long vrtc_get_time(void) | 59 | void vrtc_get_time(struct timespec *now) |
60 | { | 60 | { |
61 | u8 sec, min, hour, mday, mon; | 61 | u8 sec, min, hour, mday, mon; |
62 | unsigned long flags; | 62 | unsigned long flags; |
@@ -82,17 +82,18 @@ unsigned long vrtc_get_time(void) | |||
82 | printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " | 82 | printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " |
83 | "mon: %d year: %d\n", sec, min, hour, mday, mon, year); | 83 | "mon: %d year: %d\n", sec, min, hour, mday, mon, year); |
84 | 84 | ||
85 | return mktime(year, mon, mday, hour, min, sec); | 85 | now->tv_sec = mktime(year, mon, mday, hour, min, sec); |
86 | now->tv_nsec = 0; | ||
86 | } | 87 | } |
87 | 88 | ||
88 | int vrtc_set_mmss(unsigned long nowtime) | 89 | int vrtc_set_mmss(const struct timespec *now) |
89 | { | 90 | { |
90 | unsigned long flags; | 91 | unsigned long flags; |
91 | struct rtc_time tm; | 92 | struct rtc_time tm; |
92 | int year; | 93 | int year; |
93 | int retval = 0; | 94 | int retval = 0; |
94 | 95 | ||
95 | rtc_time_to_tm(nowtime, &tm); | 96 | rtc_time_to_tm(now->tv_sec, &tm); |
96 | if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) { | 97 | if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) { |
97 | /* | 98 | /* |
98 | * tm.year is the number of years since 1900, and the | 99 | * tm.year is the number of years since 1900, and the |
@@ -110,7 +111,7 @@ int vrtc_set_mmss(unsigned long nowtime) | |||
110 | } else { | 111 | } else { |
111 | printk(KERN_ERR | 112 | printk(KERN_ERR |
112 | "%s: Invalid vRTC value: write of %lx to vRTC failed\n", | 113 | "%s: Invalid vRTC value: write of %lx to vRTC failed\n", |
113 | __FUNCTION__, nowtime); | 114 | __FUNCTION__, now->tv_sec); |
114 | retval = -EINVAL; | 115 | retval = -EINVAL; |
115 | } | 116 | } |
116 | return retval; | 117 | return retval; |
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index a690868be837..ee365895b06b 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/math64.h> | 15 | #include <linux/math64.h> |
16 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/pvclock_gtod.h> | ||
18 | 19 | ||
19 | #include <asm/pvclock.h> | 20 | #include <asm/pvclock.h> |
20 | #include <asm/xen/hypervisor.h> | 21 | #include <asm/xen/hypervisor.h> |
@@ -179,34 +180,56 @@ static void xen_read_wallclock(struct timespec *ts) | |||
179 | put_cpu_var(xen_vcpu); | 180 | put_cpu_var(xen_vcpu); |
180 | } | 181 | } |
181 | 182 | ||
182 | static unsigned long xen_get_wallclock(void) | 183 | static void xen_get_wallclock(struct timespec *now) |
183 | { | 184 | { |
184 | struct timespec ts; | 185 | xen_read_wallclock(now); |
186 | } | ||
185 | 187 | ||
186 | xen_read_wallclock(&ts); | 188 | static int xen_set_wallclock(const struct timespec *now) |
187 | return ts.tv_sec; | 189 | { |
190 | return -1; | ||
188 | } | 191 | } |
189 | 192 | ||
190 | static int xen_set_wallclock(unsigned long now) | 193 | static int xen_pvclock_gtod_notify(struct notifier_block *nb, |
194 | unsigned long was_set, void *priv) | ||
191 | { | 195 | { |
196 | /* Protected by the calling core code serialization */ | ||
197 | static struct timespec next_sync; | ||
198 | |||
192 | struct xen_platform_op op; | 199 | struct xen_platform_op op; |
193 | int rc; | 200 | struct timespec now; |
194 | 201 | ||
195 | /* do nothing for domU */ | 202 | now = __current_kernel_time(); |
196 | if (!xen_initial_domain()) | 203 | |
197 | return -1; | 204 | /* |
205 | * We only take the expensive HV call when the clock was set | ||
206 | * or when the 11 minutes RTC synchronization time elapsed. | ||
207 | */ | ||
208 | if (!was_set && timespec_compare(&now, &next_sync) < 0) | ||
209 | return NOTIFY_OK; | ||
198 | 210 | ||
199 | op.cmd = XENPF_settime; | 211 | op.cmd = XENPF_settime; |
200 | op.u.settime.secs = now; | 212 | op.u.settime.secs = now.tv_sec; |
201 | op.u.settime.nsecs = 0; | 213 | op.u.settime.nsecs = now.tv_nsec; |
202 | op.u.settime.system_time = xen_clocksource_read(); | 214 | op.u.settime.system_time = xen_clocksource_read(); |
203 | 215 | ||
204 | rc = HYPERVISOR_dom0_op(&op); | 216 | (void)HYPERVISOR_dom0_op(&op); |
205 | WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now); | ||
206 | 217 | ||
207 | return rc; | 218 | /* |
219 | * Move the next drift compensation time 11 minutes | ||
220 | * ahead. That's emulating the sync_cmos_clock() update for | ||
221 | * the hardware RTC. | ||
222 | */ | ||
223 | next_sync = now; | ||
224 | next_sync.tv_sec += 11 * 60; | ||
225 | |||
226 | return NOTIFY_OK; | ||
208 | } | 227 | } |
209 | 228 | ||
229 | static struct notifier_block xen_pvclock_gtod_notifier = { | ||
230 | .notifier_call = xen_pvclock_gtod_notify, | ||
231 | }; | ||
232 | |||
210 | static struct clocksource xen_clocksource __read_mostly = { | 233 | static struct clocksource xen_clocksource __read_mostly = { |
211 | .name = "xen", | 234 | .name = "xen", |
212 | .rating = 400, | 235 | .rating = 400, |
@@ -482,6 +505,9 @@ static void __init xen_time_init(void) | |||
482 | xen_setup_runstate_info(cpu); | 505 | xen_setup_runstate_info(cpu); |
483 | xen_setup_timer(cpu); | 506 | xen_setup_timer(cpu); |
484 | xen_setup_cpu_clockevents(); | 507 | xen_setup_cpu_clockevents(); |
508 | |||
509 | if (xen_initial_domain()) | ||
510 | pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier); | ||
485 | } | 511 | } |
486 | 512 | ||
487 | void __init xen_init_time_ops(void) | 513 | void __init xen_init_time_ops(void) |
@@ -494,7 +520,9 @@ void __init xen_init_time_ops(void) | |||
494 | 520 | ||
495 | x86_platform.calibrate_tsc = xen_tsc_khz; | 521 | x86_platform.calibrate_tsc = xen_tsc_khz; |
496 | x86_platform.get_wallclock = xen_get_wallclock; | 522 | x86_platform.get_wallclock = xen_get_wallclock; |
497 | x86_platform.set_wallclock = xen_set_wallclock; | 523 | /* Dom0 uses the native method to set the hardware RTC. */ |
524 | if (!xen_initial_domain()) | ||
525 | x86_platform.set_wallclock = xen_set_wallclock; | ||
498 | } | 526 | } |
499 | 527 | ||
500 | #ifdef CONFIG_XEN_PVHVM | 528 | #ifdef CONFIG_XEN_PVHVM |
diff --git a/crypto/Kconfig b/crypto/Kconfig index bf8148e74e73..904ffe838567 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
@@ -376,6 +376,25 @@ config CRYPTO_CRC32_PCLMUL | |||
376 | which will enable any routine to use the CRC-32-IEEE 802.3 checksum | 376 | which will enable any routine to use the CRC-32-IEEE 802.3 checksum |
377 | and gain better performance as compared with the table implementation. | 377 | and gain better performance as compared with the table implementation. |
378 | 378 | ||
379 | config CRYPTO_CRCT10DIF | ||
380 | tristate "CRCT10DIF algorithm" | ||
381 | select CRYPTO_HASH | ||
382 | help | ||
383 | CRC T10 Data Integrity Field computation is being cast as | ||
384 | a crypto transform. This allows for faster crc t10 diff | ||
385 | transforms to be used if they are available. | ||
386 | |||
387 | config CRYPTO_CRCT10DIF_PCLMUL | ||
388 | tristate "CRCT10DIF PCLMULQDQ hardware acceleration" | ||
389 | depends on X86 && 64BIT && CRC_T10DIF | ||
390 | select CRYPTO_HASH | ||
391 | help | ||
392 | For x86_64 processors with SSE4.2 and PCLMULQDQ supported, | ||
393 | CRC T10 DIF PCLMULQDQ computation can be hardware | ||
394 | accelerated PCLMULQDQ instruction. This option will create | ||
395 | 'crct10dif-plcmul' module, which is faster when computing the | ||
396 | crct10dif checksum as compared with the generic table implementation. | ||
397 | |||
379 | config CRYPTO_GHASH | 398 | config CRYPTO_GHASH |
380 | tristate "GHASH digest algorithm" | 399 | tristate "GHASH digest algorithm" |
381 | select CRYPTO_GF128MUL | 400 | select CRYPTO_GF128MUL |
@@ -820,25 +839,6 @@ config CRYPTO_BLOWFISH_X86_64 | |||
820 | See also: | 839 | See also: |
821 | <http://www.schneier.com/blowfish.html> | 840 | <http://www.schneier.com/blowfish.html> |
822 | 841 | ||
823 | config CRYPTO_BLOWFISH_AVX2_X86_64 | ||
824 | tristate "Blowfish cipher algorithm (x86_64/AVX2)" | ||
825 | depends on X86 && 64BIT | ||
826 | depends on BROKEN | ||
827 | select CRYPTO_ALGAPI | ||
828 | select CRYPTO_CRYPTD | ||
829 | select CRYPTO_ABLK_HELPER_X86 | ||
830 | select CRYPTO_BLOWFISH_COMMON | ||
831 | select CRYPTO_BLOWFISH_X86_64 | ||
832 | help | ||
833 | Blowfish cipher algorithm (x86_64/AVX2), by Bruce Schneier. | ||
834 | |||
835 | This is a variable key length cipher which can use keys from 32 | ||
836 | bits to 448 bits in length. It's fast, simple and specifically | ||
837 | designed for use on "large microprocessors". | ||
838 | |||
839 | See also: | ||
840 | <http://www.schneier.com/blowfish.html> | ||
841 | |||
842 | config CRYPTO_CAMELLIA | 842 | config CRYPTO_CAMELLIA |
843 | tristate "Camellia cipher algorithms" | 843 | tristate "Camellia cipher algorithms" |
844 | depends on CRYPTO | 844 | depends on CRYPTO |
@@ -1297,31 +1297,6 @@ config CRYPTO_TWOFISH_AVX_X86_64 | |||
1297 | See also: | 1297 | See also: |
1298 | <http://www.schneier.com/twofish.html> | 1298 | <http://www.schneier.com/twofish.html> |
1299 | 1299 | ||
1300 | config CRYPTO_TWOFISH_AVX2_X86_64 | ||
1301 | tristate "Twofish cipher algorithm (x86_64/AVX2)" | ||
1302 | depends on X86 && 64BIT | ||
1303 | depends on BROKEN | ||
1304 | select CRYPTO_ALGAPI | ||
1305 | select CRYPTO_CRYPTD | ||
1306 | select CRYPTO_ABLK_HELPER_X86 | ||
1307 | select CRYPTO_GLUE_HELPER_X86 | ||
1308 | select CRYPTO_TWOFISH_COMMON | ||
1309 | select CRYPTO_TWOFISH_X86_64 | ||
1310 | select CRYPTO_TWOFISH_X86_64_3WAY | ||
1311 | select CRYPTO_TWOFISH_AVX_X86_64 | ||
1312 | select CRYPTO_LRW | ||
1313 | select CRYPTO_XTS | ||
1314 | help | ||
1315 | Twofish cipher algorithm (x86_64/AVX2). | ||
1316 | |||
1317 | Twofish was submitted as an AES (Advanced Encryption Standard) | ||
1318 | candidate cipher by researchers at CounterPane Systems. It is a | ||
1319 | 16 round block cipher supporting key sizes of 128, 192, and 256 | ||
1320 | bits. | ||
1321 | |||
1322 | See also: | ||
1323 | <http://www.schneier.com/twofish.html> | ||
1324 | |||
1325 | comment "Compression" | 1300 | comment "Compression" |
1326 | 1301 | ||
1327 | config CRYPTO_DEFLATE | 1302 | config CRYPTO_DEFLATE |
diff --git a/crypto/Makefile b/crypto/Makefile index a8e9b0fefbe9..62af87df8729 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -83,6 +83,7 @@ obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o | |||
83 | obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o | 83 | obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o |
84 | obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o | 84 | obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o |
85 | obj-$(CONFIG_CRYPTO_CRC32) += crc32.o | 85 | obj-$(CONFIG_CRYPTO_CRC32) += crc32.o |
86 | obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif.o | ||
86 | obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o | 87 | obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o |
87 | obj-$(CONFIG_CRYPTO_LZO) += lzo.o | 88 | obj-$(CONFIG_CRYPTO_LZO) += lzo.o |
88 | obj-$(CONFIG_CRYPTO_842) += 842.o | 89 | obj-$(CONFIG_CRYPTO_842) += 842.o |
diff --git a/crypto/crct10dif.c b/crypto/crct10dif.c new file mode 100644 index 000000000000..92aca96d6b98 --- /dev/null +++ b/crypto/crct10dif.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * T10 Data Integrity Field CRC16 Crypto Transform | ||
5 | * | ||
6 | * Copyright (c) 2007 Oracle Corporation. All rights reserved. | ||
7 | * Written by Martin K. Petersen <martin.petersen@oracle.com> | ||
8 | * Copyright (C) 2013 Intel Corporation | ||
9 | * Author: Tim Chen <tim.c.chen@linux.intel.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the Free | ||
13 | * Software Foundation; either version 2 of the License, or (at your option) | ||
14 | * any later version. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
23 | * SOFTWARE. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/crc-t10dif.h> | ||
30 | #include <crypto/internal/hash.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/string.h> | ||
33 | #include <linux/kernel.h> | ||
34 | |||
35 | struct chksum_desc_ctx { | ||
36 | __u16 crc; | ||
37 | }; | ||
38 | |||
39 | /* Table generated using the following polynomium: | ||
40 | * x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 | ||
41 | * gt: 0x8bb7 | ||
42 | */ | ||
43 | static const __u16 t10_dif_crc_table[256] = { | ||
44 | 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, | ||
45 | 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, | ||
46 | 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, | ||
47 | 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, | ||
48 | 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, | ||
49 | 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, | ||
50 | 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, | ||
51 | 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, | ||
52 | 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, | ||
53 | 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, | ||
54 | 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, | ||
55 | 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, | ||
56 | 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, | ||
57 | 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, | ||
58 | 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, | ||
59 | 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, | ||
60 | 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, | ||
61 | 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, | ||
62 | 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, | ||
63 | 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, | ||
64 | 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, | ||
65 | 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, | ||
66 | 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, | ||
67 | 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, | ||
68 | 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, | ||
69 | 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, | ||
70 | 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, | ||
71 | 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, | ||
72 | 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, | ||
73 | 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, | ||
74 | 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, | ||
75 | 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 | ||
76 | }; | ||
77 | |||
78 | __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, size_t len) | ||
79 | { | ||
80 | unsigned int i; | ||
81 | |||
82 | for (i = 0 ; i < len ; i++) | ||
83 | crc = (crc << 8) ^ t10_dif_crc_table[((crc >> 8) ^ buffer[i]) & 0xff]; | ||
84 | |||
85 | return crc; | ||
86 | } | ||
87 | EXPORT_SYMBOL(crc_t10dif_generic); | ||
88 | |||
89 | /* | ||
90 | * Steps through buffer one byte at at time, calculates reflected | ||
91 | * crc using table. | ||
92 | */ | ||
93 | |||
94 | static int chksum_init(struct shash_desc *desc) | ||
95 | { | ||
96 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
97 | |||
98 | ctx->crc = 0; | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int chksum_update(struct shash_desc *desc, const u8 *data, | ||
104 | unsigned int length) | ||
105 | { | ||
106 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
107 | |||
108 | ctx->crc = crc_t10dif_generic(ctx->crc, data, length); | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int chksum_final(struct shash_desc *desc, u8 *out) | ||
113 | { | ||
114 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
115 | |||
116 | *(__u16 *)out = ctx->crc; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int __chksum_finup(__u16 *crcp, const u8 *data, unsigned int len, | ||
121 | u8 *out) | ||
122 | { | ||
123 | *(__u16 *)out = crc_t10dif_generic(*crcp, data, len); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int chksum_finup(struct shash_desc *desc, const u8 *data, | ||
128 | unsigned int len, u8 *out) | ||
129 | { | ||
130 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
131 | |||
132 | return __chksum_finup(&ctx->crc, data, len, out); | ||
133 | } | ||
134 | |||
135 | static int chksum_digest(struct shash_desc *desc, const u8 *data, | ||
136 | unsigned int length, u8 *out) | ||
137 | { | ||
138 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | ||
139 | |||
140 | return __chksum_finup(&ctx->crc, data, length, out); | ||
141 | } | ||
142 | |||
143 | static struct shash_alg alg = { | ||
144 | .digestsize = CRC_T10DIF_DIGEST_SIZE, | ||
145 | .init = chksum_init, | ||
146 | .update = chksum_update, | ||
147 | .final = chksum_final, | ||
148 | .finup = chksum_finup, | ||
149 | .digest = chksum_digest, | ||
150 | .descsize = sizeof(struct chksum_desc_ctx), | ||
151 | .base = { | ||
152 | .cra_name = "crct10dif", | ||
153 | .cra_driver_name = "crct10dif-generic", | ||
154 | .cra_priority = 100, | ||
155 | .cra_blocksize = CRC_T10DIF_BLOCK_SIZE, | ||
156 | .cra_module = THIS_MODULE, | ||
157 | } | ||
158 | }; | ||
159 | |||
160 | static int __init crct10dif_mod_init(void) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | ret = crypto_register_shash(&alg); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static void __exit crct10dif_mod_fini(void) | ||
169 | { | ||
170 | crypto_unregister_shash(&alg); | ||
171 | } | ||
172 | |||
173 | module_init(crct10dif_mod_init); | ||
174 | module_exit(crct10dif_mod_fini); | ||
175 | |||
176 | MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>"); | ||
177 | MODULE_DESCRIPTION("T10 DIF CRC calculation."); | ||
178 | MODULE_LICENSE("GPL"); | ||
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c index 4c5862095679..6ed124f3ea0f 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c | |||
@@ -251,6 +251,7 @@ static struct shash_alg sha512_algs[2] = { { | |||
251 | .descsize = sizeof(struct sha512_state), | 251 | .descsize = sizeof(struct sha512_state), |
252 | .base = { | 252 | .base = { |
253 | .cra_name = "sha512", | 253 | .cra_name = "sha512", |
254 | .cra_driver_name = "sha512-generic", | ||
254 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | 255 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, |
255 | .cra_blocksize = SHA512_BLOCK_SIZE, | 256 | .cra_blocksize = SHA512_BLOCK_SIZE, |
256 | .cra_module = THIS_MODULE, | 257 | .cra_module = THIS_MODULE, |
@@ -263,6 +264,7 @@ static struct shash_alg sha512_algs[2] = { { | |||
263 | .descsize = sizeof(struct sha512_state), | 264 | .descsize = sizeof(struct sha512_state), |
264 | .base = { | 265 | .base = { |
265 | .cra_name = "sha384", | 266 | .cra_name = "sha384", |
267 | .cra_driver_name = "sha384-generic", | ||
266 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | 268 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, |
267 | .cra_blocksize = SHA384_BLOCK_SIZE, | 269 | .cra_blocksize = SHA384_BLOCK_SIZE, |
268 | .cra_module = THIS_MODULE, | 270 | .cra_module = THIS_MODULE, |
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 66d254ce0d11..25a5934f0e50 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c | |||
@@ -1174,6 +1174,10 @@ static int do_test(int m) | |||
1174 | ret += tcrypt_test("ghash"); | 1174 | ret += tcrypt_test("ghash"); |
1175 | break; | 1175 | break; |
1176 | 1176 | ||
1177 | case 47: | ||
1178 | ret += tcrypt_test("crct10dif"); | ||
1179 | break; | ||
1180 | |||
1177 | case 100: | 1181 | case 100: |
1178 | ret += tcrypt_test("hmac(md5)"); | 1182 | ret += tcrypt_test("hmac(md5)"); |
1179 | break; | 1183 | break; |
@@ -1498,6 +1502,10 @@ static int do_test(int m) | |||
1498 | test_hash_speed("crc32c", sec, generic_hash_speed_template); | 1502 | test_hash_speed("crc32c", sec, generic_hash_speed_template); |
1499 | if (mode > 300 && mode < 400) break; | 1503 | if (mode > 300 && mode < 400) break; |
1500 | 1504 | ||
1505 | case 320: | ||
1506 | test_hash_speed("crct10dif", sec, generic_hash_speed_template); | ||
1507 | if (mode > 300 && mode < 400) break; | ||
1508 | |||
1501 | case 399: | 1509 | case 399: |
1502 | break; | 1510 | break; |
1503 | 1511 | ||
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5823735cf381..2f00607039e2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c | |||
@@ -184,8 +184,9 @@ static int do_one_async_hash_op(struct ahash_request *req, | |||
184 | return ret; | 184 | return ret; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | 187 | static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, |
188 | unsigned int tcount, bool use_digest) | 188 | unsigned int tcount, bool use_digest, |
189 | const int align_offset) | ||
189 | { | 190 | { |
190 | const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm)); | 191 | const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm)); |
191 | unsigned int i, j, k, temp; | 192 | unsigned int i, j, k, temp; |
@@ -216,10 +217,15 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | |||
216 | if (template[i].np) | 217 | if (template[i].np) |
217 | continue; | 218 | continue; |
218 | 219 | ||
220 | ret = -EINVAL; | ||
221 | if (WARN_ON(align_offset + template[i].psize > PAGE_SIZE)) | ||
222 | goto out; | ||
223 | |||
219 | j++; | 224 | j++; |
220 | memset(result, 0, 64); | 225 | memset(result, 0, 64); |
221 | 226 | ||
222 | hash_buff = xbuf[0]; | 227 | hash_buff = xbuf[0]; |
228 | hash_buff += align_offset; | ||
223 | 229 | ||
224 | memcpy(hash_buff, template[i].plaintext, template[i].psize); | 230 | memcpy(hash_buff, template[i].plaintext, template[i].psize); |
225 | sg_init_one(&sg[0], hash_buff, template[i].psize); | 231 | sg_init_one(&sg[0], hash_buff, template[i].psize); |
@@ -281,6 +287,10 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | |||
281 | 287 | ||
282 | j = 0; | 288 | j = 0; |
283 | for (i = 0; i < tcount; i++) { | 289 | for (i = 0; i < tcount; i++) { |
290 | /* alignment tests are only done with continuous buffers */ | ||
291 | if (align_offset != 0) | ||
292 | break; | ||
293 | |||
284 | if (template[i].np) { | 294 | if (template[i].np) { |
285 | j++; | 295 | j++; |
286 | memset(result, 0, 64); | 296 | memset(result, 0, 64); |
@@ -358,9 +368,36 @@ out_nobuf: | |||
358 | return ret; | 368 | return ret; |
359 | } | 369 | } |
360 | 370 | ||
371 | static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | ||
372 | unsigned int tcount, bool use_digest) | ||
373 | { | ||
374 | unsigned int alignmask; | ||
375 | int ret; | ||
376 | |||
377 | ret = __test_hash(tfm, template, tcount, use_digest, 0); | ||
378 | if (ret) | ||
379 | return ret; | ||
380 | |||
381 | /* test unaligned buffers, check with one byte offset */ | ||
382 | ret = __test_hash(tfm, template, tcount, use_digest, 1); | ||
383 | if (ret) | ||
384 | return ret; | ||
385 | |||
386 | alignmask = crypto_tfm_alg_alignmask(&tfm->base); | ||
387 | if (alignmask) { | ||
388 | /* Check if alignment mask for tfm is correctly set. */ | ||
389 | ret = __test_hash(tfm, template, tcount, use_digest, | ||
390 | alignmask + 1); | ||
391 | if (ret) | ||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
361 | static int __test_aead(struct crypto_aead *tfm, int enc, | 398 | static int __test_aead(struct crypto_aead *tfm, int enc, |
362 | struct aead_testvec *template, unsigned int tcount, | 399 | struct aead_testvec *template, unsigned int tcount, |
363 | const bool diff_dst) | 400 | const bool diff_dst, const int align_offset) |
364 | { | 401 | { |
365 | const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)); | 402 | const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)); |
366 | unsigned int i, j, k, n, temp; | 403 | unsigned int i, j, k, n, temp; |
@@ -423,15 +460,16 @@ static int __test_aead(struct crypto_aead *tfm, int enc, | |||
423 | if (!template[i].np) { | 460 | if (!template[i].np) { |
424 | j++; | 461 | j++; |
425 | 462 | ||
426 | /* some tepmplates have no input data but they will | 463 | /* some templates have no input data but they will |
427 | * touch input | 464 | * touch input |
428 | */ | 465 | */ |
429 | input = xbuf[0]; | 466 | input = xbuf[0]; |
467 | input += align_offset; | ||
430 | assoc = axbuf[0]; | 468 | assoc = axbuf[0]; |
431 | 469 | ||
432 | ret = -EINVAL; | 470 | ret = -EINVAL; |
433 | if (WARN_ON(template[i].ilen > PAGE_SIZE || | 471 | if (WARN_ON(align_offset + template[i].ilen > |
434 | template[i].alen > PAGE_SIZE)) | 472 | PAGE_SIZE || template[i].alen > PAGE_SIZE)) |
435 | goto out; | 473 | goto out; |
436 | 474 | ||
437 | memcpy(input, template[i].input, template[i].ilen); | 475 | memcpy(input, template[i].input, template[i].ilen); |
@@ -470,6 +508,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc, | |||
470 | 508 | ||
471 | if (diff_dst) { | 509 | if (diff_dst) { |
472 | output = xoutbuf[0]; | 510 | output = xoutbuf[0]; |
511 | output += align_offset; | ||
473 | sg_init_one(&sgout[0], output, | 512 | sg_init_one(&sgout[0], output, |
474 | template[i].ilen + | 513 | template[i].ilen + |
475 | (enc ? authsize : 0)); | 514 | (enc ? authsize : 0)); |
@@ -530,6 +569,10 @@ static int __test_aead(struct crypto_aead *tfm, int enc, | |||
530 | } | 569 | } |
531 | 570 | ||
532 | for (i = 0, j = 0; i < tcount; i++) { | 571 | for (i = 0, j = 0; i < tcount; i++) { |
572 | /* alignment tests are only done with continuous buffers */ | ||
573 | if (align_offset != 0) | ||
574 | break; | ||
575 | |||
533 | if (template[i].np) { | 576 | if (template[i].np) { |
534 | j++; | 577 | j++; |
535 | 578 | ||
@@ -732,15 +775,34 @@ out_noxbuf: | |||
732 | static int test_aead(struct crypto_aead *tfm, int enc, | 775 | static int test_aead(struct crypto_aead *tfm, int enc, |
733 | struct aead_testvec *template, unsigned int tcount) | 776 | struct aead_testvec *template, unsigned int tcount) |
734 | { | 777 | { |
778 | unsigned int alignmask; | ||
735 | int ret; | 779 | int ret; |
736 | 780 | ||
737 | /* test 'dst == src' case */ | 781 | /* test 'dst == src' case */ |
738 | ret = __test_aead(tfm, enc, template, tcount, false); | 782 | ret = __test_aead(tfm, enc, template, tcount, false, 0); |
739 | if (ret) | 783 | if (ret) |
740 | return ret; | 784 | return ret; |
741 | 785 | ||
742 | /* test 'dst != src' case */ | 786 | /* test 'dst != src' case */ |
743 | return __test_aead(tfm, enc, template, tcount, true); | 787 | ret = __test_aead(tfm, enc, template, tcount, true, 0); |
788 | if (ret) | ||
789 | return ret; | ||
790 | |||
791 | /* test unaligned buffers, check with one byte offset */ | ||
792 | ret = __test_aead(tfm, enc, template, tcount, true, 1); | ||
793 | if (ret) | ||
794 | return ret; | ||
795 | |||
796 | alignmask = crypto_tfm_alg_alignmask(&tfm->base); | ||
797 | if (alignmask) { | ||
798 | /* Check if alignment mask for tfm is correctly set. */ | ||
799 | ret = __test_aead(tfm, enc, template, tcount, true, | ||
800 | alignmask + 1); | ||
801 | if (ret) | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | return 0; | ||
744 | } | 806 | } |
745 | 807 | ||
746 | static int test_cipher(struct crypto_cipher *tfm, int enc, | 808 | static int test_cipher(struct crypto_cipher *tfm, int enc, |
@@ -820,7 +882,7 @@ out_nobuf: | |||
820 | 882 | ||
821 | static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc, | 883 | static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc, |
822 | struct cipher_testvec *template, unsigned int tcount, | 884 | struct cipher_testvec *template, unsigned int tcount, |
823 | const bool diff_dst) | 885 | const bool diff_dst, const int align_offset) |
824 | { | 886 | { |
825 | const char *algo = | 887 | const char *algo = |
826 | crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); | 888 | crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); |
@@ -876,10 +938,12 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
876 | j++; | 938 | j++; |
877 | 939 | ||
878 | ret = -EINVAL; | 940 | ret = -EINVAL; |
879 | if (WARN_ON(template[i].ilen > PAGE_SIZE)) | 941 | if (WARN_ON(align_offset + template[i].ilen > |
942 | PAGE_SIZE)) | ||
880 | goto out; | 943 | goto out; |
881 | 944 | ||
882 | data = xbuf[0]; | 945 | data = xbuf[0]; |
946 | data += align_offset; | ||
883 | memcpy(data, template[i].input, template[i].ilen); | 947 | memcpy(data, template[i].input, template[i].ilen); |
884 | 948 | ||
885 | crypto_ablkcipher_clear_flags(tfm, ~0); | 949 | crypto_ablkcipher_clear_flags(tfm, ~0); |
@@ -900,6 +964,7 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
900 | sg_init_one(&sg[0], data, template[i].ilen); | 964 | sg_init_one(&sg[0], data, template[i].ilen); |
901 | if (diff_dst) { | 965 | if (diff_dst) { |
902 | data = xoutbuf[0]; | 966 | data = xoutbuf[0]; |
967 | data += align_offset; | ||
903 | sg_init_one(&sgout[0], data, template[i].ilen); | 968 | sg_init_one(&sgout[0], data, template[i].ilen); |
904 | } | 969 | } |
905 | 970 | ||
@@ -941,6 +1006,9 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
941 | 1006 | ||
942 | j = 0; | 1007 | j = 0; |
943 | for (i = 0; i < tcount; i++) { | 1008 | for (i = 0; i < tcount; i++) { |
1009 | /* alignment tests are only done with continuous buffers */ | ||
1010 | if (align_offset != 0) | ||
1011 | break; | ||
944 | 1012 | ||
945 | if (template[i].iv) | 1013 | if (template[i].iv) |
946 | memcpy(iv, template[i].iv, MAX_IVLEN); | 1014 | memcpy(iv, template[i].iv, MAX_IVLEN); |
@@ -1075,15 +1143,34 @@ out_nobuf: | |||
1075 | static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, | 1143 | static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, |
1076 | struct cipher_testvec *template, unsigned int tcount) | 1144 | struct cipher_testvec *template, unsigned int tcount) |
1077 | { | 1145 | { |
1146 | unsigned int alignmask; | ||
1078 | int ret; | 1147 | int ret; |
1079 | 1148 | ||
1080 | /* test 'dst == src' case */ | 1149 | /* test 'dst == src' case */ |
1081 | ret = __test_skcipher(tfm, enc, template, tcount, false); | 1150 | ret = __test_skcipher(tfm, enc, template, tcount, false, 0); |
1082 | if (ret) | 1151 | if (ret) |
1083 | return ret; | 1152 | return ret; |
1084 | 1153 | ||
1085 | /* test 'dst != src' case */ | 1154 | /* test 'dst != src' case */ |
1086 | return __test_skcipher(tfm, enc, template, tcount, true); | 1155 | ret = __test_skcipher(tfm, enc, template, tcount, true, 0); |
1156 | if (ret) | ||
1157 | return ret; | ||
1158 | |||
1159 | /* test unaligned buffers, check with one byte offset */ | ||
1160 | ret = __test_skcipher(tfm, enc, template, tcount, true, 1); | ||
1161 | if (ret) | ||
1162 | return ret; | ||
1163 | |||
1164 | alignmask = crypto_tfm_alg_alignmask(&tfm->base); | ||
1165 | if (alignmask) { | ||
1166 | /* Check if alignment mask for tfm is correctly set. */ | ||
1167 | ret = __test_skcipher(tfm, enc, template, tcount, true, | ||
1168 | alignmask + 1); | ||
1169 | if (ret) | ||
1170 | return ret; | ||
1171 | } | ||
1172 | |||
1173 | return 0; | ||
1087 | } | 1174 | } |
1088 | 1175 | ||
1089 | static int test_comp(struct crypto_comp *tfm, struct comp_testvec *ctemplate, | 1176 | static int test_comp(struct crypto_comp *tfm, struct comp_testvec *ctemplate, |
@@ -1654,16 +1741,10 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
1654 | .alg = "__cbc-twofish-avx", | 1741 | .alg = "__cbc-twofish-avx", |
1655 | .test = alg_test_null, | 1742 | .test = alg_test_null, |
1656 | }, { | 1743 | }, { |
1657 | .alg = "__cbc-twofish-avx2", | ||
1658 | .test = alg_test_null, | ||
1659 | }, { | ||
1660 | .alg = "__driver-cbc-aes-aesni", | 1744 | .alg = "__driver-cbc-aes-aesni", |
1661 | .test = alg_test_null, | 1745 | .test = alg_test_null, |
1662 | .fips_allowed = 1, | 1746 | .fips_allowed = 1, |
1663 | }, { | 1747 | }, { |
1664 | .alg = "__driver-cbc-blowfish-avx2", | ||
1665 | .test = alg_test_null, | ||
1666 | }, { | ||
1667 | .alg = "__driver-cbc-camellia-aesni", | 1748 | .alg = "__driver-cbc-camellia-aesni", |
1668 | .test = alg_test_null, | 1749 | .test = alg_test_null, |
1669 | }, { | 1750 | }, { |
@@ -1688,16 +1769,10 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
1688 | .alg = "__driver-cbc-twofish-avx", | 1769 | .alg = "__driver-cbc-twofish-avx", |
1689 | .test = alg_test_null, | 1770 | .test = alg_test_null, |
1690 | }, { | 1771 | }, { |
1691 | .alg = "__driver-cbc-twofish-avx2", | ||
1692 | .test = alg_test_null, | ||
1693 | }, { | ||
1694 | .alg = "__driver-ecb-aes-aesni", | 1772 | .alg = "__driver-ecb-aes-aesni", |
1695 | .test = alg_test_null, | 1773 | .test = alg_test_null, |
1696 | .fips_allowed = 1, | 1774 | .fips_allowed = 1, |
1697 | }, { | 1775 | }, { |
1698 | .alg = "__driver-ecb-blowfish-avx2", | ||
1699 | .test = alg_test_null, | ||
1700 | }, { | ||
1701 | .alg = "__driver-ecb-camellia-aesni", | 1776 | .alg = "__driver-ecb-camellia-aesni", |
1702 | .test = alg_test_null, | 1777 | .test = alg_test_null, |
1703 | }, { | 1778 | }, { |
@@ -1722,9 +1797,6 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
1722 | .alg = "__driver-ecb-twofish-avx", | 1797 | .alg = "__driver-ecb-twofish-avx", |
1723 | .test = alg_test_null, | 1798 | .test = alg_test_null, |
1724 | }, { | 1799 | }, { |
1725 | .alg = "__driver-ecb-twofish-avx2", | ||
1726 | .test = alg_test_null, | ||
1727 | }, { | ||
1728 | .alg = "__ghash-pclmulqdqni", | 1800 | .alg = "__ghash-pclmulqdqni", |
1729 | .test = alg_test_null, | 1801 | .test = alg_test_null, |
1730 | .fips_allowed = 1, | 1802 | .fips_allowed = 1, |
@@ -1974,12 +2046,19 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
1974 | } | 2046 | } |
1975 | } | 2047 | } |
1976 | }, { | 2048 | }, { |
1977 | .alg = "cryptd(__driver-cbc-aes-aesni)", | 2049 | .alg = "crct10dif", |
1978 | .test = alg_test_null, | 2050 | .test = alg_test_hash, |
1979 | .fips_allowed = 1, | 2051 | .fips_allowed = 1, |
2052 | .suite = { | ||
2053 | .hash = { | ||
2054 | .vecs = crct10dif_tv_template, | ||
2055 | .count = CRCT10DIF_TEST_VECTORS | ||
2056 | } | ||
2057 | } | ||
1980 | }, { | 2058 | }, { |
1981 | .alg = "cryptd(__driver-cbc-blowfish-avx2)", | 2059 | .alg = "cryptd(__driver-cbc-aes-aesni)", |
1982 | .test = alg_test_null, | 2060 | .test = alg_test_null, |
2061 | .fips_allowed = 1, | ||
1983 | }, { | 2062 | }, { |
1984 | .alg = "cryptd(__driver-cbc-camellia-aesni)", | 2063 | .alg = "cryptd(__driver-cbc-camellia-aesni)", |
1985 | .test = alg_test_null, | 2064 | .test = alg_test_null, |
@@ -1994,9 +2073,6 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
1994 | .test = alg_test_null, | 2073 | .test = alg_test_null, |
1995 | .fips_allowed = 1, | 2074 | .fips_allowed = 1, |
1996 | }, { | 2075 | }, { |
1997 | .alg = "cryptd(__driver-ecb-blowfish-avx2)", | ||
1998 | .test = alg_test_null, | ||
1999 | }, { | ||
2000 | .alg = "cryptd(__driver-ecb-camellia-aesni)", | 2076 | .alg = "cryptd(__driver-ecb-camellia-aesni)", |
2001 | .test = alg_test_null, | 2077 | .test = alg_test_null, |
2002 | }, { | 2078 | }, { |
@@ -2021,9 +2097,6 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
2021 | .alg = "cryptd(__driver-ecb-twofish-avx)", | 2097 | .alg = "cryptd(__driver-ecb-twofish-avx)", |
2022 | .test = alg_test_null, | 2098 | .test = alg_test_null, |
2023 | }, { | 2099 | }, { |
2024 | .alg = "cryptd(__driver-ecb-twofish-avx2)", | ||
2025 | .test = alg_test_null, | ||
2026 | }, { | ||
2027 | .alg = "cryptd(__driver-gcm-aes-aesni)", | 2100 | .alg = "cryptd(__driver-gcm-aes-aesni)", |
2028 | .test = alg_test_null, | 2101 | .test = alg_test_null, |
2029 | .fips_allowed = 1, | 2102 | .fips_allowed = 1, |
@@ -3068,6 +3141,35 @@ static const struct alg_test_desc alg_test_descs[] = { | |||
3068 | } | 3141 | } |
3069 | }; | 3142 | }; |
3070 | 3143 | ||
3144 | static bool alg_test_descs_checked; | ||
3145 | |||
3146 | static void alg_test_descs_check_order(void) | ||
3147 | { | ||
3148 | int i; | ||
3149 | |||
3150 | /* only check once */ | ||
3151 | if (alg_test_descs_checked) | ||
3152 | return; | ||
3153 | |||
3154 | alg_test_descs_checked = true; | ||
3155 | |||
3156 | for (i = 1; i < ARRAY_SIZE(alg_test_descs); i++) { | ||
3157 | int diff = strcmp(alg_test_descs[i - 1].alg, | ||
3158 | alg_test_descs[i].alg); | ||
3159 | |||
3160 | if (WARN_ON(diff > 0)) { | ||
3161 | pr_warn("testmgr: alg_test_descs entries in wrong order: '%s' before '%s'\n", | ||
3162 | alg_test_descs[i - 1].alg, | ||
3163 | alg_test_descs[i].alg); | ||
3164 | } | ||
3165 | |||
3166 | if (WARN_ON(diff == 0)) { | ||
3167 | pr_warn("testmgr: duplicate alg_test_descs entry: '%s'\n", | ||
3168 | alg_test_descs[i].alg); | ||
3169 | } | ||
3170 | } | ||
3171 | } | ||
3172 | |||
3071 | static int alg_find_test(const char *alg) | 3173 | static int alg_find_test(const char *alg) |
3072 | { | 3174 | { |
3073 | int start = 0; | 3175 | int start = 0; |
@@ -3099,6 +3201,8 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) | |||
3099 | int j; | 3201 | int j; |
3100 | int rc; | 3202 | int rc; |
3101 | 3203 | ||
3204 | alg_test_descs_check_order(); | ||
3205 | |||
3102 | if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) { | 3206 | if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) { |
3103 | char nalg[CRYPTO_MAX_ALG_NAME]; | 3207 | char nalg[CRYPTO_MAX_ALG_NAME]; |
3104 | 3208 | ||
diff --git a/crypto/testmgr.h b/crypto/testmgr.h index 1e701bc075b9..7d44aa3d6b44 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h | |||
@@ -450,6 +450,39 @@ static struct hash_testvec rmd320_tv_template[] = { | |||
450 | } | 450 | } |
451 | }; | 451 | }; |
452 | 452 | ||
453 | #define CRCT10DIF_TEST_VECTORS 3 | ||
454 | static struct hash_testvec crct10dif_tv_template[] = { | ||
455 | { | ||
456 | .plaintext = "abc", | ||
457 | .psize = 3, | ||
458 | #ifdef __LITTLE_ENDIAN | ||
459 | .digest = "\x3b\x44", | ||
460 | #else | ||
461 | .digest = "\x44\x3b", | ||
462 | #endif | ||
463 | }, { | ||
464 | .plaintext = "1234567890123456789012345678901234567890" | ||
465 | "123456789012345678901234567890123456789", | ||
466 | .psize = 79, | ||
467 | #ifdef __LITTLE_ENDIAN | ||
468 | .digest = "\x70\x4b", | ||
469 | #else | ||
470 | .digest = "\x4b\x70", | ||
471 | #endif | ||
472 | }, { | ||
473 | .plaintext = | ||
474 | "abcddddddddddddddddddddddddddddddddddddddddddddddddddddd", | ||
475 | .psize = 56, | ||
476 | #ifdef __LITTLE_ENDIAN | ||
477 | .digest = "\xe3\x9c", | ||
478 | #else | ||
479 | .digest = "\x9c\xe3", | ||
480 | #endif | ||
481 | .np = 2, | ||
482 | .tap = { 28, 28 } | ||
483 | } | ||
484 | }; | ||
485 | |||
453 | /* | 486 | /* |
454 | * SHA1 test vectors from from FIPS PUB 180-1 | 487 | * SHA1 test vectors from from FIPS PUB 180-1 |
455 | * Long vector from CAVS 5.0 | 488 | * Long vector from CAVS 5.0 |
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 7c73d4aca36b..bf9fc6b79328 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c | |||
@@ -108,8 +108,6 @@ static int atmel_trng_remove(struct platform_device *pdev) | |||
108 | clk_disable(trng->clk); | 108 | clk_disable(trng->clk); |
109 | clk_put(trng->clk); | 109 | clk_put(trng->clk); |
110 | 110 | ||
111 | platform_set_drvdata(pdev, NULL); | ||
112 | |||
113 | return 0; | 111 | return 0; |
114 | } | 112 | } |
115 | 113 | ||
diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index f343b7d0dfa1..36581ea562cb 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c | |||
@@ -137,7 +137,6 @@ static int bcm63xx_rng_probe(struct platform_device *pdev) | |||
137 | out_clk_disable: | 137 | out_clk_disable: |
138 | clk_disable(clk); | 138 | clk_disable(clk); |
139 | out_free_rng: | 139 | out_free_rng: |
140 | platform_set_drvdata(pdev, NULL); | ||
141 | kfree(rng); | 140 | kfree(rng); |
142 | out_free_priv: | 141 | out_free_priv: |
143 | kfree(priv); | 142 | kfree(priv); |
@@ -154,7 +153,6 @@ static int bcm63xx_rng_remove(struct platform_device *pdev) | |||
154 | clk_disable(priv->clk); | 153 | clk_disable(priv->clk); |
155 | kfree(priv); | 154 | kfree(priv); |
156 | kfree(rng); | 155 | kfree(rng); |
157 | platform_set_drvdata(pdev, NULL); | ||
158 | 156 | ||
159 | return 0; | 157 | return 0; |
160 | } | 158 | } |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 20b962e1d832..f9beed54d0c8 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -700,7 +700,7 @@ static int n2rng_probe(struct platform_device *op) | |||
700 | if (err) | 700 | if (err) |
701 | goto out_free_units; | 701 | goto out_free_units; |
702 | 702 | ||
703 | dev_set_drvdata(&op->dev, np); | 703 | platform_set_drvdata(op, np); |
704 | 704 | ||
705 | schedule_delayed_work(&np->work, 0); | 705 | schedule_delayed_work(&np->work, 0); |
706 | 706 | ||
@@ -721,7 +721,7 @@ out: | |||
721 | 721 | ||
722 | static int n2rng_remove(struct platform_device *op) | 722 | static int n2rng_remove(struct platform_device *op) |
723 | { | 723 | { |
724 | struct n2rng *np = dev_get_drvdata(&op->dev); | 724 | struct n2rng *np = platform_get_drvdata(op); |
725 | 725 | ||
726 | np->flags |= N2RNG_FLAG_SHUTDOWN; | 726 | np->flags |= N2RNG_FLAG_SHUTDOWN; |
727 | 727 | ||
@@ -736,8 +736,6 @@ static int n2rng_remove(struct platform_device *op) | |||
736 | 736 | ||
737 | kfree(np); | 737 | kfree(np); |
738 | 738 | ||
739 | dev_set_drvdata(&op->dev, NULL); | ||
740 | |||
741 | return 0; | 739 | return 0; |
742 | } | 740 | } |
743 | 741 | ||
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index 96de0249e595..232b87fb5fc9 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c | |||
@@ -51,7 +51,7 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) | |||
51 | return ret; | 51 | return ret; |
52 | } | 52 | } |
53 | 53 | ||
54 | clk_enable(rng_clk); | 54 | clk_prepare_enable(rng_clk); |
55 | 55 | ||
56 | ret = amba_request_regions(dev, dev->dev.init_name); | 56 | ret = amba_request_regions(dev, dev->dev.init_name); |
57 | if (ret) | 57 | if (ret) |
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c index 1eada566ca70..f2885dbe1849 100644 --- a/drivers/char/hw_random/octeon-rng.c +++ b/drivers/char/hw_random/octeon-rng.c | |||
@@ -96,7 +96,7 @@ static int octeon_rng_probe(struct platform_device *pdev) | |||
96 | 96 | ||
97 | rng->ops = ops; | 97 | rng->ops = ops; |
98 | 98 | ||
99 | dev_set_drvdata(&pdev->dev, &rng->ops); | 99 | platform_set_drvdata(pdev, &rng->ops); |
100 | ret = hwrng_register(&rng->ops); | 100 | ret = hwrng_register(&rng->ops); |
101 | if (ret) | 101 | if (ret) |
102 | return -ENOENT; | 102 | return -ENOENT; |
@@ -108,7 +108,7 @@ static int octeon_rng_probe(struct platform_device *pdev) | |||
108 | 108 | ||
109 | static int __exit octeon_rng_remove(struct platform_device *pdev) | 109 | static int __exit octeon_rng_remove(struct platform_device *pdev) |
110 | { | 110 | { |
111 | struct hwrng *rng = dev_get_drvdata(&pdev->dev); | 111 | struct hwrng *rng = platform_get_drvdata(pdev); |
112 | 112 | ||
113 | hwrng_unregister(rng); | 113 | hwrng_unregister(rng); |
114 | 114 | ||
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index d2903e772270..6843ec87b98b 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c | |||
@@ -116,7 +116,7 @@ static int omap_rng_probe(struct platform_device *pdev) | |||
116 | }; | 116 | }; |
117 | 117 | ||
118 | omap_rng_ops.priv = (unsigned long)priv; | 118 | omap_rng_ops.priv = (unsigned long)priv; |
119 | dev_set_drvdata(&pdev->dev, priv); | 119 | platform_set_drvdata(pdev, priv); |
120 | 120 | ||
121 | priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 121 | priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
122 | priv->base = devm_ioremap_resource(&pdev->dev, priv->mem_res); | 122 | priv->base = devm_ioremap_resource(&pdev->dev, priv->mem_res); |
@@ -124,7 +124,7 @@ static int omap_rng_probe(struct platform_device *pdev) | |||
124 | ret = PTR_ERR(priv->base); | 124 | ret = PTR_ERR(priv->base); |
125 | goto err_ioremap; | 125 | goto err_ioremap; |
126 | } | 126 | } |
127 | dev_set_drvdata(&pdev->dev, priv); | 127 | platform_set_drvdata(pdev, priv); |
128 | 128 | ||
129 | pm_runtime_enable(&pdev->dev); | 129 | pm_runtime_enable(&pdev->dev); |
130 | pm_runtime_get_sync(&pdev->dev); | 130 | pm_runtime_get_sync(&pdev->dev); |
@@ -151,7 +151,7 @@ err_ioremap: | |||
151 | 151 | ||
152 | static int __exit omap_rng_remove(struct platform_device *pdev) | 152 | static int __exit omap_rng_remove(struct platform_device *pdev) |
153 | { | 153 | { |
154 | struct omap_rng_private_data *priv = dev_get_drvdata(&pdev->dev); | 154 | struct omap_rng_private_data *priv = platform_get_drvdata(pdev); |
155 | 155 | ||
156 | hwrng_unregister(&omap_rng_ops); | 156 | hwrng_unregister(&omap_rng_ops); |
157 | 157 | ||
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index 3e75737f5fe1..d2120ba8f3f9 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c | |||
@@ -192,7 +192,6 @@ out_release_io: | |||
192 | out_timer: | 192 | out_timer: |
193 | del_timer_sync(&priv->timer); | 193 | del_timer_sync(&priv->timer); |
194 | out_free: | 194 | out_free: |
195 | platform_set_drvdata(pdev, NULL); | ||
196 | kfree(priv); | 195 | kfree(priv); |
197 | return err; | 196 | return err; |
198 | } | 197 | } |
@@ -209,7 +208,6 @@ static int timeriomem_rng_remove(struct platform_device *pdev) | |||
209 | del_timer_sync(&priv->timer); | 208 | del_timer_sync(&priv->timer); |
210 | iounmap(priv->io_base); | 209 | iounmap(priv->io_base); |
211 | release_mem_region(res->start, resource_size(res)); | 210 | release_mem_region(res->start, resource_size(res)); |
212 | platform_set_drvdata(pdev, NULL); | ||
213 | kfree(priv); | 211 | kfree(priv); |
214 | 212 | ||
215 | return 0; | 213 | return 0; |
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c index d34a24a0d484..00593c847cf0 100644 --- a/drivers/char/hw_random/tx4939-rng.c +++ b/drivers/char/hw_random/tx4939-rng.c | |||
@@ -154,7 +154,6 @@ static int __exit tx4939_rng_remove(struct platform_device *dev) | |||
154 | struct tx4939_rng *rngdev = platform_get_drvdata(dev); | 154 | struct tx4939_rng *rngdev = platform_get_drvdata(dev); |
155 | 155 | ||
156 | hwrng_unregister(&rngdev->rng); | 156 | hwrng_unregister(&rngdev->rng); |
157 | platform_set_drvdata(dev, NULL); | ||
158 | return 0; | 157 | return 0; |
159 | } | 158 | } |
160 | 159 | ||
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 5871933c4e51..81465c21f873 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -87,3 +87,8 @@ config CLKSRC_SAMSUNG_PWM | |||
87 | Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver | 87 | Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver |
88 | for all devicetree enabled platforms. This driver will be | 88 | for all devicetree enabled platforms. This driver will be |
89 | needed only on systems that do not have the Exynos MCT available. | 89 | needed only on systems that do not have the Exynos MCT available. |
90 | |||
91 | config VF_PIT_TIMER | ||
92 | bool | ||
93 | help | ||
94 | Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. | ||
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 8d979c72aa94..9ba8b4d867e3 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -22,10 +22,13 @@ obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o | |||
22 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 22 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
23 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 23 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o |
24 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o | 24 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o |
25 | obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o | ||
25 | obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o | 26 | obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o |
26 | obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o | 27 | obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o |
27 | obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o | 28 | obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o |
28 | obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o | 29 | obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o |
30 | obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o | ||
29 | 31 | ||
30 | obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o | 32 | obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o |
31 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o | 33 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o |
34 | obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o | ||
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 766611d29945..07ea7ce900dc 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c | |||
@@ -28,8 +28,8 @@ | |||
28 | #include <linux/of_platform.h> | 28 | #include <linux/of_platform.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | #include <linux/sched_clock.h> | ||
31 | 32 | ||
32 | #include <asm/sched_clock.h> | ||
33 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
34 | 34 | ||
35 | #define REG_CONTROL 0x00 | 35 | #define REG_CONTROL 0x00 |
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c index 77398f8c19a0..a9fd4ad25674 100644 --- a/drivers/clocksource/clksrc-dbx500-prcmu.c +++ b/drivers/clocksource/clksrc-dbx500-prcmu.c | |||
@@ -14,8 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | #include <linux/clockchips.h> | 15 | #include <linux/clockchips.h> |
16 | #include <linux/clksrc-dbx500-prcmu.h> | 16 | #include <linux/clksrc-dbx500-prcmu.h> |
17 | 17 | #include <linux/sched_clock.h> | |
18 | #include <asm/sched_clock.h> | ||
19 | 18 | ||
20 | #define RATE_32K 32768 | 19 | #define RATE_32K 32768 |
21 | 20 | ||
diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c new file mode 100644 index 000000000000..1f55f9620338 --- /dev/null +++ b/drivers/clocksource/dummy_timer.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * linux/drivers/clocksource/dummy_timer.c | ||
3 | * | ||
4 | * Copyright (C) 2013 ARM Ltd. | ||
5 | * All Rights Reserved | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/clockchips.h> | ||
12 | #include <linux/cpu.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/percpu.h> | ||
15 | #include <linux/cpumask.h> | ||
16 | |||
17 | static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt); | ||
18 | |||
19 | static void dummy_timer_set_mode(enum clock_event_mode mode, | ||
20 | struct clock_event_device *evt) | ||
21 | { | ||
22 | /* | ||
23 | * Core clockevents code will call this when exchanging timer devices. | ||
24 | * We don't need to do anything here. | ||
25 | */ | ||
26 | } | ||
27 | |||
28 | static void __cpuinit dummy_timer_setup(void) | ||
29 | { | ||
30 | int cpu = smp_processor_id(); | ||
31 | struct clock_event_device *evt = __this_cpu_ptr(&dummy_timer_evt); | ||
32 | |||
33 | evt->name = "dummy_timer"; | ||
34 | evt->features = CLOCK_EVT_FEAT_PERIODIC | | ||
35 | CLOCK_EVT_FEAT_ONESHOT | | ||
36 | CLOCK_EVT_FEAT_DUMMY; | ||
37 | evt->rating = 100; | ||
38 | evt->set_mode = dummy_timer_set_mode; | ||
39 | evt->cpumask = cpumask_of(cpu); | ||
40 | |||
41 | clockevents_register_device(evt); | ||
42 | } | ||
43 | |||
44 | static int __cpuinit dummy_timer_cpu_notify(struct notifier_block *self, | ||
45 | unsigned long action, void *hcpu) | ||
46 | { | ||
47 | if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING) | ||
48 | dummy_timer_setup(); | ||
49 | |||
50 | return NOTIFY_OK; | ||
51 | } | ||
52 | |||
53 | static struct notifier_block dummy_timer_cpu_nb __cpuinitdata = { | ||
54 | .notifier_call = dummy_timer_cpu_notify, | ||
55 | }; | ||
56 | |||
57 | static int __init dummy_timer_register(void) | ||
58 | { | ||
59 | int err = register_cpu_notifier(&dummy_timer_cpu_nb); | ||
60 | if (err) | ||
61 | return err; | ||
62 | |||
63 | /* We won't get a call on the boot CPU, so register immediately */ | ||
64 | if (num_possible_cpus() > 1) | ||
65 | dummy_timer_setup(); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | early_initcall(dummy_timer_register); | ||
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index 8c2a35f26d9b..e54ca1062d8e 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c | |||
@@ -387,15 +387,3 @@ cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs) | |||
387 | { | 387 | { |
388 | return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); | 388 | return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); |
389 | } | 389 | } |
390 | |||
391 | /** | ||
392 | * dw_apb_clocksource_unregister() - unregister and free a clocksource. | ||
393 | * | ||
394 | * @dw_cs: The clocksource to unregister/free. | ||
395 | */ | ||
396 | void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs) | ||
397 | { | ||
398 | clocksource_unregister(&dw_cs->cs); | ||
399 | |||
400 | kfree(dw_cs); | ||
401 | } | ||
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index cef554432a33..4cbae4f762b1 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c | |||
@@ -21,9 +21,7 @@ | |||
21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 22 | #include <linux/of_irq.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | 24 | #include <linux/sched_clock.h> | |
25 | #include <asm/mach/time.h> | ||
26 | #include <asm/sched_clock.h> | ||
27 | 25 | ||
28 | static void timer_get_base_and_rate(struct device_node *np, | 26 | static void timer_get_base_and_rate(struct device_node *np, |
29 | void __iomem **base, u32 *rate) | 27 | void __iomem **base, u32 *rate) |
@@ -68,7 +66,7 @@ static void add_clockevent(struct device_node *event_timer) | |||
68 | u32 irq, rate; | 66 | u32 irq, rate; |
69 | 67 | ||
70 | irq = irq_of_parse_and_map(event_timer, 0); | 68 | irq = irq_of_parse_and_map(event_timer, 0); |
71 | if (irq == NO_IRQ) | 69 | if (irq == 0) |
72 | panic("No IRQ for clock event timer"); | 70 | panic("No IRQ for clock event timer"); |
73 | 71 | ||
74 | timer_get_base_and_rate(event_timer, &iobase, &rate); | 72 | timer_get_base_and_rate(event_timer, &iobase, &rate); |
diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index ade7513a11d1..6722f0e2fe40 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c | |||
@@ -184,6 +184,8 @@ int __init metag_generic_timer_init(void) | |||
184 | #ifdef CONFIG_METAG_META21 | 184 | #ifdef CONFIG_METAG_META21 |
185 | hwtimer_freq = get_coreclock() / (metag_in32(EXPAND_TIMER_DIV) + 1); | 185 | hwtimer_freq = get_coreclock() / (metag_in32(EXPAND_TIMER_DIV) + 1); |
186 | #endif | 186 | #endif |
187 | pr_info("Timer frequency: %u Hz\n", hwtimer_freq); | ||
188 | |||
187 | clocksource_register_hz(&clocksource_metag, hwtimer_freq); | 189 | clocksource_register_hz(&clocksource_metag, hwtimer_freq); |
188 | 190 | ||
189 | setup_irq(tbisig_map(TBID_SIGNUM_TRT), &metag_timer_irq); | 191 | setup_irq(tbisig_map(TBID_SIGNUM_TRT), &metag_timer_irq); |
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index 02af4204af86..0f5e65f74dc3 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c | |||
@@ -29,9 +29,9 @@ | |||
29 | #include <linux/of_address.h> | 29 | #include <linux/of_address.h> |
30 | #include <linux/of_irq.h> | 30 | #include <linux/of_irq.h> |
31 | #include <linux/stmp_device.h> | 31 | #include <linux/stmp_device.h> |
32 | #include <linux/sched_clock.h> | ||
32 | 33 | ||
33 | #include <asm/mach/time.h> | 34 | #include <asm/mach/time.h> |
34 | #include <asm/sched_clock.h> | ||
35 | 35 | ||
36 | /* | 36 | /* |
37 | * There are 2 versions of the timrot on Freescale MXS-based SoCs. | 37 | * There are 2 versions of the timrot on Freescale MXS-based SoCs. |
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index b9415b622f55..7d2c2c56f73c 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c | |||
@@ -21,8 +21,8 @@ | |||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/platform_data/clocksource-nomadik-mtu.h> | 23 | #include <linux/platform_data/clocksource-nomadik-mtu.h> |
24 | #include <linux/sched_clock.h> | ||
24 | #include <asm/mach/time.h> | 25 | #include <asm/mach/time.h> |
25 | #include <asm/sched_clock.h> | ||
26 | 26 | ||
27 | /* | 27 | /* |
28 | * The MTU device hosts four different counters, with 4 set of | 28 | * The MTU device hosts four different counters, with 4 set of |
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 0234c8d2c8f2..584b5472eea3 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c | |||
@@ -21,10 +21,10 @@ | |||
21 | #include <linux/of_irq.h> | 21 | #include <linux/of_irq.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/sched_clock.h> | ||
24 | 25 | ||
25 | #include <clocksource/samsung_pwm.h> | 26 | #include <clocksource/samsung_pwm.h> |
26 | 27 | ||
27 | #include <asm/sched_clock.h> | ||
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Clocksource driver | 30 | * Clocksource driver |
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index ae877b021b54..93961703b887 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/of_address.h> | 27 | #include <linux/of_address.h> |
28 | #include <linux/of_irq.h> | 28 | #include <linux/of_irq.h> |
29 | #include <linux/sched_clock.h> | ||
29 | 30 | ||
30 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
31 | #include <asm/smp_twd.h> | 32 | #include <asm/smp_twd.h> |
32 | #include <asm/sched_clock.h> | ||
33 | 33 | ||
34 | #define RTC_SECONDS 0x08 | 34 | #define RTC_SECONDS 0x08 |
35 | #define RTC_SHADOW_SECONDS 0x0c | 35 | #define RTC_SHADOW_SECONDS 0x0c |
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 47a673070d70..efdca3263afe 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c | |||
@@ -27,8 +27,8 @@ | |||
27 | #include <linux/of_address.h> | 27 | #include <linux/of_address.h> |
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/sched_clock.h> | ||
30 | 31 | ||
31 | #include <asm/sched_clock.h> | ||
32 | #include <asm/localtimer.h> | 32 | #include <asm/localtimer.h> |
33 | #include <linux/percpu.h> | 33 | #include <linux/percpu.h> |
34 | /* | 34 | /* |
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index 97738dbf3e3b..e5dc9129ca26 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/of_irq.h> | 18 | #include <linux/of_irq.h> |
19 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
20 | #include <asm/sched_clock.h> | 20 | #include <linux/sched_clock.h> |
21 | #include <asm/localtimer.h> | 21 | #include <asm/localtimer.h> |
22 | #include <asm/mach/time.h> | 22 | #include <asm/mach/time.h> |
23 | 23 | ||
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index 760882665d7a..ef3cfb269d8b 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
19 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <asm/sched_clock.h> | 21 | #include <linux/sched_clock.h> |
22 | #include <asm/mach/time.h> | 22 | #include <asm/mach/time.h> |
23 | 23 | ||
24 | #define SIRFSOC_TIMER_COUNTER_LO 0x0000 | 24 | #define SIRFSOC_TIMER_COUNTER_LO 0x0000 |
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c new file mode 100644 index 000000000000..587e0202a70b --- /dev/null +++ b/drivers/clocksource/vf_pit_timer.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * Copyright 2012-2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/clockchips.h> | ||
12 | #include <linux/clk.h> | ||
13 | #include <linux/of_address.h> | ||
14 | #include <linux/of_irq.h> | ||
15 | #include <linux/sched_clock.h> | ||
16 | |||
17 | /* | ||
18 | * Each pit takes 0x10 Bytes register space | ||
19 | */ | ||
20 | #define PITMCR 0x00 | ||
21 | #define PIT0_OFFSET 0x100 | ||
22 | #define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n)) | ||
23 | #define PITLDVAL 0x00 | ||
24 | #define PITCVAL 0x04 | ||
25 | #define PITTCTRL 0x08 | ||
26 | #define PITTFLG 0x0c | ||
27 | |||
28 | #define PITMCR_MDIS (0x1 << 1) | ||
29 | |||
30 | #define PITTCTRL_TEN (0x1 << 0) | ||
31 | #define PITTCTRL_TIE (0x1 << 1) | ||
32 | #define PITCTRL_CHN (0x1 << 2) | ||
33 | |||
34 | #define PITTFLG_TIF 0x1 | ||
35 | |||
36 | static void __iomem *clksrc_base; | ||
37 | static void __iomem *clkevt_base; | ||
38 | static unsigned long cycle_per_jiffy; | ||
39 | |||
40 | static inline void pit_timer_enable(void) | ||
41 | { | ||
42 | __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL); | ||
43 | } | ||
44 | |||
45 | static inline void pit_timer_disable(void) | ||
46 | { | ||
47 | __raw_writel(0, clkevt_base + PITTCTRL); | ||
48 | } | ||
49 | |||
50 | static inline void pit_irq_acknowledge(void) | ||
51 | { | ||
52 | __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); | ||
53 | } | ||
54 | |||
55 | static unsigned int pit_read_sched_clock(void) | ||
56 | { | ||
57 | return __raw_readl(clksrc_base + PITCVAL); | ||
58 | } | ||
59 | |||
60 | static int __init pit_clocksource_init(unsigned long rate) | ||
61 | { | ||
62 | /* set the max load value and start the clock source counter */ | ||
63 | __raw_writel(0, clksrc_base + PITTCTRL); | ||
64 | __raw_writel(~0UL, clksrc_base + PITLDVAL); | ||
65 | __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL); | ||
66 | |||
67 | setup_sched_clock(pit_read_sched_clock, 32, rate); | ||
68 | return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate, | ||
69 | 300, 32, clocksource_mmio_readl_down); | ||
70 | } | ||
71 | |||
72 | static int pit_set_next_event(unsigned long delta, | ||
73 | struct clock_event_device *unused) | ||
74 | { | ||
75 | /* | ||
76 | * set a new value to PITLDVAL register will not restart the timer, | ||
77 | * to abort the current cycle and start a timer period with the new | ||
78 | * value, the timer must be disabled and enabled again. | ||
79 | * and the PITLAVAL should be set to delta minus one according to pit | ||
80 | * hardware requirement. | ||
81 | */ | ||
82 | pit_timer_disable(); | ||
83 | __raw_writel(delta - 1, clkevt_base + PITLDVAL); | ||
84 | pit_timer_enable(); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void pit_set_mode(enum clock_event_mode mode, | ||
90 | struct clock_event_device *evt) | ||
91 | { | ||
92 | switch (mode) { | ||
93 | case CLOCK_EVT_MODE_PERIODIC: | ||
94 | pit_set_next_event(cycle_per_jiffy, evt); | ||
95 | break; | ||
96 | default: | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) | ||
102 | { | ||
103 | struct clock_event_device *evt = dev_id; | ||
104 | |||
105 | pit_irq_acknowledge(); | ||
106 | |||
107 | /* | ||
108 | * pit hardware doesn't support oneshot, it will generate an interrupt | ||
109 | * and reload the counter value from PITLDVAL when PITCVAL reach zero, | ||
110 | * and start the counter again. So software need to disable the timer | ||
111 | * to stop the counter loop in ONESHOT mode. | ||
112 | */ | ||
113 | if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT)) | ||
114 | pit_timer_disable(); | ||
115 | |||
116 | evt->event_handler(evt); | ||
117 | |||
118 | return IRQ_HANDLED; | ||
119 | } | ||
120 | |||
121 | static struct clock_event_device clockevent_pit = { | ||
122 | .name = "VF pit timer", | ||
123 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
124 | .set_mode = pit_set_mode, | ||
125 | .set_next_event = pit_set_next_event, | ||
126 | .rating = 300, | ||
127 | }; | ||
128 | |||
129 | static struct irqaction pit_timer_irq = { | ||
130 | .name = "VF pit timer", | ||
131 | .flags = IRQF_TIMER | IRQF_IRQPOLL, | ||
132 | .handler = pit_timer_interrupt, | ||
133 | .dev_id = &clockevent_pit, | ||
134 | }; | ||
135 | |||
136 | static int __init pit_clockevent_init(unsigned long rate, int irq) | ||
137 | { | ||
138 | __raw_writel(0, clkevt_base + PITTCTRL); | ||
139 | __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); | ||
140 | |||
141 | BUG_ON(setup_irq(irq, &pit_timer_irq)); | ||
142 | |||
143 | clockevent_pit.cpumask = cpumask_of(0); | ||
144 | clockevent_pit.irq = irq; | ||
145 | /* | ||
146 | * The value for the LDVAL register trigger is calculated as: | ||
147 | * LDVAL trigger = (period / clock period) - 1 | ||
148 | * The pit is a 32-bit down count timer, when the conter value | ||
149 | * reaches 0, it will generate an interrupt, thus the minimal | ||
150 | * LDVAL trigger value is 1. And then the min_delta is | ||
151 | * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit. | ||
152 | */ | ||
153 | clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static void __init pit_timer_init(struct device_node *np) | ||
159 | { | ||
160 | struct clk *pit_clk; | ||
161 | void __iomem *timer_base; | ||
162 | unsigned long clk_rate; | ||
163 | int irq; | ||
164 | |||
165 | timer_base = of_iomap(np, 0); | ||
166 | BUG_ON(!timer_base); | ||
167 | |||
168 | /* | ||
169 | * PIT0 and PIT1 can be chained to build a 64-bit timer, | ||
170 | * so choose PIT2 as clocksource, PIT3 as clockevent device, | ||
171 | * and leave PIT0 and PIT1 unused for anyone else who needs them. | ||
172 | */ | ||
173 | clksrc_base = timer_base + PITn_OFFSET(2); | ||
174 | clkevt_base = timer_base + PITn_OFFSET(3); | ||
175 | |||
176 | irq = irq_of_parse_and_map(np, 0); | ||
177 | BUG_ON(irq <= 0); | ||
178 | |||
179 | pit_clk = of_clk_get(np, 0); | ||
180 | BUG_ON(IS_ERR(pit_clk)); | ||
181 | |||
182 | BUG_ON(clk_prepare_enable(pit_clk)); | ||
183 | |||
184 | clk_rate = clk_get_rate(pit_clk); | ||
185 | cycle_per_jiffy = clk_rate / (HZ); | ||
186 | |||
187 | /* enable the pit module */ | ||
188 | __raw_writel(~PITMCR_MDIS, timer_base + PITMCR); | ||
189 | |||
190 | BUG_ON(pit_clocksource_init(clk_rate)); | ||
191 | |||
192 | pit_clockevent_init(clk_rate, irq); | ||
193 | } | ||
194 | CLOCKSOURCE_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); | ||
diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c new file mode 100644 index 000000000000..ca81809d159d --- /dev/null +++ b/drivers/clocksource/zevio-timer.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * linux/drivers/clocksource/zevio-timer.c | ||
3 | * | ||
4 | * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/io.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/of_irq.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/clockchips.h> | ||
19 | #include <linux/cpumask.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #define IO_CURRENT_VAL 0x00 | ||
24 | #define IO_DIVIDER 0x04 | ||
25 | #define IO_CONTROL 0x08 | ||
26 | |||
27 | #define IO_TIMER1 0x00 | ||
28 | #define IO_TIMER2 0x0C | ||
29 | |||
30 | #define IO_MATCH_BEGIN 0x18 | ||
31 | #define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2)) | ||
32 | |||
33 | #define IO_INTR_STS 0x00 | ||
34 | #define IO_INTR_ACK 0x00 | ||
35 | #define IO_INTR_MSK 0x04 | ||
36 | |||
37 | #define CNTL_STOP_TIMER (1 << 4) | ||
38 | #define CNTL_RUN_TIMER (0 << 4) | ||
39 | |||
40 | #define CNTL_INC (1 << 3) | ||
41 | #define CNTL_DEC (0 << 3) | ||
42 | |||
43 | #define CNTL_TOZERO 0 | ||
44 | #define CNTL_MATCH(x) ((x) + 1) | ||
45 | #define CNTL_FOREVER 7 | ||
46 | |||
47 | /* There are 6 match registers but we only use one. */ | ||
48 | #define TIMER_MATCH 0 | ||
49 | |||
50 | #define TIMER_INTR_MSK (1 << (TIMER_MATCH)) | ||
51 | #define TIMER_INTR_ALL 0x3F | ||
52 | |||
53 | struct zevio_timer { | ||
54 | void __iomem *base; | ||
55 | void __iomem *timer1, *timer2; | ||
56 | void __iomem *interrupt_regs; | ||
57 | |||
58 | struct clk *clk; | ||
59 | struct clock_event_device clkevt; | ||
60 | struct irqaction clkevt_irq; | ||
61 | |||
62 | char clocksource_name[64]; | ||
63 | char clockevent_name[64]; | ||
64 | }; | ||
65 | |||
66 | static int zevio_timer_set_event(unsigned long delta, | ||
67 | struct clock_event_device *dev) | ||
68 | { | ||
69 | struct zevio_timer *timer = container_of(dev, struct zevio_timer, | ||
70 | clkevt); | ||
71 | |||
72 | writel(delta, timer->timer1 + IO_CURRENT_VAL); | ||
73 | writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH), | ||
74 | timer->timer1 + IO_CONTROL); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static void zevio_timer_set_mode(enum clock_event_mode mode, | ||
80 | struct clock_event_device *dev) | ||
81 | { | ||
82 | struct zevio_timer *timer = container_of(dev, struct zevio_timer, | ||
83 | clkevt); | ||
84 | |||
85 | switch (mode) { | ||
86 | case CLOCK_EVT_MODE_RESUME: | ||
87 | case CLOCK_EVT_MODE_ONESHOT: | ||
88 | /* Enable timer interrupts */ | ||
89 | writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); | ||
90 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); | ||
91 | break; | ||
92 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
93 | case CLOCK_EVT_MODE_UNUSED: | ||
94 | /* Disable timer interrupts */ | ||
95 | writel(0, timer->interrupt_regs + IO_INTR_MSK); | ||
96 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); | ||
97 | /* Stop timer */ | ||
98 | writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); | ||
99 | break; | ||
100 | case CLOCK_EVT_MODE_PERIODIC: | ||
101 | default: | ||
102 | /* Unsupported */ | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) | ||
108 | { | ||
109 | struct zevio_timer *timer = dev_id; | ||
110 | u32 intr; | ||
111 | |||
112 | intr = readl(timer->interrupt_regs + IO_INTR_ACK); | ||
113 | if (!(intr & TIMER_INTR_MSK)) | ||
114 | return IRQ_NONE; | ||
115 | |||
116 | writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK); | ||
117 | writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); | ||
118 | |||
119 | if (timer->clkevt.event_handler) | ||
120 | timer->clkevt.event_handler(&timer->clkevt); | ||
121 | |||
122 | return IRQ_HANDLED; | ||
123 | } | ||
124 | |||
125 | static int __init zevio_timer_add(struct device_node *node) | ||
126 | { | ||
127 | struct zevio_timer *timer; | ||
128 | struct resource res; | ||
129 | int irqnr, ret; | ||
130 | |||
131 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); | ||
132 | if (!timer) | ||
133 | return -ENOMEM; | ||
134 | |||
135 | timer->base = of_iomap(node, 0); | ||
136 | if (!timer->base) { | ||
137 | ret = -EINVAL; | ||
138 | goto error_free; | ||
139 | } | ||
140 | timer->timer1 = timer->base + IO_TIMER1; | ||
141 | timer->timer2 = timer->base + IO_TIMER2; | ||
142 | |||
143 | timer->clk = of_clk_get(node, 0); | ||
144 | if (IS_ERR(timer->clk)) { | ||
145 | ret = PTR_ERR(timer->clk); | ||
146 | pr_err("Timer clock not found! (error %d)\n", ret); | ||
147 | goto error_unmap; | ||
148 | } | ||
149 | |||
150 | timer->interrupt_regs = of_iomap(node, 1); | ||
151 | irqnr = irq_of_parse_and_map(node, 0); | ||
152 | |||
153 | of_address_to_resource(node, 0, &res); | ||
154 | scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name), | ||
155 | "%llx.%s_clocksource", | ||
156 | (unsigned long long)res.start, node->name); | ||
157 | |||
158 | scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name), | ||
159 | "%llx.%s_clockevent", | ||
160 | (unsigned long long)res.start, node->name); | ||
161 | |||
162 | if (timer->interrupt_regs && irqnr) { | ||
163 | timer->clkevt.name = timer->clockevent_name; | ||
164 | timer->clkevt.set_next_event = zevio_timer_set_event; | ||
165 | timer->clkevt.set_mode = zevio_timer_set_mode; | ||
166 | timer->clkevt.rating = 200; | ||
167 | timer->clkevt.cpumask = cpu_all_mask; | ||
168 | timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; | ||
169 | timer->clkevt.irq = irqnr; | ||
170 | |||
171 | writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); | ||
172 | writel(0, timer->timer1 + IO_DIVIDER); | ||
173 | |||
174 | /* Start with timer interrupts disabled */ | ||
175 | writel(0, timer->interrupt_regs + IO_INTR_MSK); | ||
176 | writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); | ||
177 | |||
178 | /* Interrupt to occur when timer value matches 0 */ | ||
179 | writel(0, timer->base + IO_MATCH(TIMER_MATCH)); | ||
180 | |||
181 | timer->clkevt_irq.name = timer->clockevent_name; | ||
182 | timer->clkevt_irq.handler = zevio_timer_interrupt; | ||
183 | timer->clkevt_irq.dev_id = timer; | ||
184 | timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; | ||
185 | |||
186 | setup_irq(irqnr, &timer->clkevt_irq); | ||
187 | |||
188 | clockevents_config_and_register(&timer->clkevt, | ||
189 | clk_get_rate(timer->clk), 0x0001, 0xffff); | ||
190 | pr_info("Added %s as clockevent\n", timer->clockevent_name); | ||
191 | } | ||
192 | |||
193 | writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL); | ||
194 | writel(0, timer->timer2 + IO_CURRENT_VAL); | ||
195 | writel(0, timer->timer2 + IO_DIVIDER); | ||
196 | writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC, | ||
197 | timer->timer2 + IO_CONTROL); | ||
198 | |||
199 | clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL, | ||
200 | timer->clocksource_name, | ||
201 | clk_get_rate(timer->clk), | ||
202 | 200, 16, | ||
203 | clocksource_mmio_readw_up); | ||
204 | |||
205 | pr_info("Added %s as clocksource\n", timer->clocksource_name); | ||
206 | |||
207 | return 0; | ||
208 | error_unmap: | ||
209 | iounmap(timer->base); | ||
210 | error_free: | ||
211 | kfree(timer); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_add); | ||
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index dffb85525368..8ff7c230d82e 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -278,7 +278,7 @@ config CRYPTO_DEV_PICOXCELL | |||
278 | 278 | ||
279 | config CRYPTO_DEV_SAHARA | 279 | config CRYPTO_DEV_SAHARA |
280 | tristate "Support for SAHARA crypto accelerator" | 280 | tristate "Support for SAHARA crypto accelerator" |
281 | depends on ARCH_MXC && EXPERIMENTAL && OF | 281 | depends on ARCH_MXC && OF |
282 | select CRYPTO_BLKCIPHER | 282 | select CRYPTO_BLKCIPHER |
283 | select CRYPTO_AES | 283 | select CRYPTO_AES |
284 | select CRYPTO_ECB | 284 | select CRYPTO_ECB |
@@ -286,6 +286,16 @@ config CRYPTO_DEV_SAHARA | |||
286 | This option enables support for the SAHARA HW crypto accelerator | 286 | This option enables support for the SAHARA HW crypto accelerator |
287 | found in some Freescale i.MX chips. | 287 | found in some Freescale i.MX chips. |
288 | 288 | ||
289 | config CRYPTO_DEV_DCP | ||
290 | tristate "Support for the DCP engine" | ||
291 | depends on ARCH_MXS && OF | ||
292 | select CRYPTO_BLKCIPHER | ||
293 | select CRYPTO_AES | ||
294 | select CRYPTO_CBC | ||
295 | help | ||
296 | This options enables support for the hardware crypto-acceleration | ||
297 | capabilities of the DCP co-processor | ||
298 | |||
289 | config CRYPTO_DEV_S5P | 299 | config CRYPTO_DEV_S5P |
290 | tristate "Support for Samsung S5PV210 crypto accelerator" | 300 | tristate "Support for Samsung S5PV210 crypto accelerator" |
291 | depends on ARCH_S5PV210 | 301 | depends on ARCH_S5PV210 |
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 38ce13d3b79b..b4946ddd2550 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o | |||
13 | obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o | 13 | obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o |
14 | obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o | 14 | obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o |
15 | obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o | 15 | obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o |
16 | obj-$(CONFIG_CRYPTO_DEV_DCP) += dcp.o | ||
16 | obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o | 17 | obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o |
17 | obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o | 18 | obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o |
18 | obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ | 19 | obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ |
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 6e94bcd94678..f5d6deced1cb 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c | |||
@@ -202,6 +202,7 @@ static int caam_probe(struct platform_device *pdev) | |||
202 | #ifdef CONFIG_DEBUG_FS | 202 | #ifdef CONFIG_DEBUG_FS |
203 | struct caam_perfmon *perfmon; | 203 | struct caam_perfmon *perfmon; |
204 | #endif | 204 | #endif |
205 | u64 cha_vid; | ||
205 | 206 | ||
206 | ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL); | 207 | ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL); |
207 | if (!ctrlpriv) | 208 | if (!ctrlpriv) |
@@ -293,11 +294,14 @@ static int caam_probe(struct platform_device *pdev) | |||
293 | return -ENOMEM; | 294 | return -ENOMEM; |
294 | } | 295 | } |
295 | 296 | ||
297 | cha_vid = rd_reg64(&topregs->ctrl.perfmon.cha_id); | ||
298 | |||
296 | /* | 299 | /* |
297 | * RNG4 based SECs (v5+) need special initialization prior | 300 | * If SEC has RNG version >= 4 and RNG state handle has not been |
298 | * to executing any descriptors | 301 | * already instantiated ,do RNG instantiation |
299 | */ | 302 | */ |
300 | if (of_device_is_compatible(nprop, "fsl,sec-v5.0")) { | 303 | if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4 && |
304 | !(rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IF0)) { | ||
301 | kick_trng(pdev); | 305 | kick_trng(pdev); |
302 | ret = instantiate_rng(ctrlpriv->jrdev[0]); | 306 | ret = instantiate_rng(ctrlpriv->jrdev[0]); |
303 | if (ret) { | 307 | if (ret) { |
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h index f7f833be8c67..53b296f78b0d 100644 --- a/drivers/crypto/caam/desc.h +++ b/drivers/crypto/caam/desc.h | |||
@@ -231,7 +231,12 @@ struct sec4_sg_entry { | |||
231 | #define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT) | 231 | #define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT) |
232 | #define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT) | 232 | #define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT) |
233 | #define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT) | 233 | #define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT) |
234 | #define LDST_SRCDST_WORD_CLASS_CTX (0x20 << LDST_SRCDST_SHIFT) | ||
234 | #define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT) | 235 | #define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT) |
236 | #define LDST_SRCDST_WORD_DESCBUF_JOB (0x41 << LDST_SRCDST_SHIFT) | ||
237 | #define LDST_SRCDST_WORD_DESCBUF_SHARED (0x42 << LDST_SRCDST_SHIFT) | ||
238 | #define LDST_SRCDST_WORD_DESCBUF_JOB_WE (0x45 << LDST_SRCDST_SHIFT) | ||
239 | #define LDST_SRCDST_WORD_DESCBUF_SHARED_WE (0x46 << LDST_SRCDST_SHIFT) | ||
235 | #define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT) | 240 | #define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT) |
236 | 241 | ||
237 | /* Offset in source/destination */ | 242 | /* Offset in source/destination */ |
@@ -366,6 +371,7 @@ struct sec4_sg_entry { | |||
366 | #define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT) | 371 | #define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT) |
367 | #define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT) | 372 | #define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT) |
368 | #define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT) | 373 | #define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT) |
374 | #define FIFOLD_TYPE_NOINFOFIFO (0x0F << FIFOLD_TYPE_SHIFT) | ||
369 | 375 | ||
370 | #define FIFOLDST_LEN_MASK 0xffff | 376 | #define FIFOLDST_LEN_MASK 0xffff |
371 | #define FIFOLDST_EXT_LEN_MASK 0xffffffff | 377 | #define FIFOLDST_EXT_LEN_MASK 0xffffffff |
@@ -1294,10 +1300,10 @@ struct sec4_sg_entry { | |||
1294 | #define SQOUT_SGF 0x01000000 | 1300 | #define SQOUT_SGF 0x01000000 |
1295 | 1301 | ||
1296 | /* Appends to a previous pointer */ | 1302 | /* Appends to a previous pointer */ |
1297 | #define SQOUT_PRE 0x00800000 | 1303 | #define SQOUT_PRE SQIN_PRE |
1298 | 1304 | ||
1299 | /* Restore sequence with pointer/length */ | 1305 | /* Restore sequence with pointer/length */ |
1300 | #define SQOUT_RTO 0x00200000 | 1306 | #define SQOUT_RTO SQIN_RTO |
1301 | 1307 | ||
1302 | /* Use extended length following pointer */ | 1308 | /* Use extended length following pointer */ |
1303 | #define SQOUT_EXT 0x00400000 | 1309 | #define SQOUT_EXT 0x00400000 |
@@ -1359,6 +1365,7 @@ struct sec4_sg_entry { | |||
1359 | #define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT) | 1365 | #define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT) |
1360 | #define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT) | 1366 | #define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT) |
1361 | #define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT) | 1367 | #define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT) |
1368 | #define MOVE_DEST_INFIFO_NOINFO (0x0a << MOVE_DEST_SHIFT) | ||
1362 | #define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT) | 1369 | #define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT) |
1363 | #define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT) | 1370 | #define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT) |
1364 | #define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT) | 1371 | #define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT) |
@@ -1411,6 +1418,7 @@ struct sec4_sg_entry { | |||
1411 | #define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT) | 1418 | #define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT) |
1412 | #define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT) | 1419 | #define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT) |
1413 | #define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT) | 1420 | #define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT) |
1421 | #define MATH_SRC0_DPOVRD (0x07 << MATH_SRC0_SHIFT) | ||
1414 | #define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT) | 1422 | #define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT) |
1415 | #define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT) | 1423 | #define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT) |
1416 | #define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT) | 1424 | #define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT) |
@@ -1425,6 +1433,7 @@ struct sec4_sg_entry { | |||
1425 | #define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT) | 1433 | #define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT) |
1426 | #define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT) | 1434 | #define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT) |
1427 | #define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT) | 1435 | #define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT) |
1436 | #define MATH_SRC1_DPOVRD (0x07 << MATH_SRC0_SHIFT) | ||
1428 | #define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT) | 1437 | #define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT) |
1429 | #define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT) | 1438 | #define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT) |
1430 | #define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT) | 1439 | #define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT) |
@@ -1600,4 +1609,13 @@ struct sec4_sg_entry { | |||
1600 | #define NFIFOENTRY_PLEN_SHIFT 0 | 1609 | #define NFIFOENTRY_PLEN_SHIFT 0 |
1601 | #define NFIFOENTRY_PLEN_MASK (0xFF << NFIFOENTRY_PLEN_SHIFT) | 1610 | #define NFIFOENTRY_PLEN_MASK (0xFF << NFIFOENTRY_PLEN_SHIFT) |
1602 | 1611 | ||
1612 | /* Append Load Immediate Command */ | ||
1613 | #define FD_CMD_APPEND_LOAD_IMMEDIATE 0x80000000 | ||
1614 | |||
1615 | /* Set SEQ LIODN equal to the Non-SEQ LIODN for the job */ | ||
1616 | #define FD_CMD_SET_SEQ_LIODN_EQUAL_NONSEQ_LIODN 0x40000000 | ||
1617 | |||
1618 | /* Frame Descriptor Command for Replacement Job Descriptor */ | ||
1619 | #define FD_CMD_REPLACE_JOB_DESC 0x20000000 | ||
1620 | |||
1603 | #endif /* DESC_H */ | 1621 | #endif /* DESC_H */ |
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h index c85c1f058401..fe3bfd1b08ca 100644 --- a/drivers/crypto/caam/desc_constr.h +++ b/drivers/crypto/caam/desc_constr.h | |||
@@ -110,6 +110,26 @@ static inline void append_cmd(u32 *desc, u32 command) | |||
110 | (*desc)++; | 110 | (*desc)++; |
111 | } | 111 | } |
112 | 112 | ||
113 | #define append_u32 append_cmd | ||
114 | |||
115 | static inline void append_u64(u32 *desc, u64 data) | ||
116 | { | ||
117 | u32 *offset = desc_end(desc); | ||
118 | |||
119 | *offset = upper_32_bits(data); | ||
120 | *(++offset) = lower_32_bits(data); | ||
121 | |||
122 | (*desc) += 2; | ||
123 | } | ||
124 | |||
125 | /* Write command without affecting header, and return pointer to next word */ | ||
126 | static inline u32 *write_cmd(u32 *desc, u32 command) | ||
127 | { | ||
128 | *desc = command; | ||
129 | |||
130 | return desc + 1; | ||
131 | } | ||
132 | |||
113 | static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len, | 133 | static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len, |
114 | u32 command) | 134 | u32 command) |
115 | { | 135 | { |
@@ -122,7 +142,8 @@ static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr, | |||
122 | unsigned int len, u32 command) | 142 | unsigned int len, u32 command) |
123 | { | 143 | { |
124 | append_cmd(desc, command); | 144 | append_cmd(desc, command); |
125 | append_ptr(desc, ptr); | 145 | if (!(command & (SQIN_RTO | SQIN_PRE))) |
146 | append_ptr(desc, ptr); | ||
126 | append_cmd(desc, len); | 147 | append_cmd(desc, len); |
127 | } | 148 | } |
128 | 149 | ||
@@ -176,17 +197,36 @@ static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \ | |||
176 | } | 197 | } |
177 | APPEND_CMD_PTR(key, KEY) | 198 | APPEND_CMD_PTR(key, KEY) |
178 | APPEND_CMD_PTR(load, LOAD) | 199 | APPEND_CMD_PTR(load, LOAD) |
179 | APPEND_CMD_PTR(store, STORE) | ||
180 | APPEND_CMD_PTR(fifo_load, FIFO_LOAD) | 200 | APPEND_CMD_PTR(fifo_load, FIFO_LOAD) |
181 | APPEND_CMD_PTR(fifo_store, FIFO_STORE) | 201 | APPEND_CMD_PTR(fifo_store, FIFO_STORE) |
182 | 202 | ||
203 | static inline void append_store(u32 *desc, dma_addr_t ptr, unsigned int len, | ||
204 | u32 options) | ||
205 | { | ||
206 | u32 cmd_src; | ||
207 | |||
208 | cmd_src = options & LDST_SRCDST_MASK; | ||
209 | |||
210 | append_cmd(desc, CMD_STORE | options | len); | ||
211 | |||
212 | /* The following options do not require pointer */ | ||
213 | if (!(cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED || | ||
214 | cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB || | ||
215 | cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB_WE || | ||
216 | cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED_WE)) | ||
217 | append_ptr(desc, ptr); | ||
218 | } | ||
219 | |||
183 | #define APPEND_SEQ_PTR_INTLEN(cmd, op) \ | 220 | #define APPEND_SEQ_PTR_INTLEN(cmd, op) \ |
184 | static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \ | 221 | static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \ |
185 | unsigned int len, \ | 222 | unsigned int len, \ |
186 | u32 options) \ | 223 | u32 options) \ |
187 | { \ | 224 | { \ |
188 | PRINT_POS; \ | 225 | PRINT_POS; \ |
189 | append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \ | 226 | if (options & (SQIN_RTO | SQIN_PRE)) \ |
227 | append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \ | ||
228 | else \ | ||
229 | append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \ | ||
190 | } | 230 | } |
191 | APPEND_SEQ_PTR_INTLEN(in, IN) | 231 | APPEND_SEQ_PTR_INTLEN(in, IN) |
192 | APPEND_SEQ_PTR_INTLEN(out, OUT) | 232 | APPEND_SEQ_PTR_INTLEN(out, OUT) |
@@ -259,7 +299,7 @@ APPEND_CMD_RAW_IMM(load, LOAD, u32); | |||
259 | */ | 299 | */ |
260 | #define APPEND_MATH(op, desc, dest, src_0, src_1, len) \ | 300 | #define APPEND_MATH(op, desc, dest, src_0, src_1, len) \ |
261 | append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \ | 301 | append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \ |
262 | MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32) (len & MATH_LEN_MASK)); | 302 | MATH_SRC0_##src_0 | MATH_SRC1_##src_1 | (u32)len); |
263 | 303 | ||
264 | #define append_math_add(desc, dest, src0, src1, len) \ | 304 | #define append_math_add(desc, dest, src0, src1, len) \ |
265 | APPEND_MATH(ADD, desc, dest, src0, src1, len) | 305 | APPEND_MATH(ADD, desc, dest, src0, src1, len) |
@@ -279,6 +319,8 @@ append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \ | |||
279 | APPEND_MATH(LSHIFT, desc, dest, src0, src1, len) | 319 | APPEND_MATH(LSHIFT, desc, dest, src0, src1, len) |
280 | #define append_math_rshift(desc, dest, src0, src1, len) \ | 320 | #define append_math_rshift(desc, dest, src0, src1, len) \ |
281 | APPEND_MATH(RSHIFT, desc, dest, src0, src1, len) | 321 | APPEND_MATH(RSHIFT, desc, dest, src0, src1, len) |
322 | #define append_math_ldshift(desc, dest, src0, src1, len) \ | ||
323 | APPEND_MATH(SHLD, desc, dest, src0, src1, len) | ||
282 | 324 | ||
283 | /* Exactly one source is IMM. Data is passed in as u32 value */ | 325 | /* Exactly one source is IMM. Data is passed in as u32 value */ |
284 | #define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \ | 326 | #define APPEND_MATH_IMM_u32(op, desc, dest, src_0, src_1, data) \ |
@@ -305,3 +347,34 @@ do { \ | |||
305 | APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data) | 347 | APPEND_MATH_IMM_u32(LSHIFT, desc, dest, src0, src1, data) |
306 | #define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \ | 348 | #define append_math_rshift_imm_u32(desc, dest, src0, src1, data) \ |
307 | APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data) | 349 | APPEND_MATH_IMM_u32(RSHIFT, desc, dest, src0, src1, data) |
350 | |||
351 | /* Exactly one source is IMM. Data is passed in as u64 value */ | ||
352 | #define APPEND_MATH_IMM_u64(op, desc, dest, src_0, src_1, data) \ | ||
353 | do { \ | ||
354 | u32 upper = (data >> 16) >> 16; \ | ||
355 | APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ * 2 | \ | ||
356 | (upper ? 0 : MATH_IFB)); \ | ||
357 | if (upper) \ | ||
358 | append_u64(desc, data); \ | ||
359 | else \ | ||
360 | append_u32(desc, data); \ | ||
361 | } while (0) | ||
362 | |||
363 | #define append_math_add_imm_u64(desc, dest, src0, src1, data) \ | ||
364 | APPEND_MATH_IMM_u64(ADD, desc, dest, src0, src1, data) | ||
365 | #define append_math_sub_imm_u64(desc, dest, src0, src1, data) \ | ||
366 | APPEND_MATH_IMM_u64(SUB, desc, dest, src0, src1, data) | ||
367 | #define append_math_add_c_imm_u64(desc, dest, src0, src1, data) \ | ||
368 | APPEND_MATH_IMM_u64(ADDC, desc, dest, src0, src1, data) | ||
369 | #define append_math_sub_b_imm_u64(desc, dest, src0, src1, data) \ | ||
370 | APPEND_MATH_IMM_u64(SUBB, desc, dest, src0, src1, data) | ||
371 | #define append_math_and_imm_u64(desc, dest, src0, src1, data) \ | ||
372 | APPEND_MATH_IMM_u64(AND, desc, dest, src0, src1, data) | ||
373 | #define append_math_or_imm_u64(desc, dest, src0, src1, data) \ | ||
374 | APPEND_MATH_IMM_u64(OR, desc, dest, src0, src1, data) | ||
375 | #define append_math_xor_imm_u64(desc, dest, src0, src1, data) \ | ||
376 | APPEND_MATH_IMM_u64(XOR, desc, dest, src0, src1, data) | ||
377 | #define append_math_lshift_imm_u64(desc, dest, src0, src1, data) \ | ||
378 | APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data) | ||
379 | #define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \ | ||
380 | APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data) | ||
diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h index 62950d22ac13..3a87c0cf879a 100644 --- a/drivers/crypto/caam/pdb.h +++ b/drivers/crypto/caam/pdb.h | |||
@@ -44,6 +44,7 @@ | |||
44 | #define PDBOPTS_ESP_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */ | 44 | #define PDBOPTS_ESP_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */ |
45 | #define PDBOPTS_ESP_INCIPHDR 0x04 /* Prepend IP header to output frame */ | 45 | #define PDBOPTS_ESP_INCIPHDR 0x04 /* Prepend IP header to output frame */ |
46 | #define PDBOPTS_ESP_IPVSN 0x02 /* process IPv6 header */ | 46 | #define PDBOPTS_ESP_IPVSN 0x02 /* process IPv6 header */ |
47 | #define PDBOPTS_ESP_AOFL 0x04 /* adjust out frame len (decap, SEC>=5.3)*/ | ||
47 | #define PDBOPTS_ESP_TUNNEL 0x01 /* tunnel mode next-header byte */ | 48 | #define PDBOPTS_ESP_TUNNEL 0x01 /* tunnel mode next-header byte */ |
48 | #define PDBOPTS_ESP_IPV6 0x02 /* ip header version is V6 */ | 49 | #define PDBOPTS_ESP_IPV6 0x02 /* ip header version is V6 */ |
49 | #define PDBOPTS_ESP_DIFFSERV 0x40 /* copy TOS/TC from inner iphdr */ | 50 | #define PDBOPTS_ESP_DIFFSERV 0x40 /* copy TOS/TC from inner iphdr */ |
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index cd6fedad9935..c09142fc13e3 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h | |||
@@ -117,6 +117,43 @@ struct jr_outentry { | |||
117 | #define CHA_NUM_DECONUM_SHIFT 56 | 117 | #define CHA_NUM_DECONUM_SHIFT 56 |
118 | #define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT) | 118 | #define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT) |
119 | 119 | ||
120 | /* CHA Version IDs */ | ||
121 | #define CHA_ID_AES_SHIFT 0 | ||
122 | #define CHA_ID_AES_MASK (0xfull << CHA_ID_AES_SHIFT) | ||
123 | |||
124 | #define CHA_ID_DES_SHIFT 4 | ||
125 | #define CHA_ID_DES_MASK (0xfull << CHA_ID_DES_SHIFT) | ||
126 | |||
127 | #define CHA_ID_ARC4_SHIFT 8 | ||
128 | #define CHA_ID_ARC4_MASK (0xfull << CHA_ID_ARC4_SHIFT) | ||
129 | |||
130 | #define CHA_ID_MD_SHIFT 12 | ||
131 | #define CHA_ID_MD_MASK (0xfull << CHA_ID_MD_SHIFT) | ||
132 | |||
133 | #define CHA_ID_RNG_SHIFT 16 | ||
134 | #define CHA_ID_RNG_MASK (0xfull << CHA_ID_RNG_SHIFT) | ||
135 | |||
136 | #define CHA_ID_SNW8_SHIFT 20 | ||
137 | #define CHA_ID_SNW8_MASK (0xfull << CHA_ID_SNW8_SHIFT) | ||
138 | |||
139 | #define CHA_ID_KAS_SHIFT 24 | ||
140 | #define CHA_ID_KAS_MASK (0xfull << CHA_ID_KAS_SHIFT) | ||
141 | |||
142 | #define CHA_ID_PK_SHIFT 28 | ||
143 | #define CHA_ID_PK_MASK (0xfull << CHA_ID_PK_SHIFT) | ||
144 | |||
145 | #define CHA_ID_CRC_SHIFT 32 | ||
146 | #define CHA_ID_CRC_MASK (0xfull << CHA_ID_CRC_SHIFT) | ||
147 | |||
148 | #define CHA_ID_SNW9_SHIFT 36 | ||
149 | #define CHA_ID_SNW9_MASK (0xfull << CHA_ID_SNW9_SHIFT) | ||
150 | |||
151 | #define CHA_ID_DECO_SHIFT 56 | ||
152 | #define CHA_ID_DECO_MASK (0xfull << CHA_ID_DECO_SHIFT) | ||
153 | |||
154 | #define CHA_ID_JR_SHIFT 60 | ||
155 | #define CHA_ID_JR_MASK (0xfull << CHA_ID_JR_SHIFT) | ||
156 | |||
120 | struct sec_vid { | 157 | struct sec_vid { |
121 | u16 ip_id; | 158 | u16 ip_id; |
122 | u8 maj_rev; | 159 | u8 maj_rev; |
@@ -228,7 +265,10 @@ struct rng4tst { | |||
228 | u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */ | 265 | u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */ |
229 | u32 rtfrqcnt; /* PRGM=0: freq. count register */ | 266 | u32 rtfrqcnt; /* PRGM=0: freq. count register */ |
230 | }; | 267 | }; |
231 | u32 rsvd1[56]; | 268 | u32 rsvd1[40]; |
269 | #define RDSTA_IF0 0x00000001 | ||
270 | u32 rdsta; | ||
271 | u32 rsvd2[15]; | ||
232 | }; | 272 | }; |
233 | 273 | ||
234 | /* | 274 | /* |
diff --git a/drivers/crypto/dcp.c b/drivers/crypto/dcp.c new file mode 100644 index 000000000000..a8a7dd4b0d25 --- /dev/null +++ b/drivers/crypto/dcp.c | |||
@@ -0,0 +1,912 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * Support for DCP cryptographic accelerator. | ||
5 | * | ||
6 | * Copyright (c) 2013 | ||
7 | * Author: Tobias Rauter <tobias.rauter@gmail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | * | ||
13 | * Based on tegra-aes.c, dcp.c (from freescale SDK) and sahara.c | ||
14 | */ | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/dma-mapping.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/completion.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/crypto.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | |||
30 | #include <crypto/scatterwalk.h> | ||
31 | #include <crypto/aes.h> | ||
32 | |||
33 | |||
34 | /* IOCTL for DCP OTP Key AES - taken from Freescale's SDK*/ | ||
35 | #define DBS_IOCTL_BASE 'd' | ||
36 | #define DBS_ENC _IOW(DBS_IOCTL_BASE, 0x00, uint8_t[16]) | ||
37 | #define DBS_DEC _IOW(DBS_IOCTL_BASE, 0x01, uint8_t[16]) | ||
38 | |||
39 | /* DCP channel used for AES */ | ||
40 | #define USED_CHANNEL 1 | ||
41 | /* Ring Buffers' maximum size */ | ||
42 | #define DCP_MAX_PKG 20 | ||
43 | |||
44 | /* Control Register */ | ||
45 | #define DCP_REG_CTRL 0x000 | ||
46 | #define DCP_CTRL_SFRST (1<<31) | ||
47 | #define DCP_CTRL_CLKGATE (1<<30) | ||
48 | #define DCP_CTRL_CRYPTO_PRESENT (1<<29) | ||
49 | #define DCP_CTRL_SHA_PRESENT (1<<28) | ||
50 | #define DCP_CTRL_GATHER_RES_WRITE (1<<23) | ||
51 | #define DCP_CTRL_ENABLE_CONTEXT_CACHE (1<<22) | ||
52 | #define DCP_CTRL_ENABLE_CONTEXT_SWITCH (1<<21) | ||
53 | #define DCP_CTRL_CH_IRQ_E_0 0x01 | ||
54 | #define DCP_CTRL_CH_IRQ_E_1 0x02 | ||
55 | #define DCP_CTRL_CH_IRQ_E_2 0x04 | ||
56 | #define DCP_CTRL_CH_IRQ_E_3 0x08 | ||
57 | |||
58 | /* Status register */ | ||
59 | #define DCP_REG_STAT 0x010 | ||
60 | #define DCP_STAT_OTP_KEY_READY (1<<28) | ||
61 | #define DCP_STAT_CUR_CHANNEL(stat) ((stat>>24)&0x0F) | ||
62 | #define DCP_STAT_READY_CHANNEL(stat) ((stat>>16)&0x0F) | ||
63 | #define DCP_STAT_IRQ(stat) (stat&0x0F) | ||
64 | #define DCP_STAT_CHAN_0 (0x01) | ||
65 | #define DCP_STAT_CHAN_1 (0x02) | ||
66 | #define DCP_STAT_CHAN_2 (0x04) | ||
67 | #define DCP_STAT_CHAN_3 (0x08) | ||
68 | |||
69 | /* Channel Control Register */ | ||
70 | #define DCP_REG_CHAN_CTRL 0x020 | ||
71 | #define DCP_CHAN_CTRL_CH0_IRQ_MERGED (1<<16) | ||
72 | #define DCP_CHAN_CTRL_HIGH_PRIO_0 (0x0100) | ||
73 | #define DCP_CHAN_CTRL_HIGH_PRIO_1 (0x0200) | ||
74 | #define DCP_CHAN_CTRL_HIGH_PRIO_2 (0x0400) | ||
75 | #define DCP_CHAN_CTRL_HIGH_PRIO_3 (0x0800) | ||
76 | #define DCP_CHAN_CTRL_ENABLE_0 (0x01) | ||
77 | #define DCP_CHAN_CTRL_ENABLE_1 (0x02) | ||
78 | #define DCP_CHAN_CTRL_ENABLE_2 (0x04) | ||
79 | #define DCP_CHAN_CTRL_ENABLE_3 (0x08) | ||
80 | |||
81 | /* | ||
82 | * Channel Registers: | ||
83 | * The DCP has 4 channels. Each of this channels | ||
84 | * has 4 registers (command pointer, semaphore, status and options). | ||
85 | * The address of register REG of channel CHAN is obtained by | ||
86 | * dcp_chan_reg(REG, CHAN) | ||
87 | */ | ||
88 | #define DCP_REG_CHAN_PTR 0x00000100 | ||
89 | #define DCP_REG_CHAN_SEMA 0x00000110 | ||
90 | #define DCP_REG_CHAN_STAT 0x00000120 | ||
91 | #define DCP_REG_CHAN_OPT 0x00000130 | ||
92 | |||
93 | #define DCP_CHAN_STAT_NEXT_CHAIN_IS_0 0x010000 | ||
94 | #define DCP_CHAN_STAT_NO_CHAIN 0x020000 | ||
95 | #define DCP_CHAN_STAT_CONTEXT_ERROR 0x030000 | ||
96 | #define DCP_CHAN_STAT_PAYLOAD_ERROR 0x040000 | ||
97 | #define DCP_CHAN_STAT_INVALID_MODE 0x050000 | ||
98 | #define DCP_CHAN_STAT_PAGEFAULT 0x40 | ||
99 | #define DCP_CHAN_STAT_DST 0x20 | ||
100 | #define DCP_CHAN_STAT_SRC 0x10 | ||
101 | #define DCP_CHAN_STAT_PACKET 0x08 | ||
102 | #define DCP_CHAN_STAT_SETUP 0x04 | ||
103 | #define DCP_CHAN_STAT_MISMATCH 0x02 | ||
104 | |||
105 | /* hw packet control*/ | ||
106 | |||
107 | #define DCP_PKT_PAYLOAD_KEY (1<<11) | ||
108 | #define DCP_PKT_OTP_KEY (1<<10) | ||
109 | #define DCP_PKT_CIPHER_INIT (1<<9) | ||
110 | #define DCP_PKG_CIPHER_ENCRYPT (1<<8) | ||
111 | #define DCP_PKT_CIPHER_ENABLE (1<<5) | ||
112 | #define DCP_PKT_DECR_SEM (1<<1) | ||
113 | #define DCP_PKT_CHAIN (1<<2) | ||
114 | #define DCP_PKT_IRQ 1 | ||
115 | |||
116 | #define DCP_PKT_MODE_CBC (1<<4) | ||
117 | #define DCP_PKT_KEYSELECT_OTP (0xFF<<8) | ||
118 | |||
119 | /* cipher flags */ | ||
120 | #define DCP_ENC 0x0001 | ||
121 | #define DCP_DEC 0x0002 | ||
122 | #define DCP_ECB 0x0004 | ||
123 | #define DCP_CBC 0x0008 | ||
124 | #define DCP_CBC_INIT 0x0010 | ||
125 | #define DCP_NEW_KEY 0x0040 | ||
126 | #define DCP_OTP_KEY 0x0080 | ||
127 | #define DCP_AES 0x1000 | ||
128 | |||
129 | /* DCP Flags */ | ||
130 | #define DCP_FLAG_BUSY 0x01 | ||
131 | #define DCP_FLAG_PRODUCING 0x02 | ||
132 | |||
133 | /* clock defines */ | ||
134 | #define CLOCK_ON 1 | ||
135 | #define CLOCK_OFF 0 | ||
136 | |||
137 | struct dcp_dev_req_ctx { | ||
138 | int mode; | ||
139 | }; | ||
140 | |||
141 | struct dcp_op { | ||
142 | unsigned int flags; | ||
143 | u8 key[AES_KEYSIZE_128]; | ||
144 | int keylen; | ||
145 | |||
146 | struct ablkcipher_request *req; | ||
147 | struct crypto_ablkcipher *fallback; | ||
148 | |||
149 | uint32_t stat; | ||
150 | uint32_t pkt1; | ||
151 | uint32_t pkt2; | ||
152 | struct ablkcipher_walk walk; | ||
153 | }; | ||
154 | |||
155 | struct dcp_dev { | ||
156 | struct device *dev; | ||
157 | void __iomem *dcp_regs_base; | ||
158 | |||
159 | int dcp_vmi_irq; | ||
160 | int dcp_irq; | ||
161 | |||
162 | spinlock_t queue_lock; | ||
163 | struct crypto_queue queue; | ||
164 | |||
165 | uint32_t pkt_produced; | ||
166 | uint32_t pkt_consumed; | ||
167 | |||
168 | struct dcp_hw_packet *hw_pkg[DCP_MAX_PKG]; | ||
169 | dma_addr_t hw_phys_pkg; | ||
170 | |||
171 | /* [KEY][IV] Both with 16 Bytes */ | ||
172 | u8 *payload_base; | ||
173 | dma_addr_t payload_base_dma; | ||
174 | |||
175 | |||
176 | struct tasklet_struct done_task; | ||
177 | struct tasklet_struct queue_task; | ||
178 | struct timer_list watchdog; | ||
179 | |||
180 | unsigned long flags; | ||
181 | |||
182 | struct dcp_op *ctx; | ||
183 | |||
184 | struct miscdevice dcp_bootstream_misc; | ||
185 | }; | ||
186 | |||
187 | struct dcp_hw_packet { | ||
188 | uint32_t next; | ||
189 | uint32_t pkt1; | ||
190 | uint32_t pkt2; | ||
191 | uint32_t src; | ||
192 | uint32_t dst; | ||
193 | uint32_t size; | ||
194 | uint32_t payload; | ||
195 | uint32_t stat; | ||
196 | }; | ||
197 | |||
198 | static struct dcp_dev *global_dev; | ||
199 | |||
200 | static inline u32 dcp_chan_reg(u32 reg, int chan) | ||
201 | { | ||
202 | return reg + (chan) * 0x40; | ||
203 | } | ||
204 | |||
205 | static inline void dcp_write(struct dcp_dev *dev, u32 data, u32 reg) | ||
206 | { | ||
207 | writel(data, dev->dcp_regs_base + reg); | ||
208 | } | ||
209 | |||
210 | static inline void dcp_set(struct dcp_dev *dev, u32 data, u32 reg) | ||
211 | { | ||
212 | writel(data, dev->dcp_regs_base + (reg | 0x04)); | ||
213 | } | ||
214 | |||
215 | static inline void dcp_clear(struct dcp_dev *dev, u32 data, u32 reg) | ||
216 | { | ||
217 | writel(data, dev->dcp_regs_base + (reg | 0x08)); | ||
218 | } | ||
219 | |||
220 | static inline void dcp_toggle(struct dcp_dev *dev, u32 data, u32 reg) | ||
221 | { | ||
222 | writel(data, dev->dcp_regs_base + (reg | 0x0C)); | ||
223 | } | ||
224 | |||
225 | static inline unsigned int dcp_read(struct dcp_dev *dev, u32 reg) | ||
226 | { | ||
227 | return readl(dev->dcp_regs_base + reg); | ||
228 | } | ||
229 | |||
230 | static void dcp_dma_unmap(struct dcp_dev *dev, struct dcp_hw_packet *pkt) | ||
231 | { | ||
232 | dma_unmap_page(dev->dev, pkt->src, pkt->size, DMA_TO_DEVICE); | ||
233 | dma_unmap_page(dev->dev, pkt->dst, pkt->size, DMA_FROM_DEVICE); | ||
234 | dev_dbg(dev->dev, "unmap packet %x", (unsigned int) pkt); | ||
235 | } | ||
236 | |||
237 | static int dcp_dma_map(struct dcp_dev *dev, | ||
238 | struct ablkcipher_walk *walk, struct dcp_hw_packet *pkt) | ||
239 | { | ||
240 | dev_dbg(dev->dev, "map packet %x", (unsigned int) pkt); | ||
241 | /* align to length = 16 */ | ||
242 | pkt->size = walk->nbytes - (walk->nbytes % 16); | ||
243 | |||
244 | pkt->src = dma_map_page(dev->dev, walk->src.page, walk->src.offset, | ||
245 | pkt->size, DMA_TO_DEVICE); | ||
246 | |||
247 | if (pkt->src == 0) { | ||
248 | dev_err(dev->dev, "Unable to map src"); | ||
249 | return -ENOMEM; | ||
250 | } | ||
251 | |||
252 | pkt->dst = dma_map_page(dev->dev, walk->dst.page, walk->dst.offset, | ||
253 | pkt->size, DMA_FROM_DEVICE); | ||
254 | |||
255 | if (pkt->dst == 0) { | ||
256 | dev_err(dev->dev, "Unable to map dst"); | ||
257 | dma_unmap_page(dev->dev, pkt->src, pkt->size, DMA_TO_DEVICE); | ||
258 | return -ENOMEM; | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static void dcp_op_one(struct dcp_dev *dev, struct dcp_hw_packet *pkt, | ||
265 | uint8_t last) | ||
266 | { | ||
267 | struct dcp_op *ctx = dev->ctx; | ||
268 | pkt->pkt1 = ctx->pkt1; | ||
269 | pkt->pkt2 = ctx->pkt2; | ||
270 | |||
271 | pkt->payload = (u32) dev->payload_base_dma; | ||
272 | pkt->stat = 0; | ||
273 | |||
274 | if (ctx->flags & DCP_CBC_INIT) { | ||
275 | pkt->pkt1 |= DCP_PKT_CIPHER_INIT; | ||
276 | ctx->flags &= ~DCP_CBC_INIT; | ||
277 | } | ||
278 | |||
279 | mod_timer(&dev->watchdog, jiffies + msecs_to_jiffies(500)); | ||
280 | pkt->pkt1 |= DCP_PKT_IRQ; | ||
281 | if (!last) | ||
282 | pkt->pkt1 |= DCP_PKT_CHAIN; | ||
283 | |||
284 | dev->pkt_produced++; | ||
285 | |||
286 | dcp_write(dev, 1, | ||
287 | dcp_chan_reg(DCP_REG_CHAN_SEMA, USED_CHANNEL)); | ||
288 | } | ||
289 | |||
290 | static void dcp_op_proceed(struct dcp_dev *dev) | ||
291 | { | ||
292 | struct dcp_op *ctx = dev->ctx; | ||
293 | struct dcp_hw_packet *pkt; | ||
294 | |||
295 | while (ctx->walk.nbytes) { | ||
296 | int err = 0; | ||
297 | |||
298 | pkt = dev->hw_pkg[dev->pkt_produced % DCP_MAX_PKG]; | ||
299 | err = dcp_dma_map(dev, &ctx->walk, pkt); | ||
300 | if (err) { | ||
301 | dev->ctx->stat |= err; | ||
302 | /* start timer to wait for already set up calls */ | ||
303 | mod_timer(&dev->watchdog, | ||
304 | jiffies + msecs_to_jiffies(500)); | ||
305 | break; | ||
306 | } | ||
307 | |||
308 | |||
309 | err = ctx->walk.nbytes - pkt->size; | ||
310 | ablkcipher_walk_done(dev->ctx->req, &dev->ctx->walk, err); | ||
311 | |||
312 | dcp_op_one(dev, pkt, ctx->walk.nbytes == 0); | ||
313 | /* we have to wait if no space is left in buffer */ | ||
314 | if (dev->pkt_produced - dev->pkt_consumed == DCP_MAX_PKG) | ||
315 | break; | ||
316 | } | ||
317 | clear_bit(DCP_FLAG_PRODUCING, &dev->flags); | ||
318 | } | ||
319 | |||
320 | static void dcp_op_start(struct dcp_dev *dev, uint8_t use_walk) | ||
321 | { | ||
322 | struct dcp_op *ctx = dev->ctx; | ||
323 | |||
324 | if (ctx->flags & DCP_NEW_KEY) { | ||
325 | memcpy(dev->payload_base, ctx->key, ctx->keylen); | ||
326 | ctx->flags &= ~DCP_NEW_KEY; | ||
327 | } | ||
328 | |||
329 | ctx->pkt1 = 0; | ||
330 | ctx->pkt1 |= DCP_PKT_CIPHER_ENABLE; | ||
331 | ctx->pkt1 |= DCP_PKT_DECR_SEM; | ||
332 | |||
333 | if (ctx->flags & DCP_OTP_KEY) | ||
334 | ctx->pkt1 |= DCP_PKT_OTP_KEY; | ||
335 | else | ||
336 | ctx->pkt1 |= DCP_PKT_PAYLOAD_KEY; | ||
337 | |||
338 | if (ctx->flags & DCP_ENC) | ||
339 | ctx->pkt1 |= DCP_PKG_CIPHER_ENCRYPT; | ||
340 | |||
341 | ctx->pkt2 = 0; | ||
342 | if (ctx->flags & DCP_CBC) | ||
343 | ctx->pkt2 |= DCP_PKT_MODE_CBC; | ||
344 | |||
345 | dev->pkt_produced = 0; | ||
346 | dev->pkt_consumed = 0; | ||
347 | |||
348 | ctx->stat = 0; | ||
349 | dcp_clear(dev, -1, dcp_chan_reg(DCP_REG_CHAN_STAT, USED_CHANNEL)); | ||
350 | dcp_write(dev, (u32) dev->hw_phys_pkg, | ||
351 | dcp_chan_reg(DCP_REG_CHAN_PTR, USED_CHANNEL)); | ||
352 | |||
353 | set_bit(DCP_FLAG_PRODUCING, &dev->flags); | ||
354 | |||
355 | if (use_walk) { | ||
356 | ablkcipher_walk_init(&ctx->walk, ctx->req->dst, | ||
357 | ctx->req->src, ctx->req->nbytes); | ||
358 | ablkcipher_walk_phys(ctx->req, &ctx->walk); | ||
359 | dcp_op_proceed(dev); | ||
360 | } else { | ||
361 | dcp_op_one(dev, dev->hw_pkg[0], 1); | ||
362 | clear_bit(DCP_FLAG_PRODUCING, &dev->flags); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | static void dcp_done_task(unsigned long data) | ||
367 | { | ||
368 | struct dcp_dev *dev = (struct dcp_dev *)data; | ||
369 | struct dcp_hw_packet *last_packet; | ||
370 | int fin; | ||
371 | fin = 0; | ||
372 | |||
373 | for (last_packet = dev->hw_pkg[(dev->pkt_consumed) % DCP_MAX_PKG]; | ||
374 | last_packet->stat == 1; | ||
375 | last_packet = | ||
376 | dev->hw_pkg[++(dev->pkt_consumed) % DCP_MAX_PKG]) { | ||
377 | |||
378 | dcp_dma_unmap(dev, last_packet); | ||
379 | last_packet->stat = 0; | ||
380 | fin++; | ||
381 | } | ||
382 | /* the last call of this function already consumed this IRQ's packet */ | ||
383 | if (fin == 0) | ||
384 | return; | ||
385 | |||
386 | dev_dbg(dev->dev, | ||
387 | "Packet(s) done with status %x; finished: %d, produced:%d, complete consumed: %d", | ||
388 | dev->ctx->stat, fin, dev->pkt_produced, dev->pkt_consumed); | ||
389 | |||
390 | last_packet = dev->hw_pkg[(dev->pkt_consumed - 1) % DCP_MAX_PKG]; | ||
391 | if (!dev->ctx->stat && last_packet->pkt1 & DCP_PKT_CHAIN) { | ||
392 | if (!test_and_set_bit(DCP_FLAG_PRODUCING, &dev->flags)) | ||
393 | dcp_op_proceed(dev); | ||
394 | return; | ||
395 | } | ||
396 | |||
397 | while (unlikely(dev->pkt_consumed < dev->pkt_produced)) { | ||
398 | dcp_dma_unmap(dev, | ||
399 | dev->hw_pkg[dev->pkt_consumed++ % DCP_MAX_PKG]); | ||
400 | } | ||
401 | |||
402 | if (dev->ctx->flags & DCP_OTP_KEY) { | ||
403 | /* we used the miscdevice, no walk to finish */ | ||
404 | clear_bit(DCP_FLAG_BUSY, &dev->flags); | ||
405 | return; | ||
406 | } | ||
407 | |||
408 | ablkcipher_walk_complete(&dev->ctx->walk); | ||
409 | dev->ctx->req->base.complete(&dev->ctx->req->base, | ||
410 | dev->ctx->stat); | ||
411 | dev->ctx->req = NULL; | ||
412 | /* in case there are other requests in the queue */ | ||
413 | tasklet_schedule(&dev->queue_task); | ||
414 | } | ||
415 | |||
416 | static void dcp_watchdog(unsigned long data) | ||
417 | { | ||
418 | struct dcp_dev *dev = (struct dcp_dev *)data; | ||
419 | dev->ctx->stat |= dcp_read(dev, | ||
420 | dcp_chan_reg(DCP_REG_CHAN_STAT, USED_CHANNEL)); | ||
421 | |||
422 | dev_err(dev->dev, "Timeout, Channel status: %x", dev->ctx->stat); | ||
423 | |||
424 | if (!dev->ctx->stat) | ||
425 | dev->ctx->stat = -ETIMEDOUT; | ||
426 | |||
427 | dcp_done_task(data); | ||
428 | } | ||
429 | |||
430 | |||
431 | static irqreturn_t dcp_common_irq(int irq, void *context) | ||
432 | { | ||
433 | u32 msk; | ||
434 | struct dcp_dev *dev = (struct dcp_dev *) context; | ||
435 | |||
436 | del_timer(&dev->watchdog); | ||
437 | |||
438 | msk = DCP_STAT_IRQ(dcp_read(dev, DCP_REG_STAT)); | ||
439 | dcp_clear(dev, msk, DCP_REG_STAT); | ||
440 | if (msk == 0) | ||
441 | return IRQ_NONE; | ||
442 | |||
443 | dev->ctx->stat |= dcp_read(dev, | ||
444 | dcp_chan_reg(DCP_REG_CHAN_STAT, USED_CHANNEL)); | ||
445 | |||
446 | if (msk & DCP_STAT_CHAN_1) | ||
447 | tasklet_schedule(&dev->done_task); | ||
448 | |||
449 | return IRQ_HANDLED; | ||
450 | } | ||
451 | |||
452 | static irqreturn_t dcp_vmi_irq(int irq, void *context) | ||
453 | { | ||
454 | return dcp_common_irq(irq, context); | ||
455 | } | ||
456 | |||
457 | static irqreturn_t dcp_irq(int irq, void *context) | ||
458 | { | ||
459 | return dcp_common_irq(irq, context); | ||
460 | } | ||
461 | |||
462 | static void dcp_crypt(struct dcp_dev *dev, struct dcp_op *ctx) | ||
463 | { | ||
464 | dev->ctx = ctx; | ||
465 | |||
466 | if ((ctx->flags & DCP_CBC) && ctx->req->info) { | ||
467 | ctx->flags |= DCP_CBC_INIT; | ||
468 | memcpy(dev->payload_base + AES_KEYSIZE_128, | ||
469 | ctx->req->info, AES_KEYSIZE_128); | ||
470 | } | ||
471 | |||
472 | dcp_op_start(dev, 1); | ||
473 | } | ||
474 | |||
475 | static void dcp_queue_task(unsigned long data) | ||
476 | { | ||
477 | struct dcp_dev *dev = (struct dcp_dev *) data; | ||
478 | struct crypto_async_request *async_req, *backlog; | ||
479 | struct crypto_ablkcipher *tfm; | ||
480 | struct dcp_op *ctx; | ||
481 | struct dcp_dev_req_ctx *rctx; | ||
482 | struct ablkcipher_request *req; | ||
483 | unsigned long flags; | ||
484 | |||
485 | spin_lock_irqsave(&dev->queue_lock, flags); | ||
486 | |||
487 | backlog = crypto_get_backlog(&dev->queue); | ||
488 | async_req = crypto_dequeue_request(&dev->queue); | ||
489 | |||
490 | spin_unlock_irqrestore(&dev->queue_lock, flags); | ||
491 | |||
492 | if (!async_req) | ||
493 | goto ret_nothing_done; | ||
494 | |||
495 | if (backlog) | ||
496 | backlog->complete(backlog, -EINPROGRESS); | ||
497 | |||
498 | req = ablkcipher_request_cast(async_req); | ||
499 | tfm = crypto_ablkcipher_reqtfm(req); | ||
500 | rctx = ablkcipher_request_ctx(req); | ||
501 | ctx = crypto_ablkcipher_ctx(tfm); | ||
502 | |||
503 | if (!req->src || !req->dst) | ||
504 | goto ret_nothing_done; | ||
505 | |||
506 | ctx->flags |= rctx->mode; | ||
507 | ctx->req = req; | ||
508 | |||
509 | dcp_crypt(dev, ctx); | ||
510 | |||
511 | return; | ||
512 | |||
513 | ret_nothing_done: | ||
514 | clear_bit(DCP_FLAG_BUSY, &dev->flags); | ||
515 | } | ||
516 | |||
517 | |||
518 | static int dcp_cra_init(struct crypto_tfm *tfm) | ||
519 | { | ||
520 | const char *name = tfm->__crt_alg->cra_name; | ||
521 | struct dcp_op *ctx = crypto_tfm_ctx(tfm); | ||
522 | |||
523 | tfm->crt_ablkcipher.reqsize = sizeof(struct dcp_dev_req_ctx); | ||
524 | |||
525 | ctx->fallback = crypto_alloc_ablkcipher(name, 0, | ||
526 | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); | ||
527 | |||
528 | if (IS_ERR(ctx->fallback)) { | ||
529 | dev_err(global_dev->dev, "Error allocating fallback algo %s\n", | ||
530 | name); | ||
531 | return PTR_ERR(ctx->fallback); | ||
532 | } | ||
533 | |||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static void dcp_cra_exit(struct crypto_tfm *tfm) | ||
538 | { | ||
539 | struct dcp_op *ctx = crypto_tfm_ctx(tfm); | ||
540 | |||
541 | if (ctx->fallback) | ||
542 | crypto_free_ablkcipher(ctx->fallback); | ||
543 | |||
544 | ctx->fallback = NULL; | ||
545 | } | ||
546 | |||
547 | /* async interface */ | ||
548 | static int dcp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, | ||
549 | unsigned int len) | ||
550 | { | ||
551 | struct dcp_op *ctx = crypto_ablkcipher_ctx(tfm); | ||
552 | unsigned int ret = 0; | ||
553 | ctx->keylen = len; | ||
554 | ctx->flags = 0; | ||
555 | if (len == AES_KEYSIZE_128) { | ||
556 | if (memcmp(ctx->key, key, AES_KEYSIZE_128)) { | ||
557 | memcpy(ctx->key, key, len); | ||
558 | ctx->flags |= DCP_NEW_KEY; | ||
559 | } | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; | ||
564 | ctx->fallback->base.crt_flags |= | ||
565 | (tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); | ||
566 | |||
567 | ret = crypto_ablkcipher_setkey(ctx->fallback, key, len); | ||
568 | if (ret) { | ||
569 | struct crypto_tfm *tfm_aux = crypto_ablkcipher_tfm(tfm); | ||
570 | |||
571 | tfm_aux->crt_flags &= ~CRYPTO_TFM_RES_MASK; | ||
572 | tfm_aux->crt_flags |= | ||
573 | (ctx->fallback->base.crt_flags & CRYPTO_TFM_RES_MASK); | ||
574 | } | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | static int dcp_aes_cbc_crypt(struct ablkcipher_request *req, int mode) | ||
579 | { | ||
580 | struct dcp_dev_req_ctx *rctx = ablkcipher_request_ctx(req); | ||
581 | struct dcp_dev *dev = global_dev; | ||
582 | unsigned long flags; | ||
583 | int err = 0; | ||
584 | |||
585 | if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) | ||
586 | return -EINVAL; | ||
587 | |||
588 | rctx->mode = mode; | ||
589 | |||
590 | spin_lock_irqsave(&dev->queue_lock, flags); | ||
591 | err = ablkcipher_enqueue_request(&dev->queue, req); | ||
592 | spin_unlock_irqrestore(&dev->queue_lock, flags); | ||
593 | |||
594 | flags = test_and_set_bit(DCP_FLAG_BUSY, &dev->flags); | ||
595 | |||
596 | if (!(flags & DCP_FLAG_BUSY)) | ||
597 | tasklet_schedule(&dev->queue_task); | ||
598 | |||
599 | return err; | ||
600 | } | ||
601 | |||
602 | static int dcp_aes_cbc_encrypt(struct ablkcipher_request *req) | ||
603 | { | ||
604 | struct crypto_tfm *tfm = | ||
605 | crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); | ||
606 | struct dcp_op *ctx = crypto_ablkcipher_ctx( | ||
607 | crypto_ablkcipher_reqtfm(req)); | ||
608 | |||
609 | if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { | ||
610 | int err = 0; | ||
611 | ablkcipher_request_set_tfm(req, ctx->fallback); | ||
612 | err = crypto_ablkcipher_encrypt(req); | ||
613 | ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm)); | ||
614 | return err; | ||
615 | } | ||
616 | |||
617 | return dcp_aes_cbc_crypt(req, DCP_AES | DCP_ENC | DCP_CBC); | ||
618 | } | ||
619 | |||
620 | static int dcp_aes_cbc_decrypt(struct ablkcipher_request *req) | ||
621 | { | ||
622 | struct crypto_tfm *tfm = | ||
623 | crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); | ||
624 | struct dcp_op *ctx = crypto_ablkcipher_ctx( | ||
625 | crypto_ablkcipher_reqtfm(req)); | ||
626 | |||
627 | if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { | ||
628 | int err = 0; | ||
629 | ablkcipher_request_set_tfm(req, ctx->fallback); | ||
630 | err = crypto_ablkcipher_decrypt(req); | ||
631 | ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm)); | ||
632 | return err; | ||
633 | } | ||
634 | return dcp_aes_cbc_crypt(req, DCP_AES | DCP_DEC | DCP_CBC); | ||
635 | } | ||
636 | |||
637 | static struct crypto_alg algs[] = { | ||
638 | { | ||
639 | .cra_name = "cbc(aes)", | ||
640 | .cra_driver_name = "dcp-cbc-aes", | ||
641 | .cra_alignmask = 3, | ||
642 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | | ||
643 | CRYPTO_ALG_NEED_FALLBACK, | ||
644 | .cra_blocksize = AES_KEYSIZE_128, | ||
645 | .cra_type = &crypto_ablkcipher_type, | ||
646 | .cra_priority = 300, | ||
647 | .cra_u.ablkcipher = { | ||
648 | .min_keysize = AES_KEYSIZE_128, | ||
649 | .max_keysize = AES_KEYSIZE_128, | ||
650 | .setkey = dcp_aes_setkey, | ||
651 | .encrypt = dcp_aes_cbc_encrypt, | ||
652 | .decrypt = dcp_aes_cbc_decrypt, | ||
653 | .ivsize = AES_KEYSIZE_128, | ||
654 | } | ||
655 | |||
656 | }, | ||
657 | }; | ||
658 | |||
659 | /* DCP bootstream verification interface: uses OTP key for crypto */ | ||
660 | static int dcp_bootstream_open(struct inode *inode, struct file *file) | ||
661 | { | ||
662 | file->private_data = container_of((file->private_data), | ||
663 | struct dcp_dev, dcp_bootstream_misc); | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static long dcp_bootstream_ioctl(struct file *file, | ||
668 | unsigned int cmd, unsigned long arg) | ||
669 | { | ||
670 | struct dcp_dev *dev = (struct dcp_dev *) file->private_data; | ||
671 | void __user *argp = (void __user *)arg; | ||
672 | int ret; | ||
673 | |||
674 | if (dev == NULL) | ||
675 | return -EBADF; | ||
676 | |||
677 | if (cmd != DBS_ENC && cmd != DBS_DEC) | ||
678 | return -EINVAL; | ||
679 | |||
680 | if (copy_from_user(dev->payload_base, argp, 16)) | ||
681 | return -EFAULT; | ||
682 | |||
683 | if (test_and_set_bit(DCP_FLAG_BUSY, &dev->flags)) | ||
684 | return -EAGAIN; | ||
685 | |||
686 | dev->ctx = kzalloc(sizeof(struct dcp_op), GFP_KERNEL); | ||
687 | if (!dev->ctx) { | ||
688 | dev_err(dev->dev, | ||
689 | "cannot allocate context for OTP crypto"); | ||
690 | clear_bit(DCP_FLAG_BUSY, &dev->flags); | ||
691 | return -ENOMEM; | ||
692 | } | ||
693 | |||
694 | dev->ctx->flags = DCP_AES | DCP_ECB | DCP_OTP_KEY | DCP_CBC_INIT; | ||
695 | dev->ctx->flags |= (cmd == DBS_ENC) ? DCP_ENC : DCP_DEC; | ||
696 | dev->hw_pkg[0]->src = dev->payload_base_dma; | ||
697 | dev->hw_pkg[0]->dst = dev->payload_base_dma; | ||
698 | dev->hw_pkg[0]->size = 16; | ||
699 | |||
700 | dcp_op_start(dev, 0); | ||
701 | |||
702 | while (test_bit(DCP_FLAG_BUSY, &dev->flags)) | ||
703 | cpu_relax(); | ||
704 | |||
705 | ret = dev->ctx->stat; | ||
706 | if (!ret && copy_to_user(argp, dev->payload_base, 16)) | ||
707 | ret = -EFAULT; | ||
708 | |||
709 | kfree(dev->ctx); | ||
710 | |||
711 | return ret; | ||
712 | } | ||
713 | |||
714 | static const struct file_operations dcp_bootstream_fops = { | ||
715 | .owner = THIS_MODULE, | ||
716 | .unlocked_ioctl = dcp_bootstream_ioctl, | ||
717 | .open = dcp_bootstream_open, | ||
718 | }; | ||
719 | |||
720 | static int dcp_probe(struct platform_device *pdev) | ||
721 | { | ||
722 | struct dcp_dev *dev = NULL; | ||
723 | struct resource *r; | ||
724 | int i, ret, j; | ||
725 | |||
726 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); | ||
727 | if (!dev) | ||
728 | return -ENOMEM; | ||
729 | |||
730 | global_dev = dev; | ||
731 | dev->dev = &pdev->dev; | ||
732 | |||
733 | platform_set_drvdata(pdev, dev); | ||
734 | |||
735 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
736 | if (!r) { | ||
737 | dev_err(&pdev->dev, "failed to get IORESOURCE_MEM\n"); | ||
738 | return -ENXIO; | ||
739 | } | ||
740 | dev->dcp_regs_base = devm_ioremap(&pdev->dev, r->start, | ||
741 | resource_size(r)); | ||
742 | |||
743 | dcp_set(dev, DCP_CTRL_SFRST, DCP_REG_CTRL); | ||
744 | udelay(10); | ||
745 | dcp_clear(dev, DCP_CTRL_SFRST | DCP_CTRL_CLKGATE, DCP_REG_CTRL); | ||
746 | |||
747 | dcp_write(dev, DCP_CTRL_GATHER_RES_WRITE | | ||
748 | DCP_CTRL_ENABLE_CONTEXT_CACHE | DCP_CTRL_CH_IRQ_E_1, | ||
749 | DCP_REG_CTRL); | ||
750 | |||
751 | dcp_write(dev, DCP_CHAN_CTRL_ENABLE_1, DCP_REG_CHAN_CTRL); | ||
752 | |||
753 | for (i = 0; i < 4; i++) | ||
754 | dcp_clear(dev, -1, dcp_chan_reg(DCP_REG_CHAN_STAT, i)); | ||
755 | |||
756 | dcp_clear(dev, -1, DCP_REG_STAT); | ||
757 | |||
758 | |||
759 | r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
760 | if (!r) { | ||
761 | dev_err(&pdev->dev, "can't get IRQ resource (0)\n"); | ||
762 | return -EIO; | ||
763 | } | ||
764 | dev->dcp_vmi_irq = r->start; | ||
765 | ret = request_irq(dev->dcp_vmi_irq, dcp_vmi_irq, 0, "dcp", dev); | ||
766 | if (ret != 0) { | ||
767 | dev_err(&pdev->dev, "can't request_irq (0)\n"); | ||
768 | return -EIO; | ||
769 | } | ||
770 | |||
771 | r = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
772 | if (!r) { | ||
773 | dev_err(&pdev->dev, "can't get IRQ resource (1)\n"); | ||
774 | ret = -EIO; | ||
775 | goto err_free_irq0; | ||
776 | } | ||
777 | dev->dcp_irq = r->start; | ||
778 | ret = request_irq(dev->dcp_irq, dcp_irq, 0, "dcp", dev); | ||
779 | if (ret != 0) { | ||
780 | dev_err(&pdev->dev, "can't request_irq (1)\n"); | ||
781 | ret = -EIO; | ||
782 | goto err_free_irq0; | ||
783 | } | ||
784 | |||
785 | dev->hw_pkg[0] = dma_alloc_coherent(&pdev->dev, | ||
786 | DCP_MAX_PKG * sizeof(struct dcp_hw_packet), | ||
787 | &dev->hw_phys_pkg, | ||
788 | GFP_KERNEL); | ||
789 | if (!dev->hw_pkg[0]) { | ||
790 | dev_err(&pdev->dev, "Could not allocate hw descriptors\n"); | ||
791 | ret = -ENOMEM; | ||
792 | goto err_free_irq1; | ||
793 | } | ||
794 | |||
795 | for (i = 1; i < DCP_MAX_PKG; i++) { | ||
796 | dev->hw_pkg[i - 1]->next = dev->hw_phys_pkg | ||
797 | + i * sizeof(struct dcp_hw_packet); | ||
798 | dev->hw_pkg[i] = dev->hw_pkg[i - 1] + 1; | ||
799 | } | ||
800 | dev->hw_pkg[i - 1]->next = dev->hw_phys_pkg; | ||
801 | |||
802 | |||
803 | dev->payload_base = dma_alloc_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, | ||
804 | &dev->payload_base_dma, GFP_KERNEL); | ||
805 | if (!dev->payload_base) { | ||
806 | dev_err(&pdev->dev, "Could not allocate memory for key\n"); | ||
807 | ret = -ENOMEM; | ||
808 | goto err_free_hw_packet; | ||
809 | } | ||
810 | tasklet_init(&dev->queue_task, dcp_queue_task, | ||
811 | (unsigned long) dev); | ||
812 | tasklet_init(&dev->done_task, dcp_done_task, | ||
813 | (unsigned long) dev); | ||
814 | spin_lock_init(&dev->queue_lock); | ||
815 | |||
816 | crypto_init_queue(&dev->queue, 10); | ||
817 | |||
818 | init_timer(&dev->watchdog); | ||
819 | dev->watchdog.function = &dcp_watchdog; | ||
820 | dev->watchdog.data = (unsigned long)dev; | ||
821 | |||
822 | dev->dcp_bootstream_misc.minor = MISC_DYNAMIC_MINOR, | ||
823 | dev->dcp_bootstream_misc.name = "dcpboot", | ||
824 | dev->dcp_bootstream_misc.fops = &dcp_bootstream_fops, | ||
825 | ret = misc_register(&dev->dcp_bootstream_misc); | ||
826 | if (ret != 0) { | ||
827 | dev_err(dev->dev, "Unable to register misc device\n"); | ||
828 | goto err_free_key_iv; | ||
829 | } | ||
830 | |||
831 | for (i = 0; i < ARRAY_SIZE(algs); i++) { | ||
832 | algs[i].cra_priority = 300; | ||
833 | algs[i].cra_ctxsize = sizeof(struct dcp_op); | ||
834 | algs[i].cra_module = THIS_MODULE; | ||
835 | algs[i].cra_init = dcp_cra_init; | ||
836 | algs[i].cra_exit = dcp_cra_exit; | ||
837 | if (crypto_register_alg(&algs[i])) { | ||
838 | dev_err(&pdev->dev, "register algorithm failed\n"); | ||
839 | ret = -ENOMEM; | ||
840 | goto err_unregister; | ||
841 | } | ||
842 | } | ||
843 | dev_notice(&pdev->dev, "DCP crypto enabled.!\n"); | ||
844 | |||
845 | return 0; | ||
846 | |||
847 | err_unregister: | ||
848 | for (j = 0; j < i; j++) | ||
849 | crypto_unregister_alg(&algs[j]); | ||
850 | err_free_key_iv: | ||
851 | dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base, | ||
852 | dev->payload_base_dma); | ||
853 | err_free_hw_packet: | ||
854 | dma_free_coherent(&pdev->dev, DCP_MAX_PKG * | ||
855 | sizeof(struct dcp_hw_packet), dev->hw_pkg[0], | ||
856 | dev->hw_phys_pkg); | ||
857 | err_free_irq1: | ||
858 | free_irq(dev->dcp_irq, dev); | ||
859 | err_free_irq0: | ||
860 | free_irq(dev->dcp_vmi_irq, dev); | ||
861 | |||
862 | return ret; | ||
863 | } | ||
864 | |||
865 | static int dcp_remove(struct platform_device *pdev) | ||
866 | { | ||
867 | struct dcp_dev *dev; | ||
868 | int j; | ||
869 | dev = platform_get_drvdata(pdev); | ||
870 | |||
871 | dma_free_coherent(&pdev->dev, | ||
872 | DCP_MAX_PKG * sizeof(struct dcp_hw_packet), | ||
873 | dev->hw_pkg[0], dev->hw_phys_pkg); | ||
874 | |||
875 | dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base, | ||
876 | dev->payload_base_dma); | ||
877 | |||
878 | free_irq(dev->dcp_irq, dev); | ||
879 | free_irq(dev->dcp_vmi_irq, dev); | ||
880 | |||
881 | tasklet_kill(&dev->done_task); | ||
882 | tasklet_kill(&dev->queue_task); | ||
883 | |||
884 | for (j = 0; j < ARRAY_SIZE(algs); j++) | ||
885 | crypto_unregister_alg(&algs[j]); | ||
886 | |||
887 | misc_deregister(&dev->dcp_bootstream_misc); | ||
888 | |||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | static struct of_device_id fs_dcp_of_match[] = { | ||
893 | { .compatible = "fsl-dcp"}, | ||
894 | {}, | ||
895 | }; | ||
896 | |||
897 | static struct platform_driver fs_dcp_driver = { | ||
898 | .probe = dcp_probe, | ||
899 | .remove = dcp_remove, | ||
900 | .driver = { | ||
901 | .name = "fsl-dcp", | ||
902 | .owner = THIS_MODULE, | ||
903 | .of_match_table = fs_dcp_of_match | ||
904 | } | ||
905 | }; | ||
906 | |||
907 | module_platform_driver(fs_dcp_driver); | ||
908 | |||
909 | |||
910 | MODULE_AUTHOR("Tobias Rauter <tobias.rauter@gmail.com>"); | ||
911 | MODULE_DESCRIPTION("Freescale DCP Crypto Driver"); | ||
912 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index ebf130e894b5..12fea3e22348 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c | |||
@@ -2676,7 +2676,7 @@ err_out_stop_device: | |||
2676 | hifn_reset_dma(dev, 1); | 2676 | hifn_reset_dma(dev, 1); |
2677 | hifn_stop_device(dev); | 2677 | hifn_stop_device(dev); |
2678 | err_out_free_irq: | 2678 | err_out_free_irq: |
2679 | free_irq(dev->irq, dev->name); | 2679 | free_irq(dev->irq, dev); |
2680 | tasklet_kill(&dev->tasklet); | 2680 | tasklet_kill(&dev->tasklet); |
2681 | err_out_free_desc: | 2681 | err_out_free_desc: |
2682 | pci_free_consistent(pdev, sizeof(struct hifn_dma), | 2682 | pci_free_consistent(pdev, sizeof(struct hifn_dma), |
@@ -2711,7 +2711,7 @@ static void hifn_remove(struct pci_dev *pdev) | |||
2711 | hifn_reset_dma(dev, 1); | 2711 | hifn_reset_dma(dev, 1); |
2712 | hifn_stop_device(dev); | 2712 | hifn_stop_device(dev); |
2713 | 2713 | ||
2714 | free_irq(dev->irq, dev->name); | 2714 | free_irq(dev->irq, dev); |
2715 | tasklet_kill(&dev->tasklet); | 2715 | tasklet_kill(&dev->tasklet); |
2716 | 2716 | ||
2717 | hifn_flush(dev); | 2717 | hifn_flush(dev); |
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index ce6290e5471a..3374a3ebe4c7 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c | |||
@@ -1146,7 +1146,6 @@ err_unmap_reg: | |||
1146 | err: | 1146 | err: |
1147 | kfree(cp); | 1147 | kfree(cp); |
1148 | cpg = NULL; | 1148 | cpg = NULL; |
1149 | platform_set_drvdata(pdev, NULL); | ||
1150 | return ret; | 1149 | return ret; |
1151 | } | 1150 | } |
1152 | 1151 | ||
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index ee15b0f7849a..5f7980586850 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c | |||
@@ -203,13 +203,6 @@ static void omap_aes_write_n(struct omap_aes_dev *dd, u32 offset, | |||
203 | 203 | ||
204 | static int omap_aes_hw_init(struct omap_aes_dev *dd) | 204 | static int omap_aes_hw_init(struct omap_aes_dev *dd) |
205 | { | 205 | { |
206 | /* | ||
207 | * clocks are enabled when request starts and disabled when finished. | ||
208 | * It may be long delays between requests. | ||
209 | * Device might go to off mode to save power. | ||
210 | */ | ||
211 | pm_runtime_get_sync(dd->dev); | ||
212 | |||
213 | if (!(dd->flags & FLAGS_INIT)) { | 206 | if (!(dd->flags & FLAGS_INIT)) { |
214 | dd->flags |= FLAGS_INIT; | 207 | dd->flags |= FLAGS_INIT; |
215 | dd->err = 0; | 208 | dd->err = 0; |
@@ -636,7 +629,6 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) | |||
636 | 629 | ||
637 | pr_debug("err: %d\n", err); | 630 | pr_debug("err: %d\n", err); |
638 | 631 | ||
639 | pm_runtime_put(dd->dev); | ||
640 | dd->flags &= ~FLAGS_BUSY; | 632 | dd->flags &= ~FLAGS_BUSY; |
641 | 633 | ||
642 | req->base.complete(&req->base, err); | 634 | req->base.complete(&req->base, err); |
@@ -837,8 +829,16 @@ static int omap_aes_ctr_decrypt(struct ablkcipher_request *req) | |||
837 | 829 | ||
838 | static int omap_aes_cra_init(struct crypto_tfm *tfm) | 830 | static int omap_aes_cra_init(struct crypto_tfm *tfm) |
839 | { | 831 | { |
840 | pr_debug("enter\n"); | 832 | struct omap_aes_dev *dd = NULL; |
833 | |||
834 | /* Find AES device, currently picks the first device */ | ||
835 | spin_lock_bh(&list_lock); | ||
836 | list_for_each_entry(dd, &dev_list, list) { | ||
837 | break; | ||
838 | } | ||
839 | spin_unlock_bh(&list_lock); | ||
841 | 840 | ||
841 | pm_runtime_get_sync(dd->dev); | ||
842 | tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx); | 842 | tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx); |
843 | 843 | ||
844 | return 0; | 844 | return 0; |
@@ -846,7 +846,16 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm) | |||
846 | 846 | ||
847 | static void omap_aes_cra_exit(struct crypto_tfm *tfm) | 847 | static void omap_aes_cra_exit(struct crypto_tfm *tfm) |
848 | { | 848 | { |
849 | pr_debug("enter\n"); | 849 | struct omap_aes_dev *dd = NULL; |
850 | |||
851 | /* Find AES device, currently picks the first device */ | ||
852 | spin_lock_bh(&list_lock); | ||
853 | list_for_each_entry(dd, &dev_list, list) { | ||
854 | break; | ||
855 | } | ||
856 | spin_unlock_bh(&list_lock); | ||
857 | |||
858 | pm_runtime_put_sync(dd->dev); | ||
850 | } | 859 | } |
851 | 860 | ||
852 | /* ********************** ALGS ************************************ */ | 861 | /* ********************** ALGS ************************************ */ |
@@ -1125,10 +1134,9 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
1125 | if (err) | 1134 | if (err) |
1126 | goto err_res; | 1135 | goto err_res; |
1127 | 1136 | ||
1128 | dd->io_base = devm_request_and_ioremap(dev, &res); | 1137 | dd->io_base = devm_ioremap_resource(dev, &res); |
1129 | if (!dd->io_base) { | 1138 | if (IS_ERR(dd->io_base)) { |
1130 | dev_err(dev, "can't ioremap\n"); | 1139 | err = PTR_ERR(dd->io_base); |
1131 | err = -ENOMEM; | ||
1132 | goto err_res; | 1140 | goto err_res; |
1133 | } | 1141 | } |
1134 | dd->phys_base = res.start; | 1142 | dd->phys_base = res.start; |
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index a1e1b4756ee5..4bb67652c200 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c | |||
@@ -1686,10 +1686,9 @@ static int omap_sham_probe(struct platform_device *pdev) | |||
1686 | if (err) | 1686 | if (err) |
1687 | goto res_err; | 1687 | goto res_err; |
1688 | 1688 | ||
1689 | dd->io_base = devm_request_and_ioremap(dev, &res); | 1689 | dd->io_base = devm_ioremap_resource(dev, &res); |
1690 | if (!dd->io_base) { | 1690 | if (IS_ERR(dd->io_base)) { |
1691 | dev_err(dev, "can't ioremap\n"); | 1691 | err = PTR_ERR(dd->io_base); |
1692 | err = -ENOMEM; | ||
1693 | goto res_err; | 1692 | goto res_err; |
1694 | } | 1693 | } |
1695 | dd->phys_base = res.start; | 1694 | dd->phys_base = res.start; |
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c index ac30724d923d..888f7f4a6d3f 100644 --- a/drivers/crypto/picoxcell_crypto.c +++ b/drivers/crypto/picoxcell_crypto.c | |||
@@ -1298,7 +1298,7 @@ static ssize_t spacc_stat_irq_thresh_store(struct device *dev, | |||
1298 | struct spacc_engine *engine = spacc_dev_to_engine(dev); | 1298 | struct spacc_engine *engine = spacc_dev_to_engine(dev); |
1299 | unsigned long thresh; | 1299 | unsigned long thresh; |
1300 | 1300 | ||
1301 | if (strict_strtoul(buf, 0, &thresh)) | 1301 | if (kstrtoul(buf, 0, &thresh)) |
1302 | return -EINVAL; | 1302 | return -EINVAL; |
1303 | 1303 | ||
1304 | thresh = clamp(thresh, 1UL, engine->fifo_sz - 1); | 1304 | thresh = clamp(thresh, 1UL, engine->fifo_sz - 1); |
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 4b314326f48a..cf149b19ff47 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c | |||
@@ -647,7 +647,6 @@ static int s5p_aes_probe(struct platform_device *pdev) | |||
647 | clk_disable(pdata->clk); | 647 | clk_disable(pdata->clk); |
648 | 648 | ||
649 | s5p_dev = NULL; | 649 | s5p_dev = NULL; |
650 | platform_set_drvdata(pdev, NULL); | ||
651 | 650 | ||
652 | return err; | 651 | return err; |
653 | } | 652 | } |
@@ -668,7 +667,6 @@ static int s5p_aes_remove(struct platform_device *pdev) | |||
668 | clk_disable(pdata->clk); | 667 | clk_disable(pdata->clk); |
669 | 668 | ||
670 | s5p_dev = NULL; | 669 | s5p_dev = NULL; |
671 | platform_set_drvdata(pdev, NULL); | ||
672 | 670 | ||
673 | return 0; | 671 | return 0; |
674 | } | 672 | } |
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index 83d79b964d12..a999f537228f 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c | |||
@@ -1629,7 +1629,7 @@ static int ux500_cryp_remove(struct platform_device *pdev) | |||
1629 | 1629 | ||
1630 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1630 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1631 | if (res) | 1631 | if (res) |
1632 | release_mem_region(res->start, res->end - res->start + 1); | 1632 | release_mem_region(res->start, resource_size(res)); |
1633 | 1633 | ||
1634 | kfree(device_data); | 1634 | kfree(device_data); |
1635 | 1635 | ||
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 3215a3cb3de8..6825957c97fb 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -79,25 +79,7 @@ config INTEL_IOP_ADMA | |||
79 | help | 79 | help |
80 | Enable support for the Intel(R) IOP Series RAID engines. | 80 | Enable support for the Intel(R) IOP Series RAID engines. |
81 | 81 | ||
82 | config DW_DMAC | 82 | source "drivers/dma/dw/Kconfig" |
83 | tristate "Synopsys DesignWare AHB DMA support" | ||
84 | depends on GENERIC_HARDIRQS | ||
85 | select DMA_ENGINE | ||
86 | default y if CPU_AT32AP7000 | ||
87 | help | ||
88 | Support the Synopsys DesignWare AHB DMA controller. This | ||
89 | can be integrated in chips such as the Atmel AT32ap7000. | ||
90 | |||
91 | config DW_DMAC_BIG_ENDIAN_IO | ||
92 | bool "Use big endian I/O register access" | ||
93 | default y if AVR32 | ||
94 | depends on DW_DMAC | ||
95 | help | ||
96 | Say yes here to use big endian I/O access when reading and writing | ||
97 | to the DMA controller registers. This is needed on some platforms, | ||
98 | like the Atmel AVR32 architecture. | ||
99 | |||
100 | If unsure, use the default setting. | ||
101 | 83 | ||
102 | config AT_HDMAC | 84 | config AT_HDMAC |
103 | tristate "Atmel AHB DMA support" | 85 | tristate "Atmel AHB DMA support" |
@@ -312,6 +294,12 @@ config MMP_PDMA | |||
312 | help | 294 | help |
313 | Support the MMP PDMA engine for PXA and MMP platfrom. | 295 | Support the MMP PDMA engine for PXA and MMP platfrom. |
314 | 296 | ||
297 | config DMA_JZ4740 | ||
298 | tristate "JZ4740 DMA support" | ||
299 | depends on MACH_JZ4740 | ||
300 | select DMA_ENGINE | ||
301 | select DMA_VIRTUAL_CHANNELS | ||
302 | |||
315 | config DMA_ENGINE | 303 | config DMA_ENGINE |
316 | bool | 304 | bool |
317 | 305 | ||
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index a2b0df591f95..5e0f2ef85614 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile | |||
@@ -15,7 +15,7 @@ obj-$(CONFIG_FSL_DMA) += fsldma.o | |||
15 | obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o | 15 | obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o |
16 | obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/ | 16 | obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/ |
17 | obj-$(CONFIG_MV_XOR) += mv_xor.o | 17 | obj-$(CONFIG_MV_XOR) += mv_xor.o |
18 | obj-$(CONFIG_DW_DMAC) += dw_dmac.o | 18 | obj-$(CONFIG_DW_DMAC_CORE) += dw/ |
19 | obj-$(CONFIG_AT_HDMAC) += at_hdmac.o | 19 | obj-$(CONFIG_AT_HDMAC) += at_hdmac.o |
20 | obj-$(CONFIG_MX3_IPU) += ipu/ | 20 | obj-$(CONFIG_MX3_IPU) += ipu/ |
21 | obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o | 21 | obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o |
@@ -38,3 +38,4 @@ obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o | |||
38 | obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o | 38 | obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o |
39 | obj-$(CONFIG_DMA_OMAP) += omap-dma.o | 39 | obj-$(CONFIG_DMA_OMAP) += omap-dma.o |
40 | obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o | 40 | obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o |
41 | obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o | ||
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 8bad254a498d..06fe45c74de5 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c | |||
@@ -299,8 +299,8 @@ static int pl08x_request_mux(struct pl08x_dma_chan *plchan) | |||
299 | const struct pl08x_platform_data *pd = plchan->host->pd; | 299 | const struct pl08x_platform_data *pd = plchan->host->pd; |
300 | int ret; | 300 | int ret; |
301 | 301 | ||
302 | if (plchan->mux_use++ == 0 && pd->get_signal) { | 302 | if (plchan->mux_use++ == 0 && pd->get_xfer_signal) { |
303 | ret = pd->get_signal(plchan->cd); | 303 | ret = pd->get_xfer_signal(plchan->cd); |
304 | if (ret < 0) { | 304 | if (ret < 0) { |
305 | plchan->mux_use = 0; | 305 | plchan->mux_use = 0; |
306 | return ret; | 306 | return ret; |
@@ -318,8 +318,8 @@ static void pl08x_release_mux(struct pl08x_dma_chan *plchan) | |||
318 | if (plchan->signal >= 0) { | 318 | if (plchan->signal >= 0) { |
319 | WARN_ON(plchan->mux_use == 0); | 319 | WARN_ON(plchan->mux_use == 0); |
320 | 320 | ||
321 | if (--plchan->mux_use == 0 && pd->put_signal) { | 321 | if (--plchan->mux_use == 0 && pd->put_xfer_signal) { |
322 | pd->put_signal(plchan->cd, plchan->signal); | 322 | pd->put_xfer_signal(plchan->cd, plchan->signal); |
323 | plchan->signal = -1; | 323 | plchan->signal = -1; |
324 | } | 324 | } |
325 | } | 325 | } |
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index e923cda930f9..c787f38a186a 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * found on AT91SAM9263. | 14 | * found on AT91SAM9263. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <dt-bindings/dma/at91.h> | ||
17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
18 | #include <linux/dmaengine.h> | 19 | #include <linux/dmaengine.h> |
19 | #include <linux/dma-mapping.h> | 20 | #include <linux/dma-mapping.h> |
@@ -54,6 +55,7 @@ MODULE_PARM_DESC(init_nr_desc_per_channel, | |||
54 | 55 | ||
55 | /* prototypes */ | 56 | /* prototypes */ |
56 | static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx); | 57 | static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx); |
58 | static void atc_issue_pending(struct dma_chan *chan); | ||
57 | 59 | ||
58 | 60 | ||
59 | /*----------------------------------------------------------------------*/ | 61 | /*----------------------------------------------------------------------*/ |
@@ -230,6 +232,95 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first) | |||
230 | vdbg_dump_regs(atchan); | 232 | vdbg_dump_regs(atchan); |
231 | } | 233 | } |
232 | 234 | ||
235 | /* | ||
236 | * atc_get_current_descriptors - | ||
237 | * locate the descriptor which equal to physical address in DSCR | ||
238 | * @atchan: the channel we want to start | ||
239 | * @dscr_addr: physical descriptor address in DSCR | ||
240 | */ | ||
241 | static struct at_desc *atc_get_current_descriptors(struct at_dma_chan *atchan, | ||
242 | u32 dscr_addr) | ||
243 | { | ||
244 | struct at_desc *desc, *_desc, *child, *desc_cur = NULL; | ||
245 | |||
246 | list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) { | ||
247 | if (desc->lli.dscr == dscr_addr) { | ||
248 | desc_cur = desc; | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | list_for_each_entry(child, &desc->tx_list, desc_node) { | ||
253 | if (child->lli.dscr == dscr_addr) { | ||
254 | desc_cur = child; | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | } | ||
259 | |||
260 | return desc_cur; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * atc_get_bytes_left - | ||
265 | * Get the number of bytes residue in dma buffer, | ||
266 | * @chan: the channel we want to start | ||
267 | */ | ||
268 | static int atc_get_bytes_left(struct dma_chan *chan) | ||
269 | { | ||
270 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | ||
271 | struct at_dma *atdma = to_at_dma(chan->device); | ||
272 | int chan_id = atchan->chan_common.chan_id; | ||
273 | struct at_desc *desc_first = atc_first_active(atchan); | ||
274 | struct at_desc *desc_cur; | ||
275 | int ret = 0, count = 0; | ||
276 | |||
277 | /* | ||
278 | * Initialize necessary values in the first time. | ||
279 | * remain_desc record remain desc length. | ||
280 | */ | ||
281 | if (atchan->remain_desc == 0) | ||
282 | /* First descriptor embedds the transaction length */ | ||
283 | atchan->remain_desc = desc_first->len; | ||
284 | |||
285 | /* | ||
286 | * This happens when current descriptor transfer complete. | ||
287 | * The residual buffer size should reduce current descriptor length. | ||
288 | */ | ||
289 | if (unlikely(test_bit(ATC_IS_BTC, &atchan->status))) { | ||
290 | clear_bit(ATC_IS_BTC, &atchan->status); | ||
291 | desc_cur = atc_get_current_descriptors(atchan, | ||
292 | channel_readl(atchan, DSCR)); | ||
293 | if (!desc_cur) { | ||
294 | ret = -EINVAL; | ||
295 | goto out; | ||
296 | } | ||
297 | atchan->remain_desc -= (desc_cur->lli.ctrla & ATC_BTSIZE_MAX) | ||
298 | << (desc_first->tx_width); | ||
299 | if (atchan->remain_desc < 0) { | ||
300 | ret = -EINVAL; | ||
301 | goto out; | ||
302 | } else { | ||
303 | ret = atchan->remain_desc; | ||
304 | } | ||
305 | } else { | ||
306 | /* | ||
307 | * Get residual bytes when current | ||
308 | * descriptor transfer in progress. | ||
309 | */ | ||
310 | count = (channel_readl(atchan, CTRLA) & ATC_BTSIZE_MAX) | ||
311 | << (desc_first->tx_width); | ||
312 | ret = atchan->remain_desc - count; | ||
313 | } | ||
314 | /* | ||
315 | * Check fifo empty. | ||
316 | */ | ||
317 | if (!(dma_readl(atdma, CHSR) & AT_DMA_EMPT(chan_id))) | ||
318 | atc_issue_pending(chan); | ||
319 | |||
320 | out: | ||
321 | return ret; | ||
322 | } | ||
323 | |||
233 | /** | 324 | /** |
234 | * atc_chain_complete - finish work for one transaction chain | 325 | * atc_chain_complete - finish work for one transaction chain |
235 | * @atchan: channel we work on | 326 | * @atchan: channel we work on |
@@ -327,37 +418,6 @@ static void atc_complete_all(struct at_dma_chan *atchan) | |||
327 | } | 418 | } |
328 | 419 | ||
329 | /** | 420 | /** |
330 | * atc_cleanup_descriptors - cleanup up finished descriptors in active_list | ||
331 | * @atchan: channel to be cleaned up | ||
332 | * | ||
333 | * Called with atchan->lock held and bh disabled | ||
334 | */ | ||
335 | static void atc_cleanup_descriptors(struct at_dma_chan *atchan) | ||
336 | { | ||
337 | struct at_desc *desc, *_desc; | ||
338 | struct at_desc *child; | ||
339 | |||
340 | dev_vdbg(chan2dev(&atchan->chan_common), "cleanup descriptors\n"); | ||
341 | |||
342 | list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) { | ||
343 | if (!(desc->lli.ctrla & ATC_DONE)) | ||
344 | /* This one is currently in progress */ | ||
345 | return; | ||
346 | |||
347 | list_for_each_entry(child, &desc->tx_list, desc_node) | ||
348 | if (!(child->lli.ctrla & ATC_DONE)) | ||
349 | /* Currently in progress */ | ||
350 | return; | ||
351 | |||
352 | /* | ||
353 | * No descriptors so far seem to be in progress, i.e. | ||
354 | * this chain must be done. | ||
355 | */ | ||
356 | atc_chain_complete(atchan, desc); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * atc_advance_work - at the end of a transaction, move forward | 421 | * atc_advance_work - at the end of a transaction, move forward |
362 | * @atchan: channel where the transaction ended | 422 | * @atchan: channel where the transaction ended |
363 | * | 423 | * |
@@ -496,6 +556,8 @@ static irqreturn_t at_dma_interrupt(int irq, void *dev_id) | |||
496 | /* Give information to tasklet */ | 556 | /* Give information to tasklet */ |
497 | set_bit(ATC_IS_ERROR, &atchan->status); | 557 | set_bit(ATC_IS_ERROR, &atchan->status); |
498 | } | 558 | } |
559 | if (pending & AT_DMA_BTC(i)) | ||
560 | set_bit(ATC_IS_BTC, &atchan->status); | ||
499 | tasklet_schedule(&atchan->tasklet); | 561 | tasklet_schedule(&atchan->tasklet); |
500 | ret = IRQ_HANDLED; | 562 | ret = IRQ_HANDLED; |
501 | } | 563 | } |
@@ -615,6 +677,7 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
615 | /* First descriptor of the chain embedds additional information */ | 677 | /* First descriptor of the chain embedds additional information */ |
616 | first->txd.cookie = -EBUSY; | 678 | first->txd.cookie = -EBUSY; |
617 | first->len = len; | 679 | first->len = len; |
680 | first->tx_width = src_width; | ||
618 | 681 | ||
619 | /* set end-of-link to the last link descriptor of list*/ | 682 | /* set end-of-link to the last link descriptor of list*/ |
620 | set_desc_eol(desc); | 683 | set_desc_eol(desc); |
@@ -761,6 +824,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
761 | /* First descriptor of the chain embedds additional information */ | 824 | /* First descriptor of the chain embedds additional information */ |
762 | first->txd.cookie = -EBUSY; | 825 | first->txd.cookie = -EBUSY; |
763 | first->len = total_len; | 826 | first->len = total_len; |
827 | first->tx_width = reg_width; | ||
764 | 828 | ||
765 | /* first link descriptor of list is responsible of flags */ | 829 | /* first link descriptor of list is responsible of flags */ |
766 | first->txd.flags = flags; /* client is in control of this ack */ | 830 | first->txd.flags = flags; /* client is in control of this ack */ |
@@ -919,6 +983,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | |||
919 | /* First descriptor of the chain embedds additional information */ | 983 | /* First descriptor of the chain embedds additional information */ |
920 | first->txd.cookie = -EBUSY; | 984 | first->txd.cookie = -EBUSY; |
921 | first->len = buf_len; | 985 | first->len = buf_len; |
986 | first->tx_width = reg_width; | ||
922 | 987 | ||
923 | return &first->txd; | 988 | return &first->txd; |
924 | 989 | ||
@@ -1032,34 +1097,36 @@ atc_tx_status(struct dma_chan *chan, | |||
1032 | struct dma_tx_state *txstate) | 1097 | struct dma_tx_state *txstate) |
1033 | { | 1098 | { |
1034 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 1099 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
1035 | dma_cookie_t last_used; | ||
1036 | dma_cookie_t last_complete; | ||
1037 | unsigned long flags; | 1100 | unsigned long flags; |
1038 | enum dma_status ret; | 1101 | enum dma_status ret; |
1039 | 1102 | int bytes = 0; | |
1040 | spin_lock_irqsave(&atchan->lock, flags); | ||
1041 | 1103 | ||
1042 | ret = dma_cookie_status(chan, cookie, txstate); | 1104 | ret = dma_cookie_status(chan, cookie, txstate); |
1043 | if (ret != DMA_SUCCESS) { | 1105 | if (ret == DMA_SUCCESS) |
1044 | atc_cleanup_descriptors(atchan); | 1106 | return ret; |
1107 | /* | ||
1108 | * There's no point calculating the residue if there's | ||
1109 | * no txstate to store the value. | ||
1110 | */ | ||
1111 | if (!txstate) | ||
1112 | return DMA_ERROR; | ||
1045 | 1113 | ||
1046 | ret = dma_cookie_status(chan, cookie, txstate); | 1114 | spin_lock_irqsave(&atchan->lock, flags); |
1047 | } | ||
1048 | 1115 | ||
1049 | last_complete = chan->completed_cookie; | 1116 | /* Get number of bytes left in the active transactions */ |
1050 | last_used = chan->cookie; | 1117 | bytes = atc_get_bytes_left(chan); |
1051 | 1118 | ||
1052 | spin_unlock_irqrestore(&atchan->lock, flags); | 1119 | spin_unlock_irqrestore(&atchan->lock, flags); |
1053 | 1120 | ||
1054 | if (ret != DMA_SUCCESS) | 1121 | if (unlikely(bytes < 0)) { |
1055 | dma_set_residue(txstate, atc_first_active(atchan)->len); | 1122 | dev_vdbg(chan2dev(chan), "get residual bytes error\n"); |
1056 | 1123 | return DMA_ERROR; | |
1057 | if (atc_chan_is_paused(atchan)) | 1124 | } else { |
1058 | ret = DMA_PAUSED; | 1125 | dma_set_residue(txstate, bytes); |
1126 | } | ||
1059 | 1127 | ||
1060 | dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n", | 1128 | dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d residue = %d\n", |
1061 | ret, cookie, last_complete ? last_complete : 0, | 1129 | ret, cookie, bytes); |
1062 | last_used ? last_used : 0); | ||
1063 | 1130 | ||
1064 | return ret; | 1131 | return ret; |
1065 | } | 1132 | } |
@@ -1120,7 +1187,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) | |||
1120 | */ | 1187 | */ |
1121 | BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_common.dev); | 1188 | BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_common.dev); |
1122 | 1189 | ||
1123 | /* if cfg configuration specified take it instad of default */ | 1190 | /* if cfg configuration specified take it instead of default */ |
1124 | if (atslave->cfg) | 1191 | if (atslave->cfg) |
1125 | cfg = atslave->cfg; | 1192 | cfg = atslave->cfg; |
1126 | } | 1193 | } |
@@ -1143,6 +1210,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) | |||
1143 | 1210 | ||
1144 | spin_lock_irqsave(&atchan->lock, flags); | 1211 | spin_lock_irqsave(&atchan->lock, flags); |
1145 | atchan->descs_allocated = i; | 1212 | atchan->descs_allocated = i; |
1213 | atchan->remain_desc = 0; | ||
1146 | list_splice(&tmp_list, &atchan->free_list); | 1214 | list_splice(&tmp_list, &atchan->free_list); |
1147 | dma_cookie_init(chan); | 1215 | dma_cookie_init(chan); |
1148 | spin_unlock_irqrestore(&atchan->lock, flags); | 1216 | spin_unlock_irqrestore(&atchan->lock, flags); |
@@ -1185,6 +1253,7 @@ static void atc_free_chan_resources(struct dma_chan *chan) | |||
1185 | list_splice_init(&atchan->free_list, &list); | 1253 | list_splice_init(&atchan->free_list, &list); |
1186 | atchan->descs_allocated = 0; | 1254 | atchan->descs_allocated = 0; |
1187 | atchan->status = 0; | 1255 | atchan->status = 0; |
1256 | atchan->remain_desc = 0; | ||
1188 | 1257 | ||
1189 | dev_vdbg(chan2dev(chan), "free_chan_resources: done\n"); | 1258 | dev_vdbg(chan2dev(chan), "free_chan_resources: done\n"); |
1190 | } | 1259 | } |
@@ -1223,14 +1292,31 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec, | |||
1223 | atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL); | 1292 | atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL); |
1224 | if (!atslave) | 1293 | if (!atslave) |
1225 | return NULL; | 1294 | return NULL; |
1295 | |||
1296 | atslave->cfg = ATC_DST_H2SEL_HW | ATC_SRC_H2SEL_HW; | ||
1226 | /* | 1297 | /* |
1227 | * We can fill both SRC_PER and DST_PER, one of these fields will be | 1298 | * We can fill both SRC_PER and DST_PER, one of these fields will be |
1228 | * ignored depending on DMA transfer direction. | 1299 | * ignored depending on DMA transfer direction. |
1229 | */ | 1300 | */ |
1230 | per_id = dma_spec->args[1]; | 1301 | per_id = dma_spec->args[1] & AT91_DMA_CFG_PER_ID_MASK; |
1231 | atslave->cfg = ATC_FIFOCFG_HALFFIFO | ATC_DST_H2SEL_HW | 1302 | atslave->cfg |= ATC_DST_PER_MSB(per_id) | ATC_DST_PER(per_id) |
1232 | | ATC_SRC_H2SEL_HW | ATC_DST_PER(per_id) | 1303 | | ATC_SRC_PER_MSB(per_id) | ATC_SRC_PER(per_id); |
1233 | | ATC_SRC_PER(per_id); | 1304 | /* |
1305 | * We have to translate the value we get from the device tree since | ||
1306 | * the half FIFO configuration value had to be 0 to keep backward | ||
1307 | * compatibility. | ||
1308 | */ | ||
1309 | switch (dma_spec->args[1] & AT91_DMA_CFG_FIFOCFG_MASK) { | ||
1310 | case AT91_DMA_CFG_FIFOCFG_ALAP: | ||
1311 | atslave->cfg |= ATC_FIFOCFG_LARGESTBURST; | ||
1312 | break; | ||
1313 | case AT91_DMA_CFG_FIFOCFG_ASAP: | ||
1314 | atslave->cfg |= ATC_FIFOCFG_ENOUGHSPACE; | ||
1315 | break; | ||
1316 | case AT91_DMA_CFG_FIFOCFG_HALF: | ||
1317 | default: | ||
1318 | atslave->cfg |= ATC_FIFOCFG_HALFFIFO; | ||
1319 | } | ||
1234 | atslave->dma_dev = &dmac_pdev->dev; | 1320 | atslave->dma_dev = &dmac_pdev->dev; |
1235 | 1321 | ||
1236 | chan = dma_request_channel(mask, at_dma_filter, atslave); | 1322 | chan = dma_request_channel(mask, at_dma_filter, atslave); |
@@ -1374,7 +1460,9 @@ static int __init at_dma_probe(struct platform_device *pdev) | |||
1374 | err = PTR_ERR(atdma->clk); | 1460 | err = PTR_ERR(atdma->clk); |
1375 | goto err_clk; | 1461 | goto err_clk; |
1376 | } | 1462 | } |
1377 | clk_enable(atdma->clk); | 1463 | err = clk_prepare_enable(atdma->clk); |
1464 | if (err) | ||
1465 | goto err_clk_prepare; | ||
1378 | 1466 | ||
1379 | /* force dma off, just in case */ | 1467 | /* force dma off, just in case */ |
1380 | at_dma_off(atdma); | 1468 | at_dma_off(atdma); |
@@ -1472,10 +1560,10 @@ err_of_dma_controller_register: | |||
1472 | dma_async_device_unregister(&atdma->dma_common); | 1560 | dma_async_device_unregister(&atdma->dma_common); |
1473 | dma_pool_destroy(atdma->dma_desc_pool); | 1561 | dma_pool_destroy(atdma->dma_desc_pool); |
1474 | err_pool_create: | 1562 | err_pool_create: |
1475 | platform_set_drvdata(pdev, NULL); | ||
1476 | free_irq(platform_get_irq(pdev, 0), atdma); | 1563 | free_irq(platform_get_irq(pdev, 0), atdma); |
1477 | err_irq: | 1564 | err_irq: |
1478 | clk_disable(atdma->clk); | 1565 | clk_disable_unprepare(atdma->clk); |
1566 | err_clk_prepare: | ||
1479 | clk_put(atdma->clk); | 1567 | clk_put(atdma->clk); |
1480 | err_clk: | 1568 | err_clk: |
1481 | iounmap(atdma->regs); | 1569 | iounmap(atdma->regs); |
@@ -1497,7 +1585,6 @@ static int at_dma_remove(struct platform_device *pdev) | |||
1497 | dma_async_device_unregister(&atdma->dma_common); | 1585 | dma_async_device_unregister(&atdma->dma_common); |
1498 | 1586 | ||
1499 | dma_pool_destroy(atdma->dma_desc_pool); | 1587 | dma_pool_destroy(atdma->dma_desc_pool); |
1500 | platform_set_drvdata(pdev, NULL); | ||
1501 | free_irq(platform_get_irq(pdev, 0), atdma); | 1588 | free_irq(platform_get_irq(pdev, 0), atdma); |
1502 | 1589 | ||
1503 | list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels, | 1590 | list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels, |
@@ -1512,7 +1599,7 @@ static int at_dma_remove(struct platform_device *pdev) | |||
1512 | list_del(&chan->device_node); | 1599 | list_del(&chan->device_node); |
1513 | } | 1600 | } |
1514 | 1601 | ||
1515 | clk_disable(atdma->clk); | 1602 | clk_disable_unprepare(atdma->clk); |
1516 | clk_put(atdma->clk); | 1603 | clk_put(atdma->clk); |
1517 | 1604 | ||
1518 | iounmap(atdma->regs); | 1605 | iounmap(atdma->regs); |
@@ -1531,7 +1618,7 @@ static void at_dma_shutdown(struct platform_device *pdev) | |||
1531 | struct at_dma *atdma = platform_get_drvdata(pdev); | 1618 | struct at_dma *atdma = platform_get_drvdata(pdev); |
1532 | 1619 | ||
1533 | at_dma_off(platform_get_drvdata(pdev)); | 1620 | at_dma_off(platform_get_drvdata(pdev)); |
1534 | clk_disable(atdma->clk); | 1621 | clk_disable_unprepare(atdma->clk); |
1535 | } | 1622 | } |
1536 | 1623 | ||
1537 | static int at_dma_prepare(struct device *dev) | 1624 | static int at_dma_prepare(struct device *dev) |
@@ -1588,7 +1675,7 @@ static int at_dma_suspend_noirq(struct device *dev) | |||
1588 | 1675 | ||
1589 | /* disable DMA controller */ | 1676 | /* disable DMA controller */ |
1590 | at_dma_off(atdma); | 1677 | at_dma_off(atdma); |
1591 | clk_disable(atdma->clk); | 1678 | clk_disable_unprepare(atdma->clk); |
1592 | return 0; | 1679 | return 0; |
1593 | } | 1680 | } |
1594 | 1681 | ||
@@ -1618,7 +1705,7 @@ static int at_dma_resume_noirq(struct device *dev) | |||
1618 | struct dma_chan *chan, *_chan; | 1705 | struct dma_chan *chan, *_chan; |
1619 | 1706 | ||
1620 | /* bring back DMA controller */ | 1707 | /* bring back DMA controller */ |
1621 | clk_enable(atdma->clk); | 1708 | clk_prepare_enable(atdma->clk); |
1622 | dma_writel(atdma, EN, AT_DMA_ENABLE); | 1709 | dma_writel(atdma, EN, AT_DMA_ENABLE); |
1623 | 1710 | ||
1624 | /* clear any pending interrupt */ | 1711 | /* clear any pending interrupt */ |
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index c604d26fd4d3..f31d647acdfa 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h | |||
@@ -182,6 +182,7 @@ struct at_lli { | |||
182 | * @txd: support for the async_tx api | 182 | * @txd: support for the async_tx api |
183 | * @desc_node: node on the channed descriptors list | 183 | * @desc_node: node on the channed descriptors list |
184 | * @len: total transaction bytecount | 184 | * @len: total transaction bytecount |
185 | * @tx_width: transfer width | ||
185 | */ | 186 | */ |
186 | struct at_desc { | 187 | struct at_desc { |
187 | /* FIRST values the hardware uses */ | 188 | /* FIRST values the hardware uses */ |
@@ -192,6 +193,7 @@ struct at_desc { | |||
192 | struct dma_async_tx_descriptor txd; | 193 | struct dma_async_tx_descriptor txd; |
193 | struct list_head desc_node; | 194 | struct list_head desc_node; |
194 | size_t len; | 195 | size_t len; |
196 | u32 tx_width; | ||
195 | }; | 197 | }; |
196 | 198 | ||
197 | static inline struct at_desc * | 199 | static inline struct at_desc * |
@@ -211,6 +213,7 @@ txd_to_at_desc(struct dma_async_tx_descriptor *txd) | |||
211 | enum atc_status { | 213 | enum atc_status { |
212 | ATC_IS_ERROR = 0, | 214 | ATC_IS_ERROR = 0, |
213 | ATC_IS_PAUSED = 1, | 215 | ATC_IS_PAUSED = 1, |
216 | ATC_IS_BTC = 2, | ||
214 | ATC_IS_CYCLIC = 24, | 217 | ATC_IS_CYCLIC = 24, |
215 | }; | 218 | }; |
216 | 219 | ||
@@ -228,6 +231,7 @@ enum atc_status { | |||
228 | * @save_cfg: configuration register that is saved on suspend/resume cycle | 231 | * @save_cfg: configuration register that is saved on suspend/resume cycle |
229 | * @save_dscr: for cyclic operations, preserve next descriptor address in | 232 | * @save_dscr: for cyclic operations, preserve next descriptor address in |
230 | * the cyclic list on suspend/resume cycle | 233 | * the cyclic list on suspend/resume cycle |
234 | * @remain_desc: to save remain desc length | ||
231 | * @dma_sconfig: configuration for slave transfers, passed via DMA_SLAVE_CONFIG | 235 | * @dma_sconfig: configuration for slave transfers, passed via DMA_SLAVE_CONFIG |
232 | * @lock: serializes enqueue/dequeue operations to descriptors lists | 236 | * @lock: serializes enqueue/dequeue operations to descriptors lists |
233 | * @active_list: list of descriptors dmaengine is being running on | 237 | * @active_list: list of descriptors dmaengine is being running on |
@@ -246,6 +250,7 @@ struct at_dma_chan { | |||
246 | struct tasklet_struct tasklet; | 250 | struct tasklet_struct tasklet; |
247 | u32 save_cfg; | 251 | u32 save_cfg; |
248 | u32 save_dscr; | 252 | u32 save_dscr; |
253 | u32 remain_desc; | ||
249 | struct dma_slave_config dma_sconfig; | 254 | struct dma_slave_config dma_sconfig; |
250 | 255 | ||
251 | spinlock_t lock; | 256 | spinlock_t lock; |
diff --git a/drivers/dma/dma-jz4740.c b/drivers/dma/dma-jz4740.c new file mode 100644 index 000000000000..b0c0c8268d42 --- /dev/null +++ b/drivers/dma/dma-jz4740.c | |||
@@ -0,0 +1,617 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 DMAC support | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/dmaengine.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/list.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/clk.h> | ||
27 | |||
28 | #include <asm/mach-jz4740/dma.h> | ||
29 | |||
30 | #include "virt-dma.h" | ||
31 | |||
32 | #define JZ_DMA_NR_CHANS 6 | ||
33 | |||
34 | #define JZ_REG_DMA_SRC_ADDR(x) (0x00 + (x) * 0x20) | ||
35 | #define JZ_REG_DMA_DST_ADDR(x) (0x04 + (x) * 0x20) | ||
36 | #define JZ_REG_DMA_TRANSFER_COUNT(x) (0x08 + (x) * 0x20) | ||
37 | #define JZ_REG_DMA_REQ_TYPE(x) (0x0C + (x) * 0x20) | ||
38 | #define JZ_REG_DMA_STATUS_CTRL(x) (0x10 + (x) * 0x20) | ||
39 | #define JZ_REG_DMA_CMD(x) (0x14 + (x) * 0x20) | ||
40 | #define JZ_REG_DMA_DESC_ADDR(x) (0x18 + (x) * 0x20) | ||
41 | |||
42 | #define JZ_REG_DMA_CTRL 0x300 | ||
43 | #define JZ_REG_DMA_IRQ 0x304 | ||
44 | #define JZ_REG_DMA_DOORBELL 0x308 | ||
45 | #define JZ_REG_DMA_DOORBELL_SET 0x30C | ||
46 | |||
47 | #define JZ_DMA_STATUS_CTRL_NO_DESC BIT(31) | ||
48 | #define JZ_DMA_STATUS_CTRL_DESC_INV BIT(6) | ||
49 | #define JZ_DMA_STATUS_CTRL_ADDR_ERR BIT(4) | ||
50 | #define JZ_DMA_STATUS_CTRL_TRANSFER_DONE BIT(3) | ||
51 | #define JZ_DMA_STATUS_CTRL_HALT BIT(2) | ||
52 | #define JZ_DMA_STATUS_CTRL_COUNT_TERMINATE BIT(1) | ||
53 | #define JZ_DMA_STATUS_CTRL_ENABLE BIT(0) | ||
54 | |||
55 | #define JZ_DMA_CMD_SRC_INC BIT(23) | ||
56 | #define JZ_DMA_CMD_DST_INC BIT(22) | ||
57 | #define JZ_DMA_CMD_RDIL_MASK (0xf << 16) | ||
58 | #define JZ_DMA_CMD_SRC_WIDTH_MASK (0x3 << 14) | ||
59 | #define JZ_DMA_CMD_DST_WIDTH_MASK (0x3 << 12) | ||
60 | #define JZ_DMA_CMD_INTERVAL_LENGTH_MASK (0x7 << 8) | ||
61 | #define JZ_DMA_CMD_BLOCK_MODE BIT(7) | ||
62 | #define JZ_DMA_CMD_DESC_VALID BIT(4) | ||
63 | #define JZ_DMA_CMD_DESC_VALID_MODE BIT(3) | ||
64 | #define JZ_DMA_CMD_VALID_IRQ_ENABLE BIT(2) | ||
65 | #define JZ_DMA_CMD_TRANSFER_IRQ_ENABLE BIT(1) | ||
66 | #define JZ_DMA_CMD_LINK_ENABLE BIT(0) | ||
67 | |||
68 | #define JZ_DMA_CMD_FLAGS_OFFSET 22 | ||
69 | #define JZ_DMA_CMD_RDIL_OFFSET 16 | ||
70 | #define JZ_DMA_CMD_SRC_WIDTH_OFFSET 14 | ||
71 | #define JZ_DMA_CMD_DST_WIDTH_OFFSET 12 | ||
72 | #define JZ_DMA_CMD_TRANSFER_SIZE_OFFSET 8 | ||
73 | #define JZ_DMA_CMD_MODE_OFFSET 7 | ||
74 | |||
75 | #define JZ_DMA_CTRL_PRIORITY_MASK (0x3 << 8) | ||
76 | #define JZ_DMA_CTRL_HALT BIT(3) | ||
77 | #define JZ_DMA_CTRL_ADDRESS_ERROR BIT(2) | ||
78 | #define JZ_DMA_CTRL_ENABLE BIT(0) | ||
79 | |||
80 | enum jz4740_dma_width { | ||
81 | JZ4740_DMA_WIDTH_32BIT = 0, | ||
82 | JZ4740_DMA_WIDTH_8BIT = 1, | ||
83 | JZ4740_DMA_WIDTH_16BIT = 2, | ||
84 | }; | ||
85 | |||
86 | enum jz4740_dma_transfer_size { | ||
87 | JZ4740_DMA_TRANSFER_SIZE_4BYTE = 0, | ||
88 | JZ4740_DMA_TRANSFER_SIZE_1BYTE = 1, | ||
89 | JZ4740_DMA_TRANSFER_SIZE_2BYTE = 2, | ||
90 | JZ4740_DMA_TRANSFER_SIZE_16BYTE = 3, | ||
91 | JZ4740_DMA_TRANSFER_SIZE_32BYTE = 4, | ||
92 | }; | ||
93 | |||
94 | enum jz4740_dma_flags { | ||
95 | JZ4740_DMA_SRC_AUTOINC = 0x2, | ||
96 | JZ4740_DMA_DST_AUTOINC = 0x1, | ||
97 | }; | ||
98 | |||
99 | enum jz4740_dma_mode { | ||
100 | JZ4740_DMA_MODE_SINGLE = 0, | ||
101 | JZ4740_DMA_MODE_BLOCK = 1, | ||
102 | }; | ||
103 | |||
104 | struct jz4740_dma_sg { | ||
105 | dma_addr_t addr; | ||
106 | unsigned int len; | ||
107 | }; | ||
108 | |||
109 | struct jz4740_dma_desc { | ||
110 | struct virt_dma_desc vdesc; | ||
111 | |||
112 | enum dma_transfer_direction direction; | ||
113 | bool cyclic; | ||
114 | |||
115 | unsigned int num_sgs; | ||
116 | struct jz4740_dma_sg sg[]; | ||
117 | }; | ||
118 | |||
119 | struct jz4740_dmaengine_chan { | ||
120 | struct virt_dma_chan vchan; | ||
121 | unsigned int id; | ||
122 | |||
123 | dma_addr_t fifo_addr; | ||
124 | unsigned int transfer_shift; | ||
125 | |||
126 | struct jz4740_dma_desc *desc; | ||
127 | unsigned int next_sg; | ||
128 | }; | ||
129 | |||
130 | struct jz4740_dma_dev { | ||
131 | struct dma_device ddev; | ||
132 | void __iomem *base; | ||
133 | struct clk *clk; | ||
134 | |||
135 | struct jz4740_dmaengine_chan chan[JZ_DMA_NR_CHANS]; | ||
136 | }; | ||
137 | |||
138 | static struct jz4740_dma_dev *jz4740_dma_chan_get_dev( | ||
139 | struct jz4740_dmaengine_chan *chan) | ||
140 | { | ||
141 | return container_of(chan->vchan.chan.device, struct jz4740_dma_dev, | ||
142 | ddev); | ||
143 | } | ||
144 | |||
145 | static struct jz4740_dmaengine_chan *to_jz4740_dma_chan(struct dma_chan *c) | ||
146 | { | ||
147 | return container_of(c, struct jz4740_dmaengine_chan, vchan.chan); | ||
148 | } | ||
149 | |||
150 | static struct jz4740_dma_desc *to_jz4740_dma_desc(struct virt_dma_desc *vdesc) | ||
151 | { | ||
152 | return container_of(vdesc, struct jz4740_dma_desc, vdesc); | ||
153 | } | ||
154 | |||
155 | static inline uint32_t jz4740_dma_read(struct jz4740_dma_dev *dmadev, | ||
156 | unsigned int reg) | ||
157 | { | ||
158 | return readl(dmadev->base + reg); | ||
159 | } | ||
160 | |||
161 | static inline void jz4740_dma_write(struct jz4740_dma_dev *dmadev, | ||
162 | unsigned reg, uint32_t val) | ||
163 | { | ||
164 | writel(val, dmadev->base + reg); | ||
165 | } | ||
166 | |||
167 | static inline void jz4740_dma_write_mask(struct jz4740_dma_dev *dmadev, | ||
168 | unsigned int reg, uint32_t val, uint32_t mask) | ||
169 | { | ||
170 | uint32_t tmp; | ||
171 | |||
172 | tmp = jz4740_dma_read(dmadev, reg); | ||
173 | tmp &= ~mask; | ||
174 | tmp |= val; | ||
175 | jz4740_dma_write(dmadev, reg, tmp); | ||
176 | } | ||
177 | |||
178 | static struct jz4740_dma_desc *jz4740_dma_alloc_desc(unsigned int num_sgs) | ||
179 | { | ||
180 | return kzalloc(sizeof(struct jz4740_dma_desc) + | ||
181 | sizeof(struct jz4740_dma_sg) * num_sgs, GFP_ATOMIC); | ||
182 | } | ||
183 | |||
184 | static enum jz4740_dma_width jz4740_dma_width(enum dma_slave_buswidth width) | ||
185 | { | ||
186 | switch (width) { | ||
187 | case DMA_SLAVE_BUSWIDTH_1_BYTE: | ||
188 | return JZ4740_DMA_WIDTH_8BIT; | ||
189 | case DMA_SLAVE_BUSWIDTH_2_BYTES: | ||
190 | return JZ4740_DMA_WIDTH_16BIT; | ||
191 | case DMA_SLAVE_BUSWIDTH_4_BYTES: | ||
192 | return JZ4740_DMA_WIDTH_32BIT; | ||
193 | default: | ||
194 | return JZ4740_DMA_WIDTH_32BIT; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | static enum jz4740_dma_transfer_size jz4740_dma_maxburst(u32 maxburst) | ||
199 | { | ||
200 | if (maxburst <= 1) | ||
201 | return JZ4740_DMA_TRANSFER_SIZE_1BYTE; | ||
202 | else if (maxburst <= 3) | ||
203 | return JZ4740_DMA_TRANSFER_SIZE_2BYTE; | ||
204 | else if (maxburst <= 15) | ||
205 | return JZ4740_DMA_TRANSFER_SIZE_4BYTE; | ||
206 | else if (maxburst <= 31) | ||
207 | return JZ4740_DMA_TRANSFER_SIZE_16BYTE; | ||
208 | |||
209 | return JZ4740_DMA_TRANSFER_SIZE_32BYTE; | ||
210 | } | ||
211 | |||
212 | static int jz4740_dma_slave_config(struct dma_chan *c, | ||
213 | const struct dma_slave_config *config) | ||
214 | { | ||
215 | struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); | ||
216 | struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); | ||
217 | enum jz4740_dma_width src_width; | ||
218 | enum jz4740_dma_width dst_width; | ||
219 | enum jz4740_dma_transfer_size transfer_size; | ||
220 | enum jz4740_dma_flags flags; | ||
221 | uint32_t cmd; | ||
222 | |||
223 | switch (config->direction) { | ||
224 | case DMA_MEM_TO_DEV: | ||
225 | flags = JZ4740_DMA_SRC_AUTOINC; | ||
226 | transfer_size = jz4740_dma_maxburst(config->dst_maxburst); | ||
227 | chan->fifo_addr = config->dst_addr; | ||
228 | break; | ||
229 | case DMA_DEV_TO_MEM: | ||
230 | flags = JZ4740_DMA_DST_AUTOINC; | ||
231 | transfer_size = jz4740_dma_maxburst(config->src_maxburst); | ||
232 | chan->fifo_addr = config->src_addr; | ||
233 | break; | ||
234 | default: | ||
235 | return -EINVAL; | ||
236 | } | ||
237 | |||
238 | src_width = jz4740_dma_width(config->src_addr_width); | ||
239 | dst_width = jz4740_dma_width(config->dst_addr_width); | ||
240 | |||
241 | switch (transfer_size) { | ||
242 | case JZ4740_DMA_TRANSFER_SIZE_2BYTE: | ||
243 | chan->transfer_shift = 1; | ||
244 | break; | ||
245 | case JZ4740_DMA_TRANSFER_SIZE_4BYTE: | ||
246 | chan->transfer_shift = 2; | ||
247 | break; | ||
248 | case JZ4740_DMA_TRANSFER_SIZE_16BYTE: | ||
249 | chan->transfer_shift = 4; | ||
250 | break; | ||
251 | case JZ4740_DMA_TRANSFER_SIZE_32BYTE: | ||
252 | chan->transfer_shift = 5; | ||
253 | break; | ||
254 | default: | ||
255 | chan->transfer_shift = 0; | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | cmd = flags << JZ_DMA_CMD_FLAGS_OFFSET; | ||
260 | cmd |= src_width << JZ_DMA_CMD_SRC_WIDTH_OFFSET; | ||
261 | cmd |= dst_width << JZ_DMA_CMD_DST_WIDTH_OFFSET; | ||
262 | cmd |= transfer_size << JZ_DMA_CMD_TRANSFER_SIZE_OFFSET; | ||
263 | cmd |= JZ4740_DMA_MODE_SINGLE << JZ_DMA_CMD_MODE_OFFSET; | ||
264 | cmd |= JZ_DMA_CMD_TRANSFER_IRQ_ENABLE; | ||
265 | |||
266 | jz4740_dma_write(dmadev, JZ_REG_DMA_CMD(chan->id), cmd); | ||
267 | jz4740_dma_write(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0); | ||
268 | jz4740_dma_write(dmadev, JZ_REG_DMA_REQ_TYPE(chan->id), | ||
269 | config->slave_id); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int jz4740_dma_terminate_all(struct dma_chan *c) | ||
275 | { | ||
276 | struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); | ||
277 | struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); | ||
278 | unsigned long flags; | ||
279 | LIST_HEAD(head); | ||
280 | |||
281 | spin_lock_irqsave(&chan->vchan.lock, flags); | ||
282 | jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0, | ||
283 | JZ_DMA_STATUS_CTRL_ENABLE); | ||
284 | chan->desc = NULL; | ||
285 | vchan_get_all_descriptors(&chan->vchan, &head); | ||
286 | spin_unlock_irqrestore(&chan->vchan.lock, flags); | ||
287 | |||
288 | vchan_dma_desc_free_list(&chan->vchan, &head); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int jz4740_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | ||
294 | unsigned long arg) | ||
295 | { | ||
296 | struct dma_slave_config *config = (struct dma_slave_config *)arg; | ||
297 | |||
298 | switch (cmd) { | ||
299 | case DMA_SLAVE_CONFIG: | ||
300 | return jz4740_dma_slave_config(chan, config); | ||
301 | case DMA_TERMINATE_ALL: | ||
302 | return jz4740_dma_terminate_all(chan); | ||
303 | default: | ||
304 | return -ENOSYS; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | static int jz4740_dma_start_transfer(struct jz4740_dmaengine_chan *chan) | ||
309 | { | ||
310 | struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); | ||
311 | dma_addr_t src_addr, dst_addr; | ||
312 | struct virt_dma_desc *vdesc; | ||
313 | struct jz4740_dma_sg *sg; | ||
314 | |||
315 | jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), 0, | ||
316 | JZ_DMA_STATUS_CTRL_ENABLE); | ||
317 | |||
318 | if (!chan->desc) { | ||
319 | vdesc = vchan_next_desc(&chan->vchan); | ||
320 | if (!vdesc) | ||
321 | return 0; | ||
322 | chan->desc = to_jz4740_dma_desc(vdesc); | ||
323 | chan->next_sg = 0; | ||
324 | } | ||
325 | |||
326 | if (chan->next_sg == chan->desc->num_sgs) | ||
327 | chan->next_sg = 0; | ||
328 | |||
329 | sg = &chan->desc->sg[chan->next_sg]; | ||
330 | |||
331 | if (chan->desc->direction == DMA_MEM_TO_DEV) { | ||
332 | src_addr = sg->addr; | ||
333 | dst_addr = chan->fifo_addr; | ||
334 | } else { | ||
335 | src_addr = chan->fifo_addr; | ||
336 | dst_addr = sg->addr; | ||
337 | } | ||
338 | jz4740_dma_write(dmadev, JZ_REG_DMA_SRC_ADDR(chan->id), src_addr); | ||
339 | jz4740_dma_write(dmadev, JZ_REG_DMA_DST_ADDR(chan->id), dst_addr); | ||
340 | jz4740_dma_write(dmadev, JZ_REG_DMA_TRANSFER_COUNT(chan->id), | ||
341 | sg->len >> chan->transfer_shift); | ||
342 | |||
343 | chan->next_sg++; | ||
344 | |||
345 | jz4740_dma_write_mask(dmadev, JZ_REG_DMA_STATUS_CTRL(chan->id), | ||
346 | JZ_DMA_STATUS_CTRL_NO_DESC | JZ_DMA_STATUS_CTRL_ENABLE, | ||
347 | JZ_DMA_STATUS_CTRL_HALT | JZ_DMA_STATUS_CTRL_NO_DESC | | ||
348 | JZ_DMA_STATUS_CTRL_ENABLE); | ||
349 | |||
350 | jz4740_dma_write_mask(dmadev, JZ_REG_DMA_CTRL, | ||
351 | JZ_DMA_CTRL_ENABLE, | ||
352 | JZ_DMA_CTRL_HALT | JZ_DMA_CTRL_ENABLE); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan) | ||
358 | { | ||
359 | spin_lock(&chan->vchan.lock); | ||
360 | if (chan->desc) { | ||
361 | if (chan->desc && chan->desc->cyclic) { | ||
362 | vchan_cyclic_callback(&chan->desc->vdesc); | ||
363 | } else { | ||
364 | if (chan->next_sg == chan->desc->num_sgs) { | ||
365 | chan->desc = NULL; | ||
366 | vchan_cookie_complete(&chan->desc->vdesc); | ||
367 | } | ||
368 | } | ||
369 | } | ||
370 | jz4740_dma_start_transfer(chan); | ||
371 | spin_unlock(&chan->vchan.lock); | ||
372 | } | ||
373 | |||
374 | static irqreturn_t jz4740_dma_irq(int irq, void *devid) | ||
375 | { | ||
376 | struct jz4740_dma_dev *dmadev = devid; | ||
377 | uint32_t irq_status; | ||
378 | unsigned int i; | ||
379 | |||
380 | irq_status = readl(dmadev->base + JZ_REG_DMA_IRQ); | ||
381 | |||
382 | for (i = 0; i < 6; ++i) { | ||
383 | if (irq_status & (1 << i)) { | ||
384 | jz4740_dma_write_mask(dmadev, | ||
385 | JZ_REG_DMA_STATUS_CTRL(i), 0, | ||
386 | JZ_DMA_STATUS_CTRL_ENABLE | | ||
387 | JZ_DMA_STATUS_CTRL_TRANSFER_DONE); | ||
388 | |||
389 | jz4740_dma_chan_irq(&dmadev->chan[i]); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | return IRQ_HANDLED; | ||
394 | } | ||
395 | |||
396 | static void jz4740_dma_issue_pending(struct dma_chan *c) | ||
397 | { | ||
398 | struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); | ||
399 | unsigned long flags; | ||
400 | |||
401 | spin_lock_irqsave(&chan->vchan.lock, flags); | ||
402 | if (vchan_issue_pending(&chan->vchan) && !chan->desc) | ||
403 | jz4740_dma_start_transfer(chan); | ||
404 | spin_unlock_irqrestore(&chan->vchan.lock, flags); | ||
405 | } | ||
406 | |||
407 | static struct dma_async_tx_descriptor *jz4740_dma_prep_slave_sg( | ||
408 | struct dma_chan *c, struct scatterlist *sgl, | ||
409 | unsigned int sg_len, enum dma_transfer_direction direction, | ||
410 | unsigned long flags, void *context) | ||
411 | { | ||
412 | struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); | ||
413 | struct jz4740_dma_desc *desc; | ||
414 | struct scatterlist *sg; | ||
415 | unsigned int i; | ||
416 | |||
417 | desc = jz4740_dma_alloc_desc(sg_len); | ||
418 | if (!desc) | ||
419 | return NULL; | ||
420 | |||
421 | for_each_sg(sgl, sg, sg_len, i) { | ||
422 | desc->sg[i].addr = sg_dma_address(sg); | ||
423 | desc->sg[i].len = sg_dma_len(sg); | ||
424 | } | ||
425 | |||
426 | desc->num_sgs = sg_len; | ||
427 | desc->direction = direction; | ||
428 | desc->cyclic = false; | ||
429 | |||
430 | return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); | ||
431 | } | ||
432 | |||
433 | static struct dma_async_tx_descriptor *jz4740_dma_prep_dma_cyclic( | ||
434 | struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, | ||
435 | size_t period_len, enum dma_transfer_direction direction, | ||
436 | unsigned long flags, void *context) | ||
437 | { | ||
438 | struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); | ||
439 | struct jz4740_dma_desc *desc; | ||
440 | unsigned int num_periods, i; | ||
441 | |||
442 | if (buf_len % period_len) | ||
443 | return NULL; | ||
444 | |||
445 | num_periods = buf_len / period_len; | ||
446 | |||
447 | desc = jz4740_dma_alloc_desc(num_periods); | ||
448 | if (!desc) | ||
449 | return NULL; | ||
450 | |||
451 | for (i = 0; i < num_periods; i++) { | ||
452 | desc->sg[i].addr = buf_addr; | ||
453 | desc->sg[i].len = period_len; | ||
454 | buf_addr += period_len; | ||
455 | } | ||
456 | |||
457 | desc->num_sgs = num_periods; | ||
458 | desc->direction = direction; | ||
459 | desc->cyclic = true; | ||
460 | |||
461 | return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); | ||
462 | } | ||
463 | |||
464 | static size_t jz4740_dma_desc_residue(struct jz4740_dmaengine_chan *chan, | ||
465 | struct jz4740_dma_desc *desc, unsigned int next_sg) | ||
466 | { | ||
467 | struct jz4740_dma_dev *dmadev = jz4740_dma_chan_get_dev(chan); | ||
468 | unsigned int residue, count; | ||
469 | unsigned int i; | ||
470 | |||
471 | residue = 0; | ||
472 | |||
473 | for (i = next_sg; i < desc->num_sgs; i++) | ||
474 | residue += desc->sg[i].len; | ||
475 | |||
476 | if (next_sg != 0) { | ||
477 | count = jz4740_dma_read(dmadev, | ||
478 | JZ_REG_DMA_TRANSFER_COUNT(chan->id)); | ||
479 | residue += count << chan->transfer_shift; | ||
480 | } | ||
481 | |||
482 | return residue; | ||
483 | } | ||
484 | |||
485 | static enum dma_status jz4740_dma_tx_status(struct dma_chan *c, | ||
486 | dma_cookie_t cookie, struct dma_tx_state *state) | ||
487 | { | ||
488 | struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c); | ||
489 | struct virt_dma_desc *vdesc; | ||
490 | enum dma_status status; | ||
491 | unsigned long flags; | ||
492 | |||
493 | status = dma_cookie_status(c, cookie, state); | ||
494 | if (status == DMA_SUCCESS || !state) | ||
495 | return status; | ||
496 | |||
497 | spin_lock_irqsave(&chan->vchan.lock, flags); | ||
498 | vdesc = vchan_find_desc(&chan->vchan, cookie); | ||
499 | if (cookie == chan->desc->vdesc.tx.cookie) { | ||
500 | state->residue = jz4740_dma_desc_residue(chan, chan->desc, | ||
501 | chan->next_sg); | ||
502 | } else if (vdesc) { | ||
503 | state->residue = jz4740_dma_desc_residue(chan, | ||
504 | to_jz4740_dma_desc(vdesc), 0); | ||
505 | } else { | ||
506 | state->residue = 0; | ||
507 | } | ||
508 | spin_unlock_irqrestore(&chan->vchan.lock, flags); | ||
509 | |||
510 | return status; | ||
511 | } | ||
512 | |||
513 | static int jz4740_dma_alloc_chan_resources(struct dma_chan *c) | ||
514 | { | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static void jz4740_dma_free_chan_resources(struct dma_chan *c) | ||
519 | { | ||
520 | vchan_free_chan_resources(to_virt_chan(c)); | ||
521 | } | ||
522 | |||
523 | static void jz4740_dma_desc_free(struct virt_dma_desc *vdesc) | ||
524 | { | ||
525 | kfree(container_of(vdesc, struct jz4740_dma_desc, vdesc)); | ||
526 | } | ||
527 | |||
528 | static int jz4740_dma_probe(struct platform_device *pdev) | ||
529 | { | ||
530 | struct jz4740_dmaengine_chan *chan; | ||
531 | struct jz4740_dma_dev *dmadev; | ||
532 | struct dma_device *dd; | ||
533 | unsigned int i; | ||
534 | struct resource *res; | ||
535 | int ret; | ||
536 | int irq; | ||
537 | |||
538 | dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL); | ||
539 | if (!dmadev) | ||
540 | return -EINVAL; | ||
541 | |||
542 | dd = &dmadev->ddev; | ||
543 | |||
544 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
545 | dmadev->base = devm_ioremap_resource(&pdev->dev, res); | ||
546 | if (IS_ERR(dmadev->base)) | ||
547 | return PTR_ERR(dmadev->base); | ||
548 | |||
549 | dmadev->clk = clk_get(&pdev->dev, "dma"); | ||
550 | if (IS_ERR(dmadev->clk)) | ||
551 | return PTR_ERR(dmadev->clk); | ||
552 | |||
553 | clk_prepare_enable(dmadev->clk); | ||
554 | |||
555 | dma_cap_set(DMA_SLAVE, dd->cap_mask); | ||
556 | dma_cap_set(DMA_CYCLIC, dd->cap_mask); | ||
557 | dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources; | ||
558 | dd->device_free_chan_resources = jz4740_dma_free_chan_resources; | ||
559 | dd->device_tx_status = jz4740_dma_tx_status; | ||
560 | dd->device_issue_pending = jz4740_dma_issue_pending; | ||
561 | dd->device_prep_slave_sg = jz4740_dma_prep_slave_sg; | ||
562 | dd->device_prep_dma_cyclic = jz4740_dma_prep_dma_cyclic; | ||
563 | dd->device_control = jz4740_dma_control; | ||
564 | dd->dev = &pdev->dev; | ||
565 | dd->chancnt = JZ_DMA_NR_CHANS; | ||
566 | INIT_LIST_HEAD(&dd->channels); | ||
567 | |||
568 | for (i = 0; i < dd->chancnt; i++) { | ||
569 | chan = &dmadev->chan[i]; | ||
570 | chan->id = i; | ||
571 | chan->vchan.desc_free = jz4740_dma_desc_free; | ||
572 | vchan_init(&chan->vchan, dd); | ||
573 | } | ||
574 | |||
575 | ret = dma_async_device_register(dd); | ||
576 | if (ret) | ||
577 | return ret; | ||
578 | |||
579 | irq = platform_get_irq(pdev, 0); | ||
580 | ret = request_irq(irq, jz4740_dma_irq, 0, dev_name(&pdev->dev), dmadev); | ||
581 | if (ret) | ||
582 | goto err_unregister; | ||
583 | |||
584 | platform_set_drvdata(pdev, dmadev); | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | err_unregister: | ||
589 | dma_async_device_unregister(dd); | ||
590 | return ret; | ||
591 | } | ||
592 | |||
593 | static int jz4740_dma_remove(struct platform_device *pdev) | ||
594 | { | ||
595 | struct jz4740_dma_dev *dmadev = platform_get_drvdata(pdev); | ||
596 | int irq = platform_get_irq(pdev, 0); | ||
597 | |||
598 | free_irq(irq, dmadev); | ||
599 | dma_async_device_unregister(&dmadev->ddev); | ||
600 | clk_disable_unprepare(dmadev->clk); | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static struct platform_driver jz4740_dma_driver = { | ||
606 | .probe = jz4740_dma_probe, | ||
607 | .remove = jz4740_dma_remove, | ||
608 | .driver = { | ||
609 | .name = "jz4740-dma", | ||
610 | .owner = THIS_MODULE, | ||
611 | }, | ||
612 | }; | ||
613 | module_platform_driver(jz4740_dma_driver); | ||
614 | |||
615 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
616 | MODULE_DESCRIPTION("JZ4740 DMA driver"); | ||
617 | MODULE_LICENSE("GPLv2"); | ||
diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig new file mode 100644 index 000000000000..dde13248b681 --- /dev/null +++ b/drivers/dma/dw/Kconfig | |||
@@ -0,0 +1,29 @@ | |||
1 | # | ||
2 | # DMA engine configuration for dw | ||
3 | # | ||
4 | |||
5 | config DW_DMAC_CORE | ||
6 | tristate "Synopsys DesignWare AHB DMA support" | ||
7 | depends on GENERIC_HARDIRQS | ||
8 | select DMA_ENGINE | ||
9 | |||
10 | config DW_DMAC | ||
11 | tristate "Synopsys DesignWare AHB DMA platform driver" | ||
12 | select DW_DMAC_CORE | ||
13 | select DW_DMAC_BIG_ENDIAN_IO if AVR32 | ||
14 | default y if CPU_AT32AP7000 | ||
15 | help | ||
16 | Support the Synopsys DesignWare AHB DMA controller. This | ||
17 | can be integrated in chips such as the Atmel AT32ap7000. | ||
18 | |||
19 | config DW_DMAC_PCI | ||
20 | tristate "Synopsys DesignWare AHB DMA PCI driver" | ||
21 | depends on PCI | ||
22 | select DW_DMAC_CORE | ||
23 | help | ||
24 | Support the Synopsys DesignWare AHB DMA controller on the | ||
25 | platfroms that enumerate it as a PCI device. For example, | ||
26 | Intel Medfield has integrated this GPDMA controller. | ||
27 | |||
28 | config DW_DMAC_BIG_ENDIAN_IO | ||
29 | bool | ||
diff --git a/drivers/dma/dw/Makefile b/drivers/dma/dw/Makefile new file mode 100644 index 000000000000..3eebd1ce2c6b --- /dev/null +++ b/drivers/dma/dw/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | obj-$(CONFIG_DW_DMAC_CORE) += dw_dmac_core.o | ||
2 | dw_dmac_core-objs := core.o | ||
3 | |||
4 | obj-$(CONFIG_DW_DMAC) += dw_dmac.o | ||
5 | dw_dmac-objs := platform.o | ||
6 | |||
7 | obj-$(CONFIG_DW_DMAC_PCI) += dw_dmac_pci.o | ||
8 | dw_dmac_pci-objs := pci.o | ||
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw/core.c index 2e5deaa82b60..eea479c12173 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw/core.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 Atmel Corporation | 4 | * Copyright (C) 2007-2008 Atmel Corporation |
5 | * Copyright (C) 2010-2011 ST Microelectronics | 5 | * Copyright (C) 2010-2011 ST Microelectronics |
6 | * Copyright (C) 2013 Intel Corporation | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -19,17 +20,12 @@ | |||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_dma.h> | ||
24 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
25 | #include <linux/module.h> | 24 | #include <linux/module.h> |
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
28 | #include <linux/acpi.h> | ||
29 | #include <linux/acpi_dma.h> | ||
30 | 26 | ||
31 | #include "dw_dmac_regs.h" | 27 | #include "../dmaengine.h" |
32 | #include "dmaengine.h" | 28 | #include "internal.h" |
33 | 29 | ||
34 | /* | 30 | /* |
35 | * This supports the Synopsys "DesignWare AHB Central DMA Controller", | 31 | * This supports the Synopsys "DesignWare AHB Central DMA Controller", |
@@ -41,16 +37,6 @@ | |||
41 | * which does not support descriptor writeback. | 37 | * which does not support descriptor writeback. |
42 | */ | 38 | */ |
43 | 39 | ||
44 | static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave) | ||
45 | { | ||
46 | return slave ? slave->dst_master : 0; | ||
47 | } | ||
48 | |||
49 | static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave) | ||
50 | { | ||
51 | return slave ? slave->src_master : 1; | ||
52 | } | ||
53 | |||
54 | static inline void dwc_set_masters(struct dw_dma_chan *dwc) | 40 | static inline void dwc_set_masters(struct dw_dma_chan *dwc) |
55 | { | 41 | { |
56 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | 42 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); |
@@ -556,14 +542,14 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
556 | 542 | ||
557 | /* --------------------- Cyclic DMA API extensions -------------------- */ | 543 | /* --------------------- Cyclic DMA API extensions -------------------- */ |
558 | 544 | ||
559 | inline dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan) | 545 | dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan) |
560 | { | 546 | { |
561 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | 547 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); |
562 | return channel_readl(dwc, SAR); | 548 | return channel_readl(dwc, SAR); |
563 | } | 549 | } |
564 | EXPORT_SYMBOL(dw_dma_get_src_addr); | 550 | EXPORT_SYMBOL(dw_dma_get_src_addr); |
565 | 551 | ||
566 | inline dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan) | 552 | dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan) |
567 | { | 553 | { |
568 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | 554 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); |
569 | return channel_readl(dwc, DAR); | 555 | return channel_readl(dwc, DAR); |
@@ -1225,99 +1211,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) | |||
1225 | dev_vdbg(chan2dev(chan), "%s: done\n", __func__); | 1211 | dev_vdbg(chan2dev(chan), "%s: done\n", __func__); |
1226 | } | 1212 | } |
1227 | 1213 | ||
1228 | /*----------------------------------------------------------------------*/ | ||
1229 | |||
1230 | struct dw_dma_of_filter_args { | ||
1231 | struct dw_dma *dw; | ||
1232 | unsigned int req; | ||
1233 | unsigned int src; | ||
1234 | unsigned int dst; | ||
1235 | }; | ||
1236 | |||
1237 | static bool dw_dma_of_filter(struct dma_chan *chan, void *param) | ||
1238 | { | ||
1239 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
1240 | struct dw_dma_of_filter_args *fargs = param; | ||
1241 | |||
1242 | /* Ensure the device matches our channel */ | ||
1243 | if (chan->device != &fargs->dw->dma) | ||
1244 | return false; | ||
1245 | |||
1246 | dwc->request_line = fargs->req; | ||
1247 | dwc->src_master = fargs->src; | ||
1248 | dwc->dst_master = fargs->dst; | ||
1249 | |||
1250 | return true; | ||
1251 | } | ||
1252 | |||
1253 | static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, | ||
1254 | struct of_dma *ofdma) | ||
1255 | { | ||
1256 | struct dw_dma *dw = ofdma->of_dma_data; | ||
1257 | struct dw_dma_of_filter_args fargs = { | ||
1258 | .dw = dw, | ||
1259 | }; | ||
1260 | dma_cap_mask_t cap; | ||
1261 | |||
1262 | if (dma_spec->args_count != 3) | ||
1263 | return NULL; | ||
1264 | |||
1265 | fargs.req = dma_spec->args[0]; | ||
1266 | fargs.src = dma_spec->args[1]; | ||
1267 | fargs.dst = dma_spec->args[2]; | ||
1268 | |||
1269 | if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS || | ||
1270 | fargs.src >= dw->nr_masters || | ||
1271 | fargs.dst >= dw->nr_masters)) | ||
1272 | return NULL; | ||
1273 | |||
1274 | dma_cap_zero(cap); | ||
1275 | dma_cap_set(DMA_SLAVE, cap); | ||
1276 | |||
1277 | /* TODO: there should be a simpler way to do this */ | ||
1278 | return dma_request_channel(cap, dw_dma_of_filter, &fargs); | ||
1279 | } | ||
1280 | |||
1281 | #ifdef CONFIG_ACPI | ||
1282 | static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) | ||
1283 | { | ||
1284 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
1285 | struct acpi_dma_spec *dma_spec = param; | ||
1286 | |||
1287 | if (chan->device->dev != dma_spec->dev || | ||
1288 | chan->chan_id != dma_spec->chan_id) | ||
1289 | return false; | ||
1290 | |||
1291 | dwc->request_line = dma_spec->slave_id; | ||
1292 | dwc->src_master = dwc_get_sms(NULL); | ||
1293 | dwc->dst_master = dwc_get_dms(NULL); | ||
1294 | |||
1295 | return true; | ||
1296 | } | ||
1297 | |||
1298 | static void dw_dma_acpi_controller_register(struct dw_dma *dw) | ||
1299 | { | ||
1300 | struct device *dev = dw->dma.dev; | ||
1301 | struct acpi_dma_filter_info *info; | ||
1302 | int ret; | ||
1303 | |||
1304 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | ||
1305 | if (!info) | ||
1306 | return; | ||
1307 | |||
1308 | dma_cap_zero(info->dma_cap); | ||
1309 | dma_cap_set(DMA_SLAVE, info->dma_cap); | ||
1310 | info->filter_fn = dw_dma_acpi_filter; | ||
1311 | |||
1312 | ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate, | ||
1313 | info); | ||
1314 | if (ret) | ||
1315 | dev_err(dev, "could not register acpi_dma_controller\n"); | ||
1316 | } | ||
1317 | #else /* !CONFIG_ACPI */ | ||
1318 | static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} | ||
1319 | #endif /* !CONFIG_ACPI */ | ||
1320 | |||
1321 | /* --------------------- Cyclic DMA API extensions -------------------- */ | 1214 | /* --------------------- Cyclic DMA API extensions -------------------- */ |
1322 | 1215 | ||
1323 | /** | 1216 | /** |
@@ -1598,104 +1491,24 @@ static void dw_dma_off(struct dw_dma *dw) | |||
1598 | dw->chan[i].initialized = false; | 1491 | dw->chan[i].initialized = false; |
1599 | } | 1492 | } |
1600 | 1493 | ||
1601 | #ifdef CONFIG_OF | 1494 | int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) |
1602 | static struct dw_dma_platform_data * | ||
1603 | dw_dma_parse_dt(struct platform_device *pdev) | ||
1604 | { | 1495 | { |
1605 | struct device_node *np = pdev->dev.of_node; | ||
1606 | struct dw_dma_platform_data *pdata; | ||
1607 | u32 tmp, arr[4]; | ||
1608 | |||
1609 | if (!np) { | ||
1610 | dev_err(&pdev->dev, "Missing DT data\n"); | ||
1611 | return NULL; | ||
1612 | } | ||
1613 | |||
1614 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
1615 | if (!pdata) | ||
1616 | return NULL; | ||
1617 | |||
1618 | if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels)) | ||
1619 | return NULL; | ||
1620 | |||
1621 | if (of_property_read_bool(np, "is_private")) | ||
1622 | pdata->is_private = true; | ||
1623 | |||
1624 | if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) | ||
1625 | pdata->chan_allocation_order = (unsigned char)tmp; | ||
1626 | |||
1627 | if (!of_property_read_u32(np, "chan_priority", &tmp)) | ||
1628 | pdata->chan_priority = tmp; | ||
1629 | |||
1630 | if (!of_property_read_u32(np, "block_size", &tmp)) | ||
1631 | pdata->block_size = tmp; | ||
1632 | |||
1633 | if (!of_property_read_u32(np, "dma-masters", &tmp)) { | ||
1634 | if (tmp > 4) | ||
1635 | return NULL; | ||
1636 | |||
1637 | pdata->nr_masters = tmp; | ||
1638 | } | ||
1639 | |||
1640 | if (!of_property_read_u32_array(np, "data_width", arr, | ||
1641 | pdata->nr_masters)) | ||
1642 | for (tmp = 0; tmp < pdata->nr_masters; tmp++) | ||
1643 | pdata->data_width[tmp] = arr[tmp]; | ||
1644 | |||
1645 | return pdata; | ||
1646 | } | ||
1647 | #else | ||
1648 | static inline struct dw_dma_platform_data * | ||
1649 | dw_dma_parse_dt(struct platform_device *pdev) | ||
1650 | { | ||
1651 | return NULL; | ||
1652 | } | ||
1653 | #endif | ||
1654 | |||
1655 | static int dw_probe(struct platform_device *pdev) | ||
1656 | { | ||
1657 | struct dw_dma_platform_data *pdata; | ||
1658 | struct resource *io; | ||
1659 | struct dw_dma *dw; | 1496 | struct dw_dma *dw; |
1660 | size_t size; | 1497 | size_t size; |
1661 | void __iomem *regs; | ||
1662 | bool autocfg; | 1498 | bool autocfg; |
1663 | unsigned int dw_params; | 1499 | unsigned int dw_params; |
1664 | unsigned int nr_channels; | 1500 | unsigned int nr_channels; |
1665 | unsigned int max_blk_size = 0; | 1501 | unsigned int max_blk_size = 0; |
1666 | int irq; | ||
1667 | int err; | 1502 | int err; |
1668 | int i; | 1503 | int i; |
1669 | 1504 | ||
1670 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1505 | dw_params = dma_read_byaddr(chip->regs, DW_PARAMS); |
1671 | if (!io) | ||
1672 | return -EINVAL; | ||
1673 | |||
1674 | irq = platform_get_irq(pdev, 0); | ||
1675 | if (irq < 0) | ||
1676 | return irq; | ||
1677 | |||
1678 | regs = devm_ioremap_resource(&pdev->dev, io); | ||
1679 | if (IS_ERR(regs)) | ||
1680 | return PTR_ERR(regs); | ||
1681 | |||
1682 | /* Apply default dma_mask if needed */ | ||
1683 | if (!pdev->dev.dma_mask) { | ||
1684 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | ||
1685 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
1686 | } | ||
1687 | |||
1688 | dw_params = dma_read_byaddr(regs, DW_PARAMS); | ||
1689 | autocfg = dw_params >> DW_PARAMS_EN & 0x1; | 1506 | autocfg = dw_params >> DW_PARAMS_EN & 0x1; |
1690 | 1507 | ||
1691 | dev_dbg(&pdev->dev, "DW_PARAMS: 0x%08x\n", dw_params); | 1508 | dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params); |
1692 | |||
1693 | pdata = dev_get_platdata(&pdev->dev); | ||
1694 | if (!pdata) | ||
1695 | pdata = dw_dma_parse_dt(pdev); | ||
1696 | 1509 | ||
1697 | if (!pdata && autocfg) { | 1510 | if (!pdata && autocfg) { |
1698 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 1511 | pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL); |
1699 | if (!pdata) | 1512 | if (!pdata) |
1700 | return -ENOMEM; | 1513 | return -ENOMEM; |
1701 | 1514 | ||
@@ -1712,16 +1525,17 @@ static int dw_probe(struct platform_device *pdev) | |||
1712 | nr_channels = pdata->nr_channels; | 1525 | nr_channels = pdata->nr_channels; |
1713 | 1526 | ||
1714 | size = sizeof(struct dw_dma) + nr_channels * sizeof(struct dw_dma_chan); | 1527 | size = sizeof(struct dw_dma) + nr_channels * sizeof(struct dw_dma_chan); |
1715 | dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); | 1528 | dw = devm_kzalloc(chip->dev, size, GFP_KERNEL); |
1716 | if (!dw) | 1529 | if (!dw) |
1717 | return -ENOMEM; | 1530 | return -ENOMEM; |
1718 | 1531 | ||
1719 | dw->clk = devm_clk_get(&pdev->dev, "hclk"); | 1532 | dw->clk = devm_clk_get(chip->dev, "hclk"); |
1720 | if (IS_ERR(dw->clk)) | 1533 | if (IS_ERR(dw->clk)) |
1721 | return PTR_ERR(dw->clk); | 1534 | return PTR_ERR(dw->clk); |
1722 | clk_prepare_enable(dw->clk); | 1535 | clk_prepare_enable(dw->clk); |
1723 | 1536 | ||
1724 | dw->regs = regs; | 1537 | dw->regs = chip->regs; |
1538 | chip->dw = dw; | ||
1725 | 1539 | ||
1726 | /* Get hardware configuration parameters */ | 1540 | /* Get hardware configuration parameters */ |
1727 | if (autocfg) { | 1541 | if (autocfg) { |
@@ -1746,18 +1560,16 @@ static int dw_probe(struct platform_device *pdev) | |||
1746 | /* Disable BLOCK interrupts as well */ | 1560 | /* Disable BLOCK interrupts as well */ |
1747 | channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); | 1561 | channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask); |
1748 | 1562 | ||
1749 | err = devm_request_irq(&pdev->dev, irq, dw_dma_interrupt, 0, | 1563 | err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt, 0, |
1750 | "dw_dmac", dw); | 1564 | "dw_dmac", dw); |
1751 | if (err) | 1565 | if (err) |
1752 | return err; | 1566 | return err; |
1753 | 1567 | ||
1754 | platform_set_drvdata(pdev, dw); | ||
1755 | |||
1756 | /* Create a pool of consistent memory blocks for hardware descriptors */ | 1568 | /* Create a pool of consistent memory blocks for hardware descriptors */ |
1757 | dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", &pdev->dev, | 1569 | dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev, |
1758 | sizeof(struct dw_desc), 4, 0); | 1570 | sizeof(struct dw_desc), 4, 0); |
1759 | if (!dw->desc_pool) { | 1571 | if (!dw->desc_pool) { |
1760 | dev_err(&pdev->dev, "No memory for descriptors dma pool\n"); | 1572 | dev_err(chip->dev, "No memory for descriptors dma pool\n"); |
1761 | return -ENOMEM; | 1573 | return -ENOMEM; |
1762 | } | 1574 | } |
1763 | 1575 | ||
@@ -1798,12 +1610,12 @@ static int dw_probe(struct platform_device *pdev) | |||
1798 | /* Hardware configuration */ | 1610 | /* Hardware configuration */ |
1799 | if (autocfg) { | 1611 | if (autocfg) { |
1800 | unsigned int dwc_params; | 1612 | unsigned int dwc_params; |
1613 | void __iomem *addr = chip->regs + r * sizeof(u32); | ||
1801 | 1614 | ||
1802 | dwc_params = dma_read_byaddr(regs + r * sizeof(u32), | 1615 | dwc_params = dma_read_byaddr(addr, DWC_PARAMS); |
1803 | DWC_PARAMS); | ||
1804 | 1616 | ||
1805 | dev_dbg(&pdev->dev, "DWC_PARAMS[%d]: 0x%08x\n", i, | 1617 | dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i, |
1806 | dwc_params); | 1618 | dwc_params); |
1807 | 1619 | ||
1808 | /* Decode maximum block size for given channel. The | 1620 | /* Decode maximum block size for given channel. The |
1809 | * stored 4 bit value represents blocks from 0x00 for 3 | 1621 | * stored 4 bit value represents blocks from 0x00 for 3 |
@@ -1834,7 +1646,7 @@ static int dw_probe(struct platform_device *pdev) | |||
1834 | dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); | 1646 | dma_cap_set(DMA_SLAVE, dw->dma.cap_mask); |
1835 | if (pdata->is_private) | 1647 | if (pdata->is_private) |
1836 | dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); | 1648 | dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask); |
1837 | dw->dma.dev = &pdev->dev; | 1649 | dw->dma.dev = chip->dev; |
1838 | dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; | 1650 | dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources; |
1839 | dw->dma.device_free_chan_resources = dwc_free_chan_resources; | 1651 | dw->dma.device_free_chan_resources = dwc_free_chan_resources; |
1840 | 1652 | ||
@@ -1848,32 +1660,20 @@ static int dw_probe(struct platform_device *pdev) | |||
1848 | 1660 | ||
1849 | dma_writel(dw, CFG, DW_CFG_DMA_EN); | 1661 | dma_writel(dw, CFG, DW_CFG_DMA_EN); |
1850 | 1662 | ||
1851 | dev_info(&pdev->dev, "DesignWare DMA Controller, %d channels\n", | 1663 | dev_info(chip->dev, "DesignWare DMA Controller, %d channels\n", |
1852 | nr_channels); | 1664 | nr_channels); |
1853 | 1665 | ||
1854 | dma_async_device_register(&dw->dma); | 1666 | dma_async_device_register(&dw->dma); |
1855 | 1667 | ||
1856 | if (pdev->dev.of_node) { | ||
1857 | err = of_dma_controller_register(pdev->dev.of_node, | ||
1858 | dw_dma_of_xlate, dw); | ||
1859 | if (err) | ||
1860 | dev_err(&pdev->dev, | ||
1861 | "could not register of_dma_controller\n"); | ||
1862 | } | ||
1863 | |||
1864 | if (ACPI_HANDLE(&pdev->dev)) | ||
1865 | dw_dma_acpi_controller_register(dw); | ||
1866 | |||
1867 | return 0; | 1668 | return 0; |
1868 | } | 1669 | } |
1670 | EXPORT_SYMBOL_GPL(dw_dma_probe); | ||
1869 | 1671 | ||
1870 | static int dw_remove(struct platform_device *pdev) | 1672 | int dw_dma_remove(struct dw_dma_chip *chip) |
1871 | { | 1673 | { |
1872 | struct dw_dma *dw = platform_get_drvdata(pdev); | 1674 | struct dw_dma *dw = chip->dw; |
1873 | struct dw_dma_chan *dwc, *_dwc; | 1675 | struct dw_dma_chan *dwc, *_dwc; |
1874 | 1676 | ||
1875 | if (pdev->dev.of_node) | ||
1876 | of_dma_controller_free(pdev->dev.of_node); | ||
1877 | dw_dma_off(dw); | 1677 | dw_dma_off(dw); |
1878 | dma_async_device_unregister(&dw->dma); | 1678 | dma_async_device_unregister(&dw->dma); |
1879 | 1679 | ||
@@ -1887,86 +1687,44 @@ static int dw_remove(struct platform_device *pdev) | |||
1887 | 1687 | ||
1888 | return 0; | 1688 | return 0; |
1889 | } | 1689 | } |
1690 | EXPORT_SYMBOL_GPL(dw_dma_remove); | ||
1890 | 1691 | ||
1891 | static void dw_shutdown(struct platform_device *pdev) | 1692 | void dw_dma_shutdown(struct dw_dma_chip *chip) |
1892 | { | 1693 | { |
1893 | struct dw_dma *dw = platform_get_drvdata(pdev); | 1694 | struct dw_dma *dw = chip->dw; |
1894 | 1695 | ||
1895 | dw_dma_off(dw); | 1696 | dw_dma_off(dw); |
1896 | clk_disable_unprepare(dw->clk); | 1697 | clk_disable_unprepare(dw->clk); |
1897 | } | 1698 | } |
1699 | EXPORT_SYMBOL_GPL(dw_dma_shutdown); | ||
1700 | |||
1701 | #ifdef CONFIG_PM_SLEEP | ||
1898 | 1702 | ||
1899 | static int dw_suspend_noirq(struct device *dev) | 1703 | int dw_dma_suspend(struct dw_dma_chip *chip) |
1900 | { | 1704 | { |
1901 | struct platform_device *pdev = to_platform_device(dev); | 1705 | struct dw_dma *dw = chip->dw; |
1902 | struct dw_dma *dw = platform_get_drvdata(pdev); | ||
1903 | 1706 | ||
1904 | dw_dma_off(dw); | 1707 | dw_dma_off(dw); |
1905 | clk_disable_unprepare(dw->clk); | 1708 | clk_disable_unprepare(dw->clk); |
1906 | 1709 | ||
1907 | return 0; | 1710 | return 0; |
1908 | } | 1711 | } |
1712 | EXPORT_SYMBOL_GPL(dw_dma_suspend); | ||
1909 | 1713 | ||
1910 | static int dw_resume_noirq(struct device *dev) | 1714 | int dw_dma_resume(struct dw_dma_chip *chip) |
1911 | { | 1715 | { |
1912 | struct platform_device *pdev = to_platform_device(dev); | 1716 | struct dw_dma *dw = chip->dw; |
1913 | struct dw_dma *dw = platform_get_drvdata(pdev); | ||
1914 | 1717 | ||
1915 | clk_prepare_enable(dw->clk); | 1718 | clk_prepare_enable(dw->clk); |
1916 | dma_writel(dw, CFG, DW_CFG_DMA_EN); | 1719 | dma_writel(dw, CFG, DW_CFG_DMA_EN); |
1917 | 1720 | ||
1918 | return 0; | 1721 | return 0; |
1919 | } | 1722 | } |
1723 | EXPORT_SYMBOL_GPL(dw_dma_resume); | ||
1920 | 1724 | ||
1921 | static const struct dev_pm_ops dw_dev_pm_ops = { | 1725 | #endif /* CONFIG_PM_SLEEP */ |
1922 | .suspend_noirq = dw_suspend_noirq, | ||
1923 | .resume_noirq = dw_resume_noirq, | ||
1924 | .freeze_noirq = dw_suspend_noirq, | ||
1925 | .thaw_noirq = dw_resume_noirq, | ||
1926 | .restore_noirq = dw_resume_noirq, | ||
1927 | .poweroff_noirq = dw_suspend_noirq, | ||
1928 | }; | ||
1929 | |||
1930 | #ifdef CONFIG_OF | ||
1931 | static const struct of_device_id dw_dma_of_id_table[] = { | ||
1932 | { .compatible = "snps,dma-spear1340" }, | ||
1933 | {} | ||
1934 | }; | ||
1935 | MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); | ||
1936 | #endif | ||
1937 | |||
1938 | #ifdef CONFIG_ACPI | ||
1939 | static const struct acpi_device_id dw_dma_acpi_id_table[] = { | ||
1940 | { "INTL9C60", 0 }, | ||
1941 | { } | ||
1942 | }; | ||
1943 | #endif | ||
1944 | |||
1945 | static struct platform_driver dw_driver = { | ||
1946 | .probe = dw_probe, | ||
1947 | .remove = dw_remove, | ||
1948 | .shutdown = dw_shutdown, | ||
1949 | .driver = { | ||
1950 | .name = "dw_dmac", | ||
1951 | .pm = &dw_dev_pm_ops, | ||
1952 | .of_match_table = of_match_ptr(dw_dma_of_id_table), | ||
1953 | .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table), | ||
1954 | }, | ||
1955 | }; | ||
1956 | |||
1957 | static int __init dw_init(void) | ||
1958 | { | ||
1959 | return platform_driver_register(&dw_driver); | ||
1960 | } | ||
1961 | subsys_initcall(dw_init); | ||
1962 | |||
1963 | static void __exit dw_exit(void) | ||
1964 | { | ||
1965 | platform_driver_unregister(&dw_driver); | ||
1966 | } | ||
1967 | module_exit(dw_exit); | ||
1968 | 1726 | ||
1969 | MODULE_LICENSE("GPL v2"); | 1727 | MODULE_LICENSE("GPL v2"); |
1970 | MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver"); | 1728 | MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller core driver"); |
1971 | MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); | 1729 | MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); |
1972 | MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); | 1730 | MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); |
diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h new file mode 100644 index 000000000000..32667f9e0dda --- /dev/null +++ b/drivers/dma/dw/internal.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Driver for the Synopsys DesignWare DMA Controller | ||
3 | * | ||
4 | * Copyright (C) 2013 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _DW_DMAC_INTERNAL_H | ||
12 | #define _DW_DMAC_INTERNAL_H | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/dw_dmac.h> | ||
16 | |||
17 | #include "regs.h" | ||
18 | |||
19 | /** | ||
20 | * struct dw_dma_chip - representation of DesignWare DMA controller hardware | ||
21 | * @dev: struct device of the DMA controller | ||
22 | * @irq: irq line | ||
23 | * @regs: memory mapped I/O space | ||
24 | * @dw: struct dw_dma that is filed by dw_dma_probe() | ||
25 | */ | ||
26 | struct dw_dma_chip { | ||
27 | struct device *dev; | ||
28 | int irq; | ||
29 | void __iomem *regs; | ||
30 | struct dw_dma *dw; | ||
31 | }; | ||
32 | |||
33 | /* Export to the platform drivers */ | ||
34 | int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata); | ||
35 | int dw_dma_remove(struct dw_dma_chip *chip); | ||
36 | |||
37 | void dw_dma_shutdown(struct dw_dma_chip *chip); | ||
38 | |||
39 | #ifdef CONFIG_PM_SLEEP | ||
40 | |||
41 | int dw_dma_suspend(struct dw_dma_chip *chip); | ||
42 | int dw_dma_resume(struct dw_dma_chip *chip); | ||
43 | |||
44 | #endif /* CONFIG_PM_SLEEP */ | ||
45 | |||
46 | /** | ||
47 | * dwc_get_dms - get destination master | ||
48 | * @slave: pointer to the custom slave configuration | ||
49 | * | ||
50 | * Returns destination master in the custom slave configuration if defined, or | ||
51 | * default value otherwise. | ||
52 | */ | ||
53 | static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave) | ||
54 | { | ||
55 | return slave ? slave->dst_master : 0; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * dwc_get_sms - get source master | ||
60 | * @slave: pointer to the custom slave configuration | ||
61 | * | ||
62 | * Returns source master in the custom slave configuration if defined, or | ||
63 | * default value otherwise. | ||
64 | */ | ||
65 | static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave) | ||
66 | { | ||
67 | return slave ? slave->src_master : 1; | ||
68 | } | ||
69 | |||
70 | #endif /* _DW_DMAC_INTERNAL_H */ | ||
diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c new file mode 100644 index 000000000000..e89fc24b8293 --- /dev/null +++ b/drivers/dma/dw/pci.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * PCI driver for the Synopsys DesignWare DMA Controller | ||
3 | * | ||
4 | * Copyright (C) 2013 Intel Corporation | ||
5 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/device.h> | ||
15 | |||
16 | #include "internal.h" | ||
17 | |||
18 | static struct dw_dma_platform_data dw_pci_pdata = { | ||
19 | .is_private = 1, | ||
20 | .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, | ||
21 | .chan_priority = CHAN_PRIORITY_ASCENDING, | ||
22 | }; | ||
23 | |||
24 | static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | ||
25 | { | ||
26 | struct dw_dma_chip *chip; | ||
27 | struct dw_dma_platform_data *pdata = (void *)pid->driver_data; | ||
28 | int ret; | ||
29 | |||
30 | ret = pcim_enable_device(pdev); | ||
31 | if (ret) | ||
32 | return ret; | ||
33 | |||
34 | ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); | ||
35 | if (ret) { | ||
36 | dev_err(&pdev->dev, "I/O memory remapping failed\n"); | ||
37 | return ret; | ||
38 | } | ||
39 | |||
40 | pci_set_master(pdev); | ||
41 | pci_try_set_mwi(pdev); | ||
42 | |||
43 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
44 | if (ret) | ||
45 | return ret; | ||
46 | |||
47 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
48 | if (ret) | ||
49 | return ret; | ||
50 | |||
51 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); | ||
52 | if (!chip) | ||
53 | return -ENOMEM; | ||
54 | |||
55 | chip->dev = &pdev->dev; | ||
56 | chip->regs = pcim_iomap_table(pdev)[0]; | ||
57 | chip->irq = pdev->irq; | ||
58 | |||
59 | ret = dw_dma_probe(chip, pdata); | ||
60 | if (ret) | ||
61 | return ret; | ||
62 | |||
63 | pci_set_drvdata(pdev, chip); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static void dw_pci_remove(struct pci_dev *pdev) | ||
69 | { | ||
70 | struct dw_dma_chip *chip = pci_get_drvdata(pdev); | ||
71 | int ret; | ||
72 | |||
73 | ret = dw_dma_remove(chip); | ||
74 | if (ret) | ||
75 | dev_warn(&pdev->dev, "can't remove device properly: %d\n", ret); | ||
76 | } | ||
77 | |||
78 | static DEFINE_PCI_DEVICE_TABLE(dw_pci_id_table) = { | ||
79 | /* Medfield */ | ||
80 | { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_pci_pdata }, | ||
81 | { PCI_VDEVICE(INTEL, 0x0830), (kernel_ulong_t)&dw_pci_pdata }, | ||
82 | |||
83 | /* BayTrail */ | ||
84 | { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_pdata }, | ||
85 | { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_pdata }, | ||
86 | { } | ||
87 | }; | ||
88 | MODULE_DEVICE_TABLE(pci, dw_pci_id_table); | ||
89 | |||
90 | static struct pci_driver dw_pci_driver = { | ||
91 | .name = "dw_dmac_pci", | ||
92 | .id_table = dw_pci_id_table, | ||
93 | .probe = dw_pci_probe, | ||
94 | .remove = dw_pci_remove, | ||
95 | }; | ||
96 | |||
97 | module_pci_driver(dw_pci_driver); | ||
98 | |||
99 | MODULE_LICENSE("GPL v2"); | ||
100 | MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller PCI driver"); | ||
101 | MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); | ||
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c new file mode 100644 index 000000000000..6c9449cffae8 --- /dev/null +++ b/drivers/dma/dw/platform.c | |||
@@ -0,0 +1,317 @@ | |||
1 | /* | ||
2 | * Platform driver for the Synopsys DesignWare DMA Controller | ||
3 | * | ||
4 | * Copyright (C) 2007-2008 Atmel Corporation | ||
5 | * Copyright (C) 2010-2011 ST Microelectronics | ||
6 | * Copyright (C) 2013 Intel Corporation | ||
7 | * | ||
8 | * Some parts of this driver are derived from the original dw_dmac. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/dmaengine.h> | ||
20 | #include <linux/dma-mapping.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_dma.h> | ||
23 | #include <linux/acpi.h> | ||
24 | #include <linux/acpi_dma.h> | ||
25 | |||
26 | #include "internal.h" | ||
27 | |||
28 | struct dw_dma_of_filter_args { | ||
29 | struct dw_dma *dw; | ||
30 | unsigned int req; | ||
31 | unsigned int src; | ||
32 | unsigned int dst; | ||
33 | }; | ||
34 | |||
35 | static bool dw_dma_of_filter(struct dma_chan *chan, void *param) | ||
36 | { | ||
37 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
38 | struct dw_dma_of_filter_args *fargs = param; | ||
39 | |||
40 | /* Ensure the device matches our channel */ | ||
41 | if (chan->device != &fargs->dw->dma) | ||
42 | return false; | ||
43 | |||
44 | dwc->request_line = fargs->req; | ||
45 | dwc->src_master = fargs->src; | ||
46 | dwc->dst_master = fargs->dst; | ||
47 | |||
48 | return true; | ||
49 | } | ||
50 | |||
51 | static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, | ||
52 | struct of_dma *ofdma) | ||
53 | { | ||
54 | struct dw_dma *dw = ofdma->of_dma_data; | ||
55 | struct dw_dma_of_filter_args fargs = { | ||
56 | .dw = dw, | ||
57 | }; | ||
58 | dma_cap_mask_t cap; | ||
59 | |||
60 | if (dma_spec->args_count != 3) | ||
61 | return NULL; | ||
62 | |||
63 | fargs.req = dma_spec->args[0]; | ||
64 | fargs.src = dma_spec->args[1]; | ||
65 | fargs.dst = dma_spec->args[2]; | ||
66 | |||
67 | if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS || | ||
68 | fargs.src >= dw->nr_masters || | ||
69 | fargs.dst >= dw->nr_masters)) | ||
70 | return NULL; | ||
71 | |||
72 | dma_cap_zero(cap); | ||
73 | dma_cap_set(DMA_SLAVE, cap); | ||
74 | |||
75 | /* TODO: there should be a simpler way to do this */ | ||
76 | return dma_request_channel(cap, dw_dma_of_filter, &fargs); | ||
77 | } | ||
78 | |||
79 | #ifdef CONFIG_ACPI | ||
80 | static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) | ||
81 | { | ||
82 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
83 | struct acpi_dma_spec *dma_spec = param; | ||
84 | |||
85 | if (chan->device->dev != dma_spec->dev || | ||
86 | chan->chan_id != dma_spec->chan_id) | ||
87 | return false; | ||
88 | |||
89 | dwc->request_line = dma_spec->slave_id; | ||
90 | dwc->src_master = dwc_get_sms(NULL); | ||
91 | dwc->dst_master = dwc_get_dms(NULL); | ||
92 | |||
93 | return true; | ||
94 | } | ||
95 | |||
96 | static void dw_dma_acpi_controller_register(struct dw_dma *dw) | ||
97 | { | ||
98 | struct device *dev = dw->dma.dev; | ||
99 | struct acpi_dma_filter_info *info; | ||
100 | int ret; | ||
101 | |||
102 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | ||
103 | if (!info) | ||
104 | return; | ||
105 | |||
106 | dma_cap_zero(info->dma_cap); | ||
107 | dma_cap_set(DMA_SLAVE, info->dma_cap); | ||
108 | info->filter_fn = dw_dma_acpi_filter; | ||
109 | |||
110 | ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate, | ||
111 | info); | ||
112 | if (ret) | ||
113 | dev_err(dev, "could not register acpi_dma_controller\n"); | ||
114 | } | ||
115 | #else /* !CONFIG_ACPI */ | ||
116 | static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {} | ||
117 | #endif /* !CONFIG_ACPI */ | ||
118 | |||
119 | #ifdef CONFIG_OF | ||
120 | static struct dw_dma_platform_data * | ||
121 | dw_dma_parse_dt(struct platform_device *pdev) | ||
122 | { | ||
123 | struct device_node *np = pdev->dev.of_node; | ||
124 | struct dw_dma_platform_data *pdata; | ||
125 | u32 tmp, arr[4]; | ||
126 | |||
127 | if (!np) { | ||
128 | dev_err(&pdev->dev, "Missing DT data\n"); | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
133 | if (!pdata) | ||
134 | return NULL; | ||
135 | |||
136 | if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels)) | ||
137 | return NULL; | ||
138 | |||
139 | if (of_property_read_bool(np, "is_private")) | ||
140 | pdata->is_private = true; | ||
141 | |||
142 | if (!of_property_read_u32(np, "chan_allocation_order", &tmp)) | ||
143 | pdata->chan_allocation_order = (unsigned char)tmp; | ||
144 | |||
145 | if (!of_property_read_u32(np, "chan_priority", &tmp)) | ||
146 | pdata->chan_priority = tmp; | ||
147 | |||
148 | if (!of_property_read_u32(np, "block_size", &tmp)) | ||
149 | pdata->block_size = tmp; | ||
150 | |||
151 | if (!of_property_read_u32(np, "dma-masters", &tmp)) { | ||
152 | if (tmp > 4) | ||
153 | return NULL; | ||
154 | |||
155 | pdata->nr_masters = tmp; | ||
156 | } | ||
157 | |||
158 | if (!of_property_read_u32_array(np, "data_width", arr, | ||
159 | pdata->nr_masters)) | ||
160 | for (tmp = 0; tmp < pdata->nr_masters; tmp++) | ||
161 | pdata->data_width[tmp] = arr[tmp]; | ||
162 | |||
163 | return pdata; | ||
164 | } | ||
165 | #else | ||
166 | static inline struct dw_dma_platform_data * | ||
167 | dw_dma_parse_dt(struct platform_device *pdev) | ||
168 | { | ||
169 | return NULL; | ||
170 | } | ||
171 | #endif | ||
172 | |||
173 | static int dw_probe(struct platform_device *pdev) | ||
174 | { | ||
175 | struct dw_dma_chip *chip; | ||
176 | struct device *dev = &pdev->dev; | ||
177 | struct resource *mem; | ||
178 | struct dw_dma_platform_data *pdata; | ||
179 | int err; | ||
180 | |||
181 | chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); | ||
182 | if (!chip) | ||
183 | return -ENOMEM; | ||
184 | |||
185 | chip->irq = platform_get_irq(pdev, 0); | ||
186 | if (chip->irq < 0) | ||
187 | return chip->irq; | ||
188 | |||
189 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
190 | chip->regs = devm_ioremap_resource(dev, mem); | ||
191 | if (IS_ERR(chip->regs)) | ||
192 | return PTR_ERR(chip->regs); | ||
193 | |||
194 | /* Apply default dma_mask if needed */ | ||
195 | if (!dev->dma_mask) { | ||
196 | dev->dma_mask = &dev->coherent_dma_mask; | ||
197 | dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
198 | } | ||
199 | |||
200 | pdata = dev_get_platdata(dev); | ||
201 | if (!pdata) | ||
202 | pdata = dw_dma_parse_dt(pdev); | ||
203 | |||
204 | chip->dev = dev; | ||
205 | |||
206 | err = dw_dma_probe(chip, pdata); | ||
207 | if (err) | ||
208 | return err; | ||
209 | |||
210 | platform_set_drvdata(pdev, chip); | ||
211 | |||
212 | if (pdev->dev.of_node) { | ||
213 | err = of_dma_controller_register(pdev->dev.of_node, | ||
214 | dw_dma_of_xlate, chip->dw); | ||
215 | if (err) | ||
216 | dev_err(&pdev->dev, | ||
217 | "could not register of_dma_controller\n"); | ||
218 | } | ||
219 | |||
220 | if (ACPI_HANDLE(&pdev->dev)) | ||
221 | dw_dma_acpi_controller_register(chip->dw); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int dw_remove(struct platform_device *pdev) | ||
227 | { | ||
228 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | ||
229 | |||
230 | if (pdev->dev.of_node) | ||
231 | of_dma_controller_free(pdev->dev.of_node); | ||
232 | |||
233 | return dw_dma_remove(chip); | ||
234 | } | ||
235 | |||
236 | static void dw_shutdown(struct platform_device *pdev) | ||
237 | { | ||
238 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | ||
239 | |||
240 | dw_dma_shutdown(chip); | ||
241 | } | ||
242 | |||
243 | #ifdef CONFIG_OF | ||
244 | static const struct of_device_id dw_dma_of_id_table[] = { | ||
245 | { .compatible = "snps,dma-spear1340" }, | ||
246 | {} | ||
247 | }; | ||
248 | MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); | ||
249 | #endif | ||
250 | |||
251 | #ifdef CONFIG_ACPI | ||
252 | static const struct acpi_device_id dw_dma_acpi_id_table[] = { | ||
253 | { "INTL9C60", 0 }, | ||
254 | { } | ||
255 | }; | ||
256 | #endif | ||
257 | |||
258 | #ifdef CONFIG_PM_SLEEP | ||
259 | |||
260 | static int dw_suspend_noirq(struct device *dev) | ||
261 | { | ||
262 | struct platform_device *pdev = to_platform_device(dev); | ||
263 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | ||
264 | |||
265 | return dw_dma_suspend(chip); | ||
266 | } | ||
267 | |||
268 | static int dw_resume_noirq(struct device *dev) | ||
269 | { | ||
270 | struct platform_device *pdev = to_platform_device(dev); | ||
271 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | ||
272 | |||
273 | return dw_dma_resume(chip); | ||
274 | } | ||
275 | |||
276 | #else /* !CONFIG_PM_SLEEP */ | ||
277 | |||
278 | #define dw_suspend_noirq NULL | ||
279 | #define dw_resume_noirq NULL | ||
280 | |||
281 | #endif /* !CONFIG_PM_SLEEP */ | ||
282 | |||
283 | static const struct dev_pm_ops dw_dev_pm_ops = { | ||
284 | .suspend_noirq = dw_suspend_noirq, | ||
285 | .resume_noirq = dw_resume_noirq, | ||
286 | .freeze_noirq = dw_suspend_noirq, | ||
287 | .thaw_noirq = dw_resume_noirq, | ||
288 | .restore_noirq = dw_resume_noirq, | ||
289 | .poweroff_noirq = dw_suspend_noirq, | ||
290 | }; | ||
291 | |||
292 | static struct platform_driver dw_driver = { | ||
293 | .probe = dw_probe, | ||
294 | .remove = dw_remove, | ||
295 | .shutdown = dw_shutdown, | ||
296 | .driver = { | ||
297 | .name = "dw_dmac", | ||
298 | .pm = &dw_dev_pm_ops, | ||
299 | .of_match_table = of_match_ptr(dw_dma_of_id_table), | ||
300 | .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table), | ||
301 | }, | ||
302 | }; | ||
303 | |||
304 | static int __init dw_init(void) | ||
305 | { | ||
306 | return platform_driver_register(&dw_driver); | ||
307 | } | ||
308 | subsys_initcall(dw_init); | ||
309 | |||
310 | static void __exit dw_exit(void) | ||
311 | { | ||
312 | platform_driver_unregister(&dw_driver); | ||
313 | } | ||
314 | module_exit(dw_exit); | ||
315 | |||
316 | MODULE_LICENSE("GPL v2"); | ||
317 | MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver"); | ||
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw/regs.h index 9d417200bd57..deb4274f80f4 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw/regs.h | |||
@@ -9,6 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/interrupt.h> | ||
12 | #include <linux/dmaengine.h> | 13 | #include <linux/dmaengine.h> |
13 | #include <linux/dw_dmac.h> | 14 | #include <linux/dw_dmac.h> |
14 | 15 | ||
@@ -100,6 +101,12 @@ struct dw_dma_regs { | |||
100 | u32 DW_PARAMS; | 101 | u32 DW_PARAMS; |
101 | }; | 102 | }; |
102 | 103 | ||
104 | /* | ||
105 | * Big endian I/O access when reading and writing to the DMA controller | ||
106 | * registers. This is needed on some platforms, like the Atmel AVR32 | ||
107 | * architecture. | ||
108 | */ | ||
109 | |||
103 | #ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO | 110 | #ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO |
104 | #define dma_readl_native ioread32be | 111 | #define dma_readl_native ioread32be |
105 | #define dma_writel_native iowrite32be | 112 | #define dma_writel_native iowrite32be |
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 4fc2980556ad..49e8fbdb8983 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c | |||
@@ -1368,7 +1368,7 @@ static int fsldma_of_probe(struct platform_device *op) | |||
1368 | 1368 | ||
1369 | dma_set_mask(&(op->dev), DMA_BIT_MASK(36)); | 1369 | dma_set_mask(&(op->dev), DMA_BIT_MASK(36)); |
1370 | 1370 | ||
1371 | dev_set_drvdata(&op->dev, fdev); | 1371 | platform_set_drvdata(op, fdev); |
1372 | 1372 | ||
1373 | /* | 1373 | /* |
1374 | * We cannot use of_platform_bus_probe() because there is no | 1374 | * We cannot use of_platform_bus_probe() because there is no |
@@ -1417,7 +1417,7 @@ static int fsldma_of_remove(struct platform_device *op) | |||
1417 | struct fsldma_device *fdev; | 1417 | struct fsldma_device *fdev; |
1418 | unsigned int i; | 1418 | unsigned int i; |
1419 | 1419 | ||
1420 | fdev = dev_get_drvdata(&op->dev); | 1420 | fdev = platform_get_drvdata(op); |
1421 | dma_async_device_unregister(&fdev->common); | 1421 | dma_async_device_unregister(&fdev->common); |
1422 | 1422 | ||
1423 | fsldma_free_irqs(fdev); | 1423 | fsldma_free_irqs(fdev); |
@@ -1428,7 +1428,6 @@ static int fsldma_of_remove(struct platform_device *op) | |||
1428 | } | 1428 | } |
1429 | 1429 | ||
1430 | iounmap(fdev->regs); | 1430 | iounmap(fdev->regs); |
1431 | dev_set_drvdata(&op->dev, NULL); | ||
1432 | kfree(fdev); | 1431 | kfree(fdev); |
1433 | 1432 | ||
1434 | return 0; | 1433 | return 0; |
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index f28583370d00..ff2aab973b45 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | #include <linux/dmaengine.h> | 28 | #include <linux/dmaengine.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/of_device.h> | ||
31 | #include <linux/of_dma.h> | ||
30 | 32 | ||
31 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
32 | #include <linux/platform_data/dma-imx.h> | 34 | #include <linux/platform_data/dma-imx.h> |
@@ -186,6 +188,11 @@ struct imxdma_engine { | |||
186 | enum imx_dma_type devtype; | 188 | enum imx_dma_type devtype; |
187 | }; | 189 | }; |
188 | 190 | ||
191 | struct imxdma_filter_data { | ||
192 | struct imxdma_engine *imxdma; | ||
193 | int request; | ||
194 | }; | ||
195 | |||
189 | static struct platform_device_id imx_dma_devtype[] = { | 196 | static struct platform_device_id imx_dma_devtype[] = { |
190 | { | 197 | { |
191 | .name = "imx1-dma", | 198 | .name = "imx1-dma", |
@@ -202,6 +209,22 @@ static struct platform_device_id imx_dma_devtype[] = { | |||
202 | }; | 209 | }; |
203 | MODULE_DEVICE_TABLE(platform, imx_dma_devtype); | 210 | MODULE_DEVICE_TABLE(platform, imx_dma_devtype); |
204 | 211 | ||
212 | static const struct of_device_id imx_dma_of_dev_id[] = { | ||
213 | { | ||
214 | .compatible = "fsl,imx1-dma", | ||
215 | .data = &imx_dma_devtype[IMX1_DMA], | ||
216 | }, { | ||
217 | .compatible = "fsl,imx21-dma", | ||
218 | .data = &imx_dma_devtype[IMX21_DMA], | ||
219 | }, { | ||
220 | .compatible = "fsl,imx27-dma", | ||
221 | .data = &imx_dma_devtype[IMX27_DMA], | ||
222 | }, { | ||
223 | /* sentinel */ | ||
224 | } | ||
225 | }; | ||
226 | MODULE_DEVICE_TABLE(of, imx_dma_of_dev_id); | ||
227 | |||
205 | static inline int is_imx1_dma(struct imxdma_engine *imxdma) | 228 | static inline int is_imx1_dma(struct imxdma_engine *imxdma) |
206 | { | 229 | { |
207 | return imxdma->devtype == IMX1_DMA; | 230 | return imxdma->devtype == IMX1_DMA; |
@@ -996,17 +1019,55 @@ static void imxdma_issue_pending(struct dma_chan *chan) | |||
996 | spin_unlock_irqrestore(&imxdma->lock, flags); | 1019 | spin_unlock_irqrestore(&imxdma->lock, flags); |
997 | } | 1020 | } |
998 | 1021 | ||
1022 | static bool imxdma_filter_fn(struct dma_chan *chan, void *param) | ||
1023 | { | ||
1024 | struct imxdma_filter_data *fdata = param; | ||
1025 | struct imxdma_channel *imxdma_chan = to_imxdma_chan(chan); | ||
1026 | |||
1027 | if (chan->device->dev != fdata->imxdma->dev) | ||
1028 | return false; | ||
1029 | |||
1030 | imxdma_chan->dma_request = fdata->request; | ||
1031 | chan->private = NULL; | ||
1032 | |||
1033 | return true; | ||
1034 | } | ||
1035 | |||
1036 | static struct dma_chan *imxdma_xlate(struct of_phandle_args *dma_spec, | ||
1037 | struct of_dma *ofdma) | ||
1038 | { | ||
1039 | int count = dma_spec->args_count; | ||
1040 | struct imxdma_engine *imxdma = ofdma->of_dma_data; | ||
1041 | struct imxdma_filter_data fdata = { | ||
1042 | .imxdma = imxdma, | ||
1043 | }; | ||
1044 | |||
1045 | if (count != 1) | ||
1046 | return NULL; | ||
1047 | |||
1048 | fdata.request = dma_spec->args[0]; | ||
1049 | |||
1050 | return dma_request_channel(imxdma->dma_device.cap_mask, | ||
1051 | imxdma_filter_fn, &fdata); | ||
1052 | } | ||
1053 | |||
999 | static int __init imxdma_probe(struct platform_device *pdev) | 1054 | static int __init imxdma_probe(struct platform_device *pdev) |
1000 | { | 1055 | { |
1001 | struct imxdma_engine *imxdma; | 1056 | struct imxdma_engine *imxdma; |
1002 | struct resource *res; | 1057 | struct resource *res; |
1058 | const struct of_device_id *of_id; | ||
1003 | int ret, i; | 1059 | int ret, i; |
1004 | int irq, irq_err; | 1060 | int irq, irq_err; |
1005 | 1061 | ||
1062 | of_id = of_match_device(imx_dma_of_dev_id, &pdev->dev); | ||
1063 | if (of_id) | ||
1064 | pdev->id_entry = of_id->data; | ||
1065 | |||
1006 | imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL); | 1066 | imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL); |
1007 | if (!imxdma) | 1067 | if (!imxdma) |
1008 | return -ENOMEM; | 1068 | return -ENOMEM; |
1009 | 1069 | ||
1070 | imxdma->dev = &pdev->dev; | ||
1010 | imxdma->devtype = pdev->id_entry->driver_data; | 1071 | imxdma->devtype = pdev->id_entry->driver_data; |
1011 | 1072 | ||
1012 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1073 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1111,7 +1172,6 @@ static int __init imxdma_probe(struct platform_device *pdev) | |||
1111 | &imxdma->dma_device.channels); | 1172 | &imxdma->dma_device.channels); |
1112 | } | 1173 | } |
1113 | 1174 | ||
1114 | imxdma->dev = &pdev->dev; | ||
1115 | imxdma->dma_device.dev = &pdev->dev; | 1175 | imxdma->dma_device.dev = &pdev->dev; |
1116 | 1176 | ||
1117 | imxdma->dma_device.device_alloc_chan_resources = imxdma_alloc_chan_resources; | 1177 | imxdma->dma_device.device_alloc_chan_resources = imxdma_alloc_chan_resources; |
@@ -1136,8 +1196,19 @@ static int __init imxdma_probe(struct platform_device *pdev) | |||
1136 | goto err; | 1196 | goto err; |
1137 | } | 1197 | } |
1138 | 1198 | ||
1199 | if (pdev->dev.of_node) { | ||
1200 | ret = of_dma_controller_register(pdev->dev.of_node, | ||
1201 | imxdma_xlate, imxdma); | ||
1202 | if (ret) { | ||
1203 | dev_err(&pdev->dev, "unable to register of_dma_controller\n"); | ||
1204 | goto err_of_dma_controller; | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1139 | return 0; | 1208 | return 0; |
1140 | 1209 | ||
1210 | err_of_dma_controller: | ||
1211 | dma_async_device_unregister(&imxdma->dma_device); | ||
1141 | err: | 1212 | err: |
1142 | clk_disable_unprepare(imxdma->dma_ipg); | 1213 | clk_disable_unprepare(imxdma->dma_ipg); |
1143 | clk_disable_unprepare(imxdma->dma_ahb); | 1214 | clk_disable_unprepare(imxdma->dma_ahb); |
@@ -1150,6 +1221,9 @@ static int imxdma_remove(struct platform_device *pdev) | |||
1150 | 1221 | ||
1151 | dma_async_device_unregister(&imxdma->dma_device); | 1222 | dma_async_device_unregister(&imxdma->dma_device); |
1152 | 1223 | ||
1224 | if (pdev->dev.of_node) | ||
1225 | of_dma_controller_free(pdev->dev.of_node); | ||
1226 | |||
1153 | clk_disable_unprepare(imxdma->dma_ipg); | 1227 | clk_disable_unprepare(imxdma->dma_ipg); |
1154 | clk_disable_unprepare(imxdma->dma_ahb); | 1228 | clk_disable_unprepare(imxdma->dma_ahb); |
1155 | 1229 | ||
@@ -1159,6 +1233,7 @@ static int imxdma_remove(struct platform_device *pdev) | |||
1159 | static struct platform_driver imxdma_driver = { | 1233 | static struct platform_driver imxdma_driver = { |
1160 | .driver = { | 1234 | .driver = { |
1161 | .name = "imx-dma", | 1235 | .name = "imx-dma", |
1236 | .of_match_table = imx_dma_of_dev_id, | ||
1162 | }, | 1237 | }, |
1163 | .id_table = imx_dma_devtype, | 1238 | .id_table = imx_dma_devtype, |
1164 | .remove = imxdma_remove, | 1239 | .remove = imxdma_remove, |
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 092867bf795c..1e44b8cf95da 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/dmaengine.h> | 36 | #include <linux/dmaengine.h> |
37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
38 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
39 | #include <linux/of_dma.h> | ||
39 | 40 | ||
40 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
41 | #include <linux/platform_data/dma-imx-sdma.h> | 42 | #include <linux/platform_data/dma-imx-sdma.h> |
@@ -1296,6 +1297,35 @@ err_dma_alloc: | |||
1296 | return ret; | 1297 | return ret; |
1297 | } | 1298 | } |
1298 | 1299 | ||
1300 | static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param) | ||
1301 | { | ||
1302 | struct imx_dma_data *data = fn_param; | ||
1303 | |||
1304 | if (!imx_dma_is_general_purpose(chan)) | ||
1305 | return false; | ||
1306 | |||
1307 | chan->private = data; | ||
1308 | |||
1309 | return true; | ||
1310 | } | ||
1311 | |||
1312 | static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec, | ||
1313 | struct of_dma *ofdma) | ||
1314 | { | ||
1315 | struct sdma_engine *sdma = ofdma->of_dma_data; | ||
1316 | dma_cap_mask_t mask = sdma->dma_device.cap_mask; | ||
1317 | struct imx_dma_data data; | ||
1318 | |||
1319 | if (dma_spec->args_count != 3) | ||
1320 | return NULL; | ||
1321 | |||
1322 | data.dma_request = dma_spec->args[0]; | ||
1323 | data.peripheral_type = dma_spec->args[1]; | ||
1324 | data.priority = dma_spec->args[2]; | ||
1325 | |||
1326 | return dma_request_channel(mask, sdma_filter_fn, &data); | ||
1327 | } | ||
1328 | |||
1299 | static int __init sdma_probe(struct platform_device *pdev) | 1329 | static int __init sdma_probe(struct platform_device *pdev) |
1300 | { | 1330 | { |
1301 | const struct of_device_id *of_id = | 1331 | const struct of_device_id *of_id = |
@@ -1443,10 +1473,20 @@ static int __init sdma_probe(struct platform_device *pdev) | |||
1443 | goto err_init; | 1473 | goto err_init; |
1444 | } | 1474 | } |
1445 | 1475 | ||
1476 | if (np) { | ||
1477 | ret = of_dma_controller_register(np, sdma_xlate, sdma); | ||
1478 | if (ret) { | ||
1479 | dev_err(&pdev->dev, "failed to register controller\n"); | ||
1480 | goto err_register; | ||
1481 | } | ||
1482 | } | ||
1483 | |||
1446 | dev_info(sdma->dev, "initialized\n"); | 1484 | dev_info(sdma->dev, "initialized\n"); |
1447 | 1485 | ||
1448 | return 0; | 1486 | return 0; |
1449 | 1487 | ||
1488 | err_register: | ||
1489 | dma_async_device_unregister(&sdma->dma_device); | ||
1450 | err_init: | 1490 | err_init: |
1451 | kfree(sdma->script_addrs); | 1491 | kfree(sdma->script_addrs); |
1452 | err_alloc: | 1492 | err_alloc: |
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 43d5a6c33297..9b9366537d73 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c | |||
@@ -154,6 +154,10 @@ static void mmp_tdma_disable_chan(struct mmp_tdma_chan *tdmac) | |||
154 | { | 154 | { |
155 | writel(readl(tdmac->reg_base + TDCR) & ~TDCR_CHANEN, | 155 | writel(readl(tdmac->reg_base + TDCR) & ~TDCR_CHANEN, |
156 | tdmac->reg_base + TDCR); | 156 | tdmac->reg_base + TDCR); |
157 | |||
158 | /* disable irq */ | ||
159 | writel(0, tdmac->reg_base + TDIMR); | ||
160 | |||
157 | tdmac->status = DMA_SUCCESS; | 161 | tdmac->status = DMA_SUCCESS; |
158 | } | 162 | } |
159 | 163 | ||
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index b48a79c28845..719593002ab7 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c | |||
@@ -693,7 +693,7 @@ static bool mxs_dma_filter_fn(struct dma_chan *chan, void *fn_param) | |||
693 | return true; | 693 | return true; |
694 | } | 694 | } |
695 | 695 | ||
696 | struct dma_chan *mxs_dma_xlate(struct of_phandle_args *dma_spec, | 696 | static struct dma_chan *mxs_dma_xlate(struct of_phandle_args *dma_spec, |
697 | struct of_dma *ofdma) | 697 | struct of_dma *ofdma) |
698 | { | 698 | { |
699 | struct mxs_dma_engine *mxs_dma = ofdma->of_dma_data; | 699 | struct mxs_dma_engine *mxs_dma = ofdma->of_dma_data; |
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index 7aa0864cd487..75334bdd2c56 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c | |||
@@ -35,8 +35,7 @@ static struct of_dma *of_dma_find_controller(struct of_phandle_args *dma_spec) | |||
35 | struct of_dma *ofdma; | 35 | struct of_dma *ofdma; |
36 | 36 | ||
37 | list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) | 37 | list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) |
38 | if ((ofdma->of_node == dma_spec->np) && | 38 | if (ofdma->of_node == dma_spec->np) |
39 | (ofdma->of_dma_nbcells == dma_spec->args_count)) | ||
40 | return ofdma; | 39 | return ofdma; |
41 | 40 | ||
42 | pr_debug("%s: can't find DMA controller %s\n", __func__, | 41 | pr_debug("%s: can't find DMA controller %s\n", __func__, |
@@ -64,8 +63,6 @@ int of_dma_controller_register(struct device_node *np, | |||
64 | void *data) | 63 | void *data) |
65 | { | 64 | { |
66 | struct of_dma *ofdma; | 65 | struct of_dma *ofdma; |
67 | int nbcells; | ||
68 | const __be32 *prop; | ||
69 | 66 | ||
70 | if (!np || !of_dma_xlate) { | 67 | if (!np || !of_dma_xlate) { |
71 | pr_err("%s: not enough information provided\n", __func__); | 68 | pr_err("%s: not enough information provided\n", __func__); |
@@ -76,19 +73,7 @@ int of_dma_controller_register(struct device_node *np, | |||
76 | if (!ofdma) | 73 | if (!ofdma) |
77 | return -ENOMEM; | 74 | return -ENOMEM; |
78 | 75 | ||
79 | prop = of_get_property(np, "#dma-cells", NULL); | ||
80 | if (prop) | ||
81 | nbcells = be32_to_cpup(prop); | ||
82 | |||
83 | if (!prop || !nbcells) { | ||
84 | pr_err("%s: #dma-cells property is missing or invalid\n", | ||
85 | __func__); | ||
86 | kfree(ofdma); | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | |||
90 | ofdma->of_node = np; | 76 | ofdma->of_node = np; |
91 | ofdma->of_dma_nbcells = nbcells; | ||
92 | ofdma->of_dma_xlate = of_dma_xlate; | 77 | ofdma->of_dma_xlate = of_dma_xlate; |
93 | ofdma->of_dma_data = data; | 78 | ofdma->of_dma_data = data; |
94 | 79 | ||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 7ec82f0667eb..593827b3fdd4 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c | |||
@@ -157,7 +157,6 @@ enum pl330_reqtype { | |||
157 | #define PERIPH_REV_R0P0 0 | 157 | #define PERIPH_REV_R0P0 0 |
158 | #define PERIPH_REV_R1P0 1 | 158 | #define PERIPH_REV_R1P0 1 |
159 | #define PERIPH_REV_R1P1 2 | 159 | #define PERIPH_REV_R1P1 2 |
160 | #define PCELL_ID 0xff0 | ||
161 | 160 | ||
162 | #define CR0_PERIPH_REQ_SET (1 << 0) | 161 | #define CR0_PERIPH_REQ_SET (1 << 0) |
163 | #define CR0_BOOT_EN_SET (1 << 1) | 162 | #define CR0_BOOT_EN_SET (1 << 1) |
@@ -193,8 +192,6 @@ enum pl330_reqtype { | |||
193 | #define INTEG_CFG 0x0 | 192 | #define INTEG_CFG 0x0 |
194 | #define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12)) | 193 | #define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12)) |
195 | 194 | ||
196 | #define PCELL_ID_VAL 0xb105f00d | ||
197 | |||
198 | #define PL330_STATE_STOPPED (1 << 0) | 195 | #define PL330_STATE_STOPPED (1 << 0) |
199 | #define PL330_STATE_EXECUTING (1 << 1) | 196 | #define PL330_STATE_EXECUTING (1 << 1) |
200 | #define PL330_STATE_WFE (1 << 2) | 197 | #define PL330_STATE_WFE (1 << 2) |
@@ -292,7 +289,6 @@ static unsigned cmd_line; | |||
292 | /* Populated by the PL330 core driver for DMA API driver's info */ | 289 | /* Populated by the PL330 core driver for DMA API driver's info */ |
293 | struct pl330_config { | 290 | struct pl330_config { |
294 | u32 periph_id; | 291 | u32 periph_id; |
295 | u32 pcell_id; | ||
296 | #define DMAC_MODE_NS (1 << 0) | 292 | #define DMAC_MODE_NS (1 << 0) |
297 | unsigned int mode; | 293 | unsigned int mode; |
298 | unsigned int data_bus_width:10; /* In number of bits */ | 294 | unsigned int data_bus_width:10; /* In number of bits */ |
@@ -505,7 +501,7 @@ struct pl330_dmac { | |||
505 | /* Maximum possible events/irqs */ | 501 | /* Maximum possible events/irqs */ |
506 | int events[32]; | 502 | int events[32]; |
507 | /* BUS address of MicroCode buffer */ | 503 | /* BUS address of MicroCode buffer */ |
508 | u32 mcode_bus; | 504 | dma_addr_t mcode_bus; |
509 | /* CPU address of MicroCode buffer */ | 505 | /* CPU address of MicroCode buffer */ |
510 | void *mcode_cpu; | 506 | void *mcode_cpu; |
511 | /* List of all Channel threads */ | 507 | /* List of all Channel threads */ |
@@ -650,19 +646,6 @@ static inline bool _manager_ns(struct pl330_thread *thrd) | |||
650 | return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false; | 646 | return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false; |
651 | } | 647 | } |
652 | 648 | ||
653 | static inline u32 get_id(struct pl330_info *pi, u32 off) | ||
654 | { | ||
655 | void __iomem *regs = pi->base; | ||
656 | u32 id = 0; | ||
657 | |||
658 | id |= (readb(regs + off + 0x0) << 0); | ||
659 | id |= (readb(regs + off + 0x4) << 8); | ||
660 | id |= (readb(regs + off + 0x8) << 16); | ||
661 | id |= (readb(regs + off + 0xc) << 24); | ||
662 | |||
663 | return id; | ||
664 | } | ||
665 | |||
666 | static inline u32 get_revision(u32 periph_id) | 649 | static inline u32 get_revision(u32 periph_id) |
667 | { | 650 | { |
668 | return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK; | 651 | return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK; |
@@ -1986,9 +1969,6 @@ static void read_dmac_config(struct pl330_info *pi) | |||
1986 | pi->pcfg.num_events = val; | 1969 | pi->pcfg.num_events = val; |
1987 | 1970 | ||
1988 | pi->pcfg.irq_ns = readl(regs + CR3); | 1971 | pi->pcfg.irq_ns = readl(regs + CR3); |
1989 | |||
1990 | pi->pcfg.periph_id = get_id(pi, PERIPH_ID); | ||
1991 | pi->pcfg.pcell_id = get_id(pi, PCELL_ID); | ||
1992 | } | 1972 | } |
1993 | 1973 | ||
1994 | static inline void _reset_thread(struct pl330_thread *thrd) | 1974 | static inline void _reset_thread(struct pl330_thread *thrd) |
@@ -2098,10 +2078,8 @@ static int pl330_add(struct pl330_info *pi) | |||
2098 | regs = pi->base; | 2078 | regs = pi->base; |
2099 | 2079 | ||
2100 | /* Check if we can handle this DMAC */ | 2080 | /* Check if we can handle this DMAC */ |
2101 | if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL | 2081 | if ((pi->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) { |
2102 | || get_id(pi, PCELL_ID) != PCELL_ID_VAL) { | 2082 | dev_err(pi->dev, "PERIPH_ID 0x%x !\n", pi->pcfg.periph_id); |
2103 | dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n", | ||
2104 | get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID)); | ||
2105 | return -EINVAL; | 2083 | return -EINVAL; |
2106 | } | 2084 | } |
2107 | 2085 | ||
@@ -2916,6 +2894,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
2916 | if (ret) | 2894 | if (ret) |
2917 | return ret; | 2895 | return ret; |
2918 | 2896 | ||
2897 | pi->pcfg.periph_id = adev->periphid; | ||
2919 | ret = pl330_add(pi); | 2898 | ret = pl330_add(pi); |
2920 | if (ret) | 2899 | if (ret) |
2921 | goto probe_err1; | 2900 | goto probe_err1; |
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 1e220f8dfd8c..370ff8265630 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c | |||
@@ -4434,7 +4434,7 @@ static int ppc440spe_adma_probe(struct platform_device *ofdev) | |||
4434 | adev->dev = &ofdev->dev; | 4434 | adev->dev = &ofdev->dev; |
4435 | adev->common.dev = &ofdev->dev; | 4435 | adev->common.dev = &ofdev->dev; |
4436 | INIT_LIST_HEAD(&adev->common.channels); | 4436 | INIT_LIST_HEAD(&adev->common.channels); |
4437 | dev_set_drvdata(&ofdev->dev, adev); | 4437 | platform_set_drvdata(ofdev, adev); |
4438 | 4438 | ||
4439 | /* create a channel */ | 4439 | /* create a channel */ |
4440 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); | 4440 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); |
@@ -4547,14 +4547,13 @@ out: | |||
4547 | */ | 4547 | */ |
4548 | static int ppc440spe_adma_remove(struct platform_device *ofdev) | 4548 | static int ppc440spe_adma_remove(struct platform_device *ofdev) |
4549 | { | 4549 | { |
4550 | struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); | 4550 | struct ppc440spe_adma_device *adev = platform_get_drvdata(ofdev); |
4551 | struct device_node *np = ofdev->dev.of_node; | 4551 | struct device_node *np = ofdev->dev.of_node; |
4552 | struct resource res; | 4552 | struct resource res; |
4553 | struct dma_chan *chan, *_chan; | 4553 | struct dma_chan *chan, *_chan; |
4554 | struct ppc_dma_chan_ref *ref, *_ref; | 4554 | struct ppc_dma_chan_ref *ref, *_ref; |
4555 | struct ppc440spe_adma_chan *ppc440spe_chan; | 4555 | struct ppc440spe_adma_chan *ppc440spe_chan; |
4556 | 4556 | ||
4557 | dev_set_drvdata(&ofdev->dev, NULL); | ||
4558 | if (adev->id < PPC440SPE_ADMA_ENGINES_NUM) | 4557 | if (adev->id < PPC440SPE_ADMA_ENGINES_NUM) |
4559 | ppc440spe_adma_devices[adev->id] = -1; | 4558 | ppc440spe_adma_devices[adev->id] = -1; |
4560 | 4559 | ||
diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile index c07ca4612e46..c962138dde96 100644 --- a/drivers/dma/sh/Makefile +++ b/drivers/dma/sh/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o | 1 | obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o |
2 | obj-$(CONFIG_SH_DMAE) += shdma.o | 2 | obj-$(CONFIG_SH_DMAE) += shdma.o |
3 | obj-$(CONFIG_SUDMAC) += sudmac.o | 3 | obj-$(CONFIG_SUDMAC) += sudmac.o |
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c index 4acb85a10250..28ca36121631 100644 --- a/drivers/dma/sh/shdma-base.c +++ b/drivers/dma/sh/shdma-base.c | |||
@@ -175,7 +175,18 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) | |||
175 | { | 175 | { |
176 | struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); | 176 | struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); |
177 | const struct shdma_ops *ops = sdev->ops; | 177 | const struct shdma_ops *ops = sdev->ops; |
178 | int ret; | 178 | int ret, match; |
179 | |||
180 | if (schan->dev->of_node) { | ||
181 | match = schan->hw_req; | ||
182 | ret = ops->set_slave(schan, match, true); | ||
183 | if (ret < 0) | ||
184 | return ret; | ||
185 | |||
186 | slave_id = schan->slave_id; | ||
187 | } else { | ||
188 | match = slave_id; | ||
189 | } | ||
179 | 190 | ||
180 | if (slave_id < 0 || slave_id >= slave_num) | 191 | if (slave_id < 0 || slave_id >= slave_num) |
181 | return -EINVAL; | 192 | return -EINVAL; |
@@ -183,7 +194,7 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) | |||
183 | if (test_and_set_bit(slave_id, shdma_slave_used)) | 194 | if (test_and_set_bit(slave_id, shdma_slave_used)) |
184 | return -EBUSY; | 195 | return -EBUSY; |
185 | 196 | ||
186 | ret = ops->set_slave(schan, slave_id, false); | 197 | ret = ops->set_slave(schan, match, false); |
187 | if (ret < 0) { | 198 | if (ret < 0) { |
188 | clear_bit(slave_id, shdma_slave_used); | 199 | clear_bit(slave_id, shdma_slave_used); |
189 | return ret; | 200 | return ret; |
@@ -206,23 +217,26 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) | |||
206 | * services would have to provide their own filters, which first would check | 217 | * services would have to provide their own filters, which first would check |
207 | * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do | 218 | * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do |
208 | * this, and only then, in case of a match, call this common filter. | 219 | * this, and only then, in case of a match, call this common filter. |
220 | * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate(). | ||
221 | * In that case the MID-RID value is used for slave channel filtering and is | ||
222 | * passed to this function in the "arg" parameter. | ||
209 | */ | 223 | */ |
210 | bool shdma_chan_filter(struct dma_chan *chan, void *arg) | 224 | bool shdma_chan_filter(struct dma_chan *chan, void *arg) |
211 | { | 225 | { |
212 | struct shdma_chan *schan = to_shdma_chan(chan); | 226 | struct shdma_chan *schan = to_shdma_chan(chan); |
213 | struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); | 227 | struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); |
214 | const struct shdma_ops *ops = sdev->ops; | 228 | const struct shdma_ops *ops = sdev->ops; |
215 | int slave_id = (int)arg; | 229 | int match = (int)arg; |
216 | int ret; | 230 | int ret; |
217 | 231 | ||
218 | if (slave_id < 0) | 232 | if (match < 0) |
219 | /* No slave requested - arbitrary channel */ | 233 | /* No slave requested - arbitrary channel */ |
220 | return true; | 234 | return true; |
221 | 235 | ||
222 | if (slave_id >= slave_num) | 236 | if (!schan->dev->of_node && match >= slave_num) |
223 | return false; | 237 | return false; |
224 | 238 | ||
225 | ret = ops->set_slave(schan, slave_id, true); | 239 | ret = ops->set_slave(schan, match, true); |
226 | if (ret < 0) | 240 | if (ret < 0) |
227 | return false; | 241 | return false; |
228 | 242 | ||
diff --git a/drivers/dma/sh/shdma-of.c b/drivers/dma/sh/shdma-of.c new file mode 100644 index 000000000000..11bcb05cd79c --- /dev/null +++ b/drivers/dma/sh/shdma-of.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * SHDMA Device Tree glue | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Electronics Inc. | ||
5 | * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
6 | * | ||
7 | * This is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/dmaengine.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_dma.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/shdma-base.h> | ||
19 | |||
20 | #define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan) | ||
21 | |||
22 | static struct dma_chan *shdma_of_xlate(struct of_phandle_args *dma_spec, | ||
23 | struct of_dma *ofdma) | ||
24 | { | ||
25 | u32 id = dma_spec->args[0]; | ||
26 | dma_cap_mask_t mask; | ||
27 | struct dma_chan *chan; | ||
28 | |||
29 | if (dma_spec->args_count != 1) | ||
30 | return NULL; | ||
31 | |||
32 | dma_cap_zero(mask); | ||
33 | /* Only slave DMA channels can be allocated via DT */ | ||
34 | dma_cap_set(DMA_SLAVE, mask); | ||
35 | |||
36 | chan = dma_request_channel(mask, shdma_chan_filter, (void *)id); | ||
37 | if (chan) | ||
38 | to_shdma_chan(chan)->hw_req = id; | ||
39 | |||
40 | return chan; | ||
41 | } | ||
42 | |||
43 | static int shdma_of_probe(struct platform_device *pdev) | ||
44 | { | ||
45 | const struct of_dev_auxdata *lookup = pdev->dev.platform_data; | ||
46 | int ret; | ||
47 | |||
48 | if (!lookup) | ||
49 | return -EINVAL; | ||
50 | |||
51 | ret = of_dma_controller_register(pdev->dev.of_node, | ||
52 | shdma_of_xlate, pdev); | ||
53 | if (ret < 0) | ||
54 | return ret; | ||
55 | |||
56 | ret = of_platform_populate(pdev->dev.of_node, NULL, lookup, &pdev->dev); | ||
57 | if (ret < 0) | ||
58 | of_dma_controller_free(pdev->dev.of_node); | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static const struct of_device_id shdma_of_match[] = { | ||
64 | { .compatible = "renesas,shdma-mux", }, | ||
65 | { } | ||
66 | }; | ||
67 | MODULE_DEVICE_TABLE(of, sh_dmae_of_match); | ||
68 | |||
69 | static struct platform_driver shdma_of = { | ||
70 | .driver = { | ||
71 | .owner = THIS_MODULE, | ||
72 | .name = "shdma-of", | ||
73 | .of_match_table = shdma_of_match, | ||
74 | }, | ||
75 | .probe = shdma_of_probe, | ||
76 | }; | ||
77 | |||
78 | module_platform_driver(shdma_of); | ||
79 | |||
80 | MODULE_LICENSE("GPL v2"); | ||
81 | MODULE_DESCRIPTION("SH-DMA driver DT glue"); | ||
82 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c index b70709b030d8..b67f45f5c271 100644 --- a/drivers/dma/sh/shdma.c +++ b/drivers/dma/sh/shdma.c | |||
@@ -301,20 +301,32 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan, | |||
301 | } | 301 | } |
302 | } | 302 | } |
303 | 303 | ||
304 | /* | ||
305 | * Find a slave channel configuration from the contoller list by either a slave | ||
306 | * ID in the non-DT case, or by a MID/RID value in the DT case | ||
307 | */ | ||
304 | static const struct sh_dmae_slave_config *dmae_find_slave( | 308 | static const struct sh_dmae_slave_config *dmae_find_slave( |
305 | struct sh_dmae_chan *sh_chan, int slave_id) | 309 | struct sh_dmae_chan *sh_chan, int match) |
306 | { | 310 | { |
307 | struct sh_dmae_device *shdev = to_sh_dev(sh_chan); | 311 | struct sh_dmae_device *shdev = to_sh_dev(sh_chan); |
308 | struct sh_dmae_pdata *pdata = shdev->pdata; | 312 | struct sh_dmae_pdata *pdata = shdev->pdata; |
309 | const struct sh_dmae_slave_config *cfg; | 313 | const struct sh_dmae_slave_config *cfg; |
310 | int i; | 314 | int i; |
311 | 315 | ||
312 | if (slave_id >= SH_DMA_SLAVE_NUMBER) | 316 | if (!sh_chan->shdma_chan.dev->of_node) { |
313 | return NULL; | 317 | if (match >= SH_DMA_SLAVE_NUMBER) |
318 | return NULL; | ||
314 | 319 | ||
315 | for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) | 320 | for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) |
316 | if (cfg->slave_id == slave_id) | 321 | if (cfg->slave_id == match) |
317 | return cfg; | 322 | return cfg; |
323 | } else { | ||
324 | for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) | ||
325 | if (cfg->mid_rid == match) { | ||
326 | sh_chan->shdma_chan.slave_id = cfg->slave_id; | ||
327 | return cfg; | ||
328 | } | ||
329 | } | ||
318 | 330 | ||
319 | return NULL; | 331 | return NULL; |
320 | } | 332 | } |
@@ -729,7 +741,7 @@ static int sh_dmae_probe(struct platform_device *pdev) | |||
729 | goto eshdma; | 741 | goto eshdma; |
730 | 742 | ||
731 | /* platform data */ | 743 | /* platform data */ |
732 | shdev->pdata = pdev->dev.platform_data; | 744 | shdev->pdata = pdata; |
733 | 745 | ||
734 | if (pdata->chcr_offset) | 746 | if (pdata->chcr_offset) |
735 | shdev->chcr_offset = pdata->chcr_offset; | 747 | shdev->chcr_offset = pdata->chcr_offset; |
@@ -920,11 +932,18 @@ static int sh_dmae_remove(struct platform_device *pdev) | |||
920 | return 0; | 932 | return 0; |
921 | } | 933 | } |
922 | 934 | ||
935 | static const struct of_device_id sh_dmae_of_match[] = { | ||
936 | { .compatible = "renesas,shdma", }, | ||
937 | { } | ||
938 | }; | ||
939 | MODULE_DEVICE_TABLE(of, sh_dmae_of_match); | ||
940 | |||
923 | static struct platform_driver sh_dmae_driver = { | 941 | static struct platform_driver sh_dmae_driver = { |
924 | .driver = { | 942 | .driver = { |
925 | .owner = THIS_MODULE, | 943 | .owner = THIS_MODULE, |
926 | .pm = &sh_dmae_pm, | 944 | .pm = &sh_dmae_pm, |
927 | .name = SH_DMAE_DRV_NAME, | 945 | .name = SH_DMAE_DRV_NAME, |
946 | .of_match_table = sh_dmae_of_match, | ||
928 | }, | 947 | }, |
929 | .remove = sh_dmae_remove, | 948 | .remove = sh_dmae_remove, |
930 | .shutdown = sh_dmae_shutdown, | 949 | .shutdown = sh_dmae_shutdown, |
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 1765a0a2736d..716b23e4f327 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c | |||
@@ -466,12 +466,29 @@ static enum dma_status | |||
466 | sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | 466 | sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, |
467 | struct dma_tx_state *txstate) | 467 | struct dma_tx_state *txstate) |
468 | { | 468 | { |
469 | struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan); | ||
469 | struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); | 470 | struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); |
470 | unsigned long flags; | 471 | unsigned long flags; |
471 | enum dma_status ret; | 472 | enum dma_status ret; |
473 | struct sirfsoc_dma_desc *sdesc; | ||
474 | int cid = schan->chan.chan_id; | ||
475 | unsigned long dma_pos; | ||
476 | unsigned long dma_request_bytes; | ||
477 | unsigned long residue; | ||
472 | 478 | ||
473 | spin_lock_irqsave(&schan->lock, flags); | 479 | spin_lock_irqsave(&schan->lock, flags); |
480 | |||
481 | sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc, | ||
482 | node); | ||
483 | dma_request_bytes = (sdesc->xlen + 1) * (sdesc->ylen + 1) * | ||
484 | (sdesc->width * SIRFSOC_DMA_WORD_LEN); | ||
485 | |||
474 | ret = dma_cookie_status(chan, cookie, txstate); | 486 | ret = dma_cookie_status(chan, cookie, txstate); |
487 | dma_pos = readl_relaxed(sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_ADDR) | ||
488 | << 2; | ||
489 | residue = dma_request_bytes - (dma_pos - sdesc->addr); | ||
490 | dma_set_residue(txstate, residue); | ||
491 | |||
475 | spin_unlock_irqrestore(&schan->lock, flags); | 492 | spin_unlock_irqrestore(&schan->lock, flags); |
476 | 493 | ||
477 | return ret; | 494 | return ret; |
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 33f59ecd256e..f137914d7b16 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c | |||
@@ -1191,6 +1191,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) | |||
1191 | list_splice_init(&tdc->free_dma_desc, &dma_desc_list); | 1191 | list_splice_init(&tdc->free_dma_desc, &dma_desc_list); |
1192 | INIT_LIST_HEAD(&tdc->cb_desc); | 1192 | INIT_LIST_HEAD(&tdc->cb_desc); |
1193 | tdc->config_init = false; | 1193 | tdc->config_init = false; |
1194 | tdc->isr_handler = NULL; | ||
1194 | spin_unlock_irqrestore(&tdc->lock, flags); | 1195 | spin_unlock_irqrestore(&tdc->lock, flags); |
1195 | 1196 | ||
1196 | while (!list_empty(&dma_desc_list)) { | 1197 | while (!list_empty(&dma_desc_list)) { |
@@ -1334,7 +1335,7 @@ static int tegra_dma_probe(struct platform_device *pdev) | |||
1334 | if (ret) { | 1335 | if (ret) { |
1335 | dev_err(&pdev->dev, | 1336 | dev_err(&pdev->dev, |
1336 | "request_irq failed with err %d channel %d\n", | 1337 | "request_irq failed with err %d channel %d\n", |
1337 | i, ret); | 1338 | ret, i); |
1338 | goto err_irq; | 1339 | goto err_irq; |
1339 | } | 1340 | } |
1340 | 1341 | ||
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index 26107ba6edb3..0ef43c136aa7 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c | |||
@@ -811,8 +811,6 @@ static int td_remove(struct platform_device *pdev) | |||
811 | kfree(td); | 811 | kfree(td); |
812 | release_mem_region(iomem->start, resource_size(iomem)); | 812 | release_mem_region(iomem->start, resource_size(iomem)); |
813 | 813 | ||
814 | platform_set_drvdata(pdev, NULL); | ||
815 | |||
816 | dev_dbg(&pdev->dev, "Removed...\n"); | 814 | dev_dbg(&pdev->dev, "Removed...\n"); |
817 | return 0; | 815 | return 0; |
818 | } | 816 | } |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 0aaece9107c7..315dcc6ec1f5 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #define MTD_PARAM_LEN_MAX 64 | 47 | #define MTD_PARAM_LEN_MAX 64 |
48 | 48 | ||
49 | /* Maximum number of comma-separated items in the 'mtd=' parameter */ | 49 | /* Maximum number of comma-separated items in the 'mtd=' parameter */ |
50 | #define MTD_PARAM_MAX_COUNT 3 | 50 | #define MTD_PARAM_MAX_COUNT 4 |
51 | 51 | ||
52 | /* Maximum value for the number of bad PEBs per 1024 PEBs */ | 52 | /* Maximum value for the number of bad PEBs per 1024 PEBs */ |
53 | #define MAX_MTD_UBI_BEB_LIMIT 768 | 53 | #define MAX_MTD_UBI_BEB_LIMIT 768 |
@@ -67,6 +67,7 @@ | |||
67 | */ | 67 | */ |
68 | struct mtd_dev_param { | 68 | struct mtd_dev_param { |
69 | char name[MTD_PARAM_LEN_MAX]; | 69 | char name[MTD_PARAM_LEN_MAX]; |
70 | int ubi_num; | ||
70 | int vid_hdr_offs; | 71 | int vid_hdr_offs; |
71 | int max_beb_per1024; | 72 | int max_beb_per1024; |
72 | }; | 73 | }; |
@@ -1261,11 +1262,15 @@ static int __init ubi_init(void) | |||
1261 | mtd = open_mtd_device(p->name); | 1262 | mtd = open_mtd_device(p->name); |
1262 | if (IS_ERR(mtd)) { | 1263 | if (IS_ERR(mtd)) { |
1263 | err = PTR_ERR(mtd); | 1264 | err = PTR_ERR(mtd); |
1264 | goto out_detach; | 1265 | ubi_err("cannot open mtd %s, error %d", p->name, err); |
1266 | /* See comment below re-ubi_is_module(). */ | ||
1267 | if (ubi_is_module()) | ||
1268 | goto out_detach; | ||
1269 | continue; | ||
1265 | } | 1270 | } |
1266 | 1271 | ||
1267 | mutex_lock(&ubi_devices_mutex); | 1272 | mutex_lock(&ubi_devices_mutex); |
1268 | err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, | 1273 | err = ubi_attach_mtd_dev(mtd, p->ubi_num, |
1269 | p->vid_hdr_offs, p->max_beb_per1024); | 1274 | p->vid_hdr_offs, p->max_beb_per1024); |
1270 | mutex_unlock(&ubi_devices_mutex); | 1275 | mutex_unlock(&ubi_devices_mutex); |
1271 | if (err < 0) { | 1276 | if (err < 0) { |
@@ -1309,7 +1314,7 @@ out_version: | |||
1309 | out_class: | 1314 | out_class: |
1310 | class_destroy(ubi_class); | 1315 | class_destroy(ubi_class); |
1311 | out: | 1316 | out: |
1312 | ubi_err("UBI error: cannot initialize UBI, error %d", err); | 1317 | ubi_err("cannot initialize UBI, error %d", err); |
1313 | return err; | 1318 | return err; |
1314 | } | 1319 | } |
1315 | late_initcall(ubi_init); | 1320 | late_initcall(ubi_init); |
@@ -1346,7 +1351,7 @@ static int __init bytes_str_to_int(const char *str) | |||
1346 | 1351 | ||
1347 | result = simple_strtoul(str, &endp, 0); | 1352 | result = simple_strtoul(str, &endp, 0); |
1348 | if (str == endp || result >= INT_MAX) { | 1353 | if (str == endp || result >= INT_MAX) { |
1349 | ubi_err("UBI error: incorrect bytes count: \"%s\"\n", str); | 1354 | ubi_err("incorrect bytes count: \"%s\"\n", str); |
1350 | return -EINVAL; | 1355 | return -EINVAL; |
1351 | } | 1356 | } |
1352 | 1357 | ||
@@ -1362,7 +1367,7 @@ static int __init bytes_str_to_int(const char *str) | |||
1362 | case '\0': | 1367 | case '\0': |
1363 | break; | 1368 | break; |
1364 | default: | 1369 | default: |
1365 | ubi_err("UBI error: incorrect bytes count: \"%s\"\n", str); | 1370 | ubi_err("incorrect bytes count: \"%s\"\n", str); |
1366 | return -EINVAL; | 1371 | return -EINVAL; |
1367 | } | 1372 | } |
1368 | 1373 | ||
@@ -1383,20 +1388,20 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) | |||
1383 | struct mtd_dev_param *p; | 1388 | struct mtd_dev_param *p; |
1384 | char buf[MTD_PARAM_LEN_MAX]; | 1389 | char buf[MTD_PARAM_LEN_MAX]; |
1385 | char *pbuf = &buf[0]; | 1390 | char *pbuf = &buf[0]; |
1386 | char *tokens[MTD_PARAM_MAX_COUNT]; | 1391 | char *tokens[MTD_PARAM_MAX_COUNT], *token; |
1387 | 1392 | ||
1388 | if (!val) | 1393 | if (!val) |
1389 | return -EINVAL; | 1394 | return -EINVAL; |
1390 | 1395 | ||
1391 | if (mtd_devs == UBI_MAX_DEVICES) { | 1396 | if (mtd_devs == UBI_MAX_DEVICES) { |
1392 | ubi_err("UBI error: too many parameters, max. is %d\n", | 1397 | ubi_err("too many parameters, max. is %d\n", |
1393 | UBI_MAX_DEVICES); | 1398 | UBI_MAX_DEVICES); |
1394 | return -EINVAL; | 1399 | return -EINVAL; |
1395 | } | 1400 | } |
1396 | 1401 | ||
1397 | len = strnlen(val, MTD_PARAM_LEN_MAX); | 1402 | len = strnlen(val, MTD_PARAM_LEN_MAX); |
1398 | if (len == MTD_PARAM_LEN_MAX) { | 1403 | if (len == MTD_PARAM_LEN_MAX) { |
1399 | ubi_err("UBI error: parameter \"%s\" is too long, max. is %d\n", | 1404 | ubi_err("parameter \"%s\" is too long, max. is %d\n", |
1400 | val, MTD_PARAM_LEN_MAX); | 1405 | val, MTD_PARAM_LEN_MAX); |
1401 | return -EINVAL; | 1406 | return -EINVAL; |
1402 | } | 1407 | } |
@@ -1416,44 +1421,60 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) | |||
1416 | tokens[i] = strsep(&pbuf, ","); | 1421 | tokens[i] = strsep(&pbuf, ","); |
1417 | 1422 | ||
1418 | if (pbuf) { | 1423 | if (pbuf) { |
1419 | ubi_err("UBI error: too many arguments at \"%s\"\n", val); | 1424 | ubi_err("too many arguments at \"%s\"\n", val); |
1420 | return -EINVAL; | 1425 | return -EINVAL; |
1421 | } | 1426 | } |
1422 | 1427 | ||
1423 | p = &mtd_dev_param[mtd_devs]; | 1428 | p = &mtd_dev_param[mtd_devs]; |
1424 | strcpy(&p->name[0], tokens[0]); | 1429 | strcpy(&p->name[0], tokens[0]); |
1425 | 1430 | ||
1426 | if (tokens[1]) | 1431 | token = tokens[1]; |
1427 | p->vid_hdr_offs = bytes_str_to_int(tokens[1]); | 1432 | if (token) { |
1433 | p->vid_hdr_offs = bytes_str_to_int(token); | ||
1428 | 1434 | ||
1429 | if (p->vid_hdr_offs < 0) | 1435 | if (p->vid_hdr_offs < 0) |
1430 | return p->vid_hdr_offs; | 1436 | return p->vid_hdr_offs; |
1437 | } | ||
1431 | 1438 | ||
1432 | if (tokens[2]) { | 1439 | token = tokens[2]; |
1433 | int err = kstrtoint(tokens[2], 10, &p->max_beb_per1024); | 1440 | if (token) { |
1441 | int err = kstrtoint(token, 10, &p->max_beb_per1024); | ||
1434 | 1442 | ||
1435 | if (err) { | 1443 | if (err) { |
1436 | ubi_err("UBI error: bad value for max_beb_per1024 parameter: %s", | 1444 | ubi_err("bad value for max_beb_per1024 parameter: %s", |
1437 | tokens[2]); | 1445 | token); |
1438 | return -EINVAL; | 1446 | return -EINVAL; |
1439 | } | 1447 | } |
1440 | } | 1448 | } |
1441 | 1449 | ||
1450 | token = tokens[3]; | ||
1451 | if (token) { | ||
1452 | int err = kstrtoint(token, 10, &p->ubi_num); | ||
1453 | |||
1454 | if (err) { | ||
1455 | ubi_err("bad value for ubi_num parameter: %s", token); | ||
1456 | return -EINVAL; | ||
1457 | } | ||
1458 | } else | ||
1459 | p->ubi_num = UBI_DEV_NUM_AUTO; | ||
1460 | |||
1442 | mtd_devs += 1; | 1461 | mtd_devs += 1; |
1443 | return 0; | 1462 | return 0; |
1444 | } | 1463 | } |
1445 | 1464 | ||
1446 | module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000); | 1465 | module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000); |
1447 | MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024]].\n" | 1466 | MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n" |
1448 | "Multiple \"mtd\" parameters may be specified.\n" | 1467 | "Multiple \"mtd\" parameters may be specified.\n" |
1449 | "MTD devices may be specified by their number, name, or path to the MTD character device node.\n" | 1468 | "MTD devices may be specified by their number, name, or path to the MTD character device node.\n" |
1450 | "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n" | 1469 | "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n" |
1451 | "Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value (" | 1470 | "Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value (" |
1452 | __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n" | 1471 | __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n" |
1472 | "Optional \"ubi_num\" parameter specifies UBI device number which have to be assigned to the newly created UBI device (assigned automatically by default)\n" | ||
1453 | "\n" | 1473 | "\n" |
1454 | "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n" | 1474 | "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n" |
1455 | "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n" | 1475 | "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n" |
1456 | "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n" | 1476 | "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n" |
1477 | "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n" | ||
1457 | "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device)."); | 1478 | "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device)."); |
1458 | #ifdef CONFIG_MTD_UBI_FASTMAP | 1479 | #ifdef CONFIG_MTD_UBI_FASTMAP |
1459 | module_param(fm_autoconvert, bool, 0644); | 1480 | module_param(fm_autoconvert, bool, 0644); |
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 0648c6996d43..154275182b4b 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c | |||
@@ -727,8 +727,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, | |||
727 | 727 | ||
728 | aeb = NULL; | 728 | aeb = NULL; |
729 | list_for_each_entry(tmp_aeb, &used, u.list) { | 729 | list_for_each_entry(tmp_aeb, &used, u.list) { |
730 | if (tmp_aeb->pnum == pnum) | 730 | if (tmp_aeb->pnum == pnum) { |
731 | aeb = tmp_aeb; | 731 | aeb = tmp_aeb; |
732 | break; | ||
733 | } | ||
732 | } | 734 | } |
733 | 735 | ||
734 | /* This can happen if a PEB is already in an EBA known | 736 | /* This can happen if a PEB is already in an EBA known |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 9385b4524547..624e8dc24532 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -168,9 +168,6 @@ out_resume: | |||
168 | 168 | ||
169 | dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE); | 169 | dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE); |
170 | 170 | ||
171 | /* Make sure timer events get retriggered on all CPUs */ | ||
172 | clock_was_set(); | ||
173 | |||
174 | out_thaw: | 171 | out_thaw: |
175 | #ifdef CONFIG_PREEMPT | 172 | #ifdef CONFIG_PREEMPT |
176 | thaw_processes(); | 173 | thaw_processes(); |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 64e5323cbbb0..5e7c60c1cb63 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -387,7 +387,7 @@ static void remove_dir(struct dentry * d) | |||
387 | if (d->d_inode) | 387 | if (d->d_inode) |
388 | simple_rmdir(parent->d_inode,d); | 388 | simple_rmdir(parent->d_inode,d); |
389 | 389 | ||
390 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, d->d_count); | 390 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, d_count(d)); |
391 | 391 | ||
392 | dput(parent); | 392 | dput(parent); |
393 | } | 393 | } |
diff --git a/fs/timerfd.c b/fs/timerfd.c index 32b644f03690..929312180dd0 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/alarmtimer.h> | ||
11 | #include <linux/file.h> | 12 | #include <linux/file.h> |
12 | #include <linux/poll.h> | 13 | #include <linux/poll.h> |
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
@@ -26,7 +27,10 @@ | |||
26 | #include <linux/rcupdate.h> | 27 | #include <linux/rcupdate.h> |
27 | 28 | ||
28 | struct timerfd_ctx { | 29 | struct timerfd_ctx { |
29 | struct hrtimer tmr; | 30 | union { |
31 | struct hrtimer tmr; | ||
32 | struct alarm alarm; | ||
33 | } t; | ||
30 | ktime_t tintv; | 34 | ktime_t tintv; |
31 | ktime_t moffs; | 35 | ktime_t moffs; |
32 | wait_queue_head_t wqh; | 36 | wait_queue_head_t wqh; |
@@ -41,14 +45,19 @@ struct timerfd_ctx { | |||
41 | static LIST_HEAD(cancel_list); | 45 | static LIST_HEAD(cancel_list); |
42 | static DEFINE_SPINLOCK(cancel_lock); | 46 | static DEFINE_SPINLOCK(cancel_lock); |
43 | 47 | ||
48 | static inline bool isalarm(struct timerfd_ctx *ctx) | ||
49 | { | ||
50 | return ctx->clockid == CLOCK_REALTIME_ALARM || | ||
51 | ctx->clockid == CLOCK_BOOTTIME_ALARM; | ||
52 | } | ||
53 | |||
44 | /* | 54 | /* |
45 | * This gets called when the timer event triggers. We set the "expired" | 55 | * This gets called when the timer event triggers. We set the "expired" |
46 | * flag, but we do not re-arm the timer (in case it's necessary, | 56 | * flag, but we do not re-arm the timer (in case it's necessary, |
47 | * tintv.tv64 != 0) until the timer is accessed. | 57 | * tintv.tv64 != 0) until the timer is accessed. |
48 | */ | 58 | */ |
49 | static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) | 59 | static void timerfd_triggered(struct timerfd_ctx *ctx) |
50 | { | 60 | { |
51 | struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr); | ||
52 | unsigned long flags; | 61 | unsigned long flags; |
53 | 62 | ||
54 | spin_lock_irqsave(&ctx->wqh.lock, flags); | 63 | spin_lock_irqsave(&ctx->wqh.lock, flags); |
@@ -56,10 +65,25 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) | |||
56 | ctx->ticks++; | 65 | ctx->ticks++; |
57 | wake_up_locked(&ctx->wqh); | 66 | wake_up_locked(&ctx->wqh); |
58 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); | 67 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); |
68 | } | ||
59 | 69 | ||
70 | static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) | ||
71 | { | ||
72 | struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, | ||
73 | t.tmr); | ||
74 | timerfd_triggered(ctx); | ||
60 | return HRTIMER_NORESTART; | 75 | return HRTIMER_NORESTART; |
61 | } | 76 | } |
62 | 77 | ||
78 | static enum alarmtimer_restart timerfd_alarmproc(struct alarm *alarm, | ||
79 | ktime_t now) | ||
80 | { | ||
81 | struct timerfd_ctx *ctx = container_of(alarm, struct timerfd_ctx, | ||
82 | t.alarm); | ||
83 | timerfd_triggered(ctx); | ||
84 | return ALARMTIMER_NORESTART; | ||
85 | } | ||
86 | |||
63 | /* | 87 | /* |
64 | * Called when the clock was set to cancel the timers in the cancel | 88 | * Called when the clock was set to cancel the timers in the cancel |
65 | * list. This will wake up processes waiting on these timers. The | 89 | * list. This will wake up processes waiting on these timers. The |
@@ -107,8 +131,9 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx) | |||
107 | 131 | ||
108 | static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) | 132 | static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) |
109 | { | 133 | { |
110 | if (ctx->clockid == CLOCK_REALTIME && (flags & TFD_TIMER_ABSTIME) && | 134 | if ((ctx->clockid == CLOCK_REALTIME || |
111 | (flags & TFD_TIMER_CANCEL_ON_SET)) { | 135 | ctx->clockid == CLOCK_REALTIME_ALARM) && |
136 | (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) { | ||
112 | if (!ctx->might_cancel) { | 137 | if (!ctx->might_cancel) { |
113 | ctx->might_cancel = true; | 138 | ctx->might_cancel = true; |
114 | spin_lock(&cancel_lock); | 139 | spin_lock(&cancel_lock); |
@@ -124,7 +149,11 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) | |||
124 | { | 149 | { |
125 | ktime_t remaining; | 150 | ktime_t remaining; |
126 | 151 | ||
127 | remaining = hrtimer_expires_remaining(&ctx->tmr); | 152 | if (isalarm(ctx)) |
153 | remaining = alarm_expires_remaining(&ctx->t.alarm); | ||
154 | else | ||
155 | remaining = hrtimer_expires_remaining(&ctx->t.tmr); | ||
156 | |||
128 | return remaining.tv64 < 0 ? ktime_set(0, 0): remaining; | 157 | return remaining.tv64 < 0 ? ktime_set(0, 0): remaining; |
129 | } | 158 | } |
130 | 159 | ||
@@ -142,11 +171,28 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags, | |||
142 | ctx->expired = 0; | 171 | ctx->expired = 0; |
143 | ctx->ticks = 0; | 172 | ctx->ticks = 0; |
144 | ctx->tintv = timespec_to_ktime(ktmr->it_interval); | 173 | ctx->tintv = timespec_to_ktime(ktmr->it_interval); |
145 | hrtimer_init(&ctx->tmr, clockid, htmode); | 174 | |
146 | hrtimer_set_expires(&ctx->tmr, texp); | 175 | if (isalarm(ctx)) { |
147 | ctx->tmr.function = timerfd_tmrproc; | 176 | alarm_init(&ctx->t.alarm, |
177 | ctx->clockid == CLOCK_REALTIME_ALARM ? | ||
178 | ALARM_REALTIME : ALARM_BOOTTIME, | ||
179 | timerfd_alarmproc); | ||
180 | } else { | ||
181 | hrtimer_init(&ctx->t.tmr, clockid, htmode); | ||
182 | hrtimer_set_expires(&ctx->t.tmr, texp); | ||
183 | ctx->t.tmr.function = timerfd_tmrproc; | ||
184 | } | ||
185 | |||
148 | if (texp.tv64 != 0) { | 186 | if (texp.tv64 != 0) { |
149 | hrtimer_start(&ctx->tmr, texp, htmode); | 187 | if (isalarm(ctx)) { |
188 | if (flags & TFD_TIMER_ABSTIME) | ||
189 | alarm_start(&ctx->t.alarm, texp); | ||
190 | else | ||
191 | alarm_start_relative(&ctx->t.alarm, texp); | ||
192 | } else { | ||
193 | hrtimer_start(&ctx->t.tmr, texp, htmode); | ||
194 | } | ||
195 | |||
150 | if (timerfd_canceled(ctx)) | 196 | if (timerfd_canceled(ctx)) |
151 | return -ECANCELED; | 197 | return -ECANCELED; |
152 | } | 198 | } |
@@ -158,7 +204,11 @@ static int timerfd_release(struct inode *inode, struct file *file) | |||
158 | struct timerfd_ctx *ctx = file->private_data; | 204 | struct timerfd_ctx *ctx = file->private_data; |
159 | 205 | ||
160 | timerfd_remove_cancel(ctx); | 206 | timerfd_remove_cancel(ctx); |
161 | hrtimer_cancel(&ctx->tmr); | 207 | |
208 | if (isalarm(ctx)) | ||
209 | alarm_cancel(&ctx->t.alarm); | ||
210 | else | ||
211 | hrtimer_cancel(&ctx->t.tmr); | ||
162 | kfree_rcu(ctx, rcu); | 212 | kfree_rcu(ctx, rcu); |
163 | return 0; | 213 | return 0; |
164 | } | 214 | } |
@@ -215,9 +265,15 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, | |||
215 | * callback to avoid DoS attacks specifying a very | 265 | * callback to avoid DoS attacks specifying a very |
216 | * short timer period. | 266 | * short timer period. |
217 | */ | 267 | */ |
218 | ticks += hrtimer_forward_now(&ctx->tmr, | 268 | if (isalarm(ctx)) { |
219 | ctx->tintv) - 1; | 269 | ticks += alarm_forward_now( |
220 | hrtimer_restart(&ctx->tmr); | 270 | &ctx->t.alarm, ctx->tintv) - 1; |
271 | alarm_restart(&ctx->t.alarm); | ||
272 | } else { | ||
273 | ticks += hrtimer_forward_now(&ctx->t.tmr, | ||
274 | ctx->tintv) - 1; | ||
275 | hrtimer_restart(&ctx->t.tmr); | ||
276 | } | ||
221 | } | 277 | } |
222 | ctx->expired = 0; | 278 | ctx->expired = 0; |
223 | ctx->ticks = 0; | 279 | ctx->ticks = 0; |
@@ -259,7 +315,9 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
259 | 315 | ||
260 | if ((flags & ~TFD_CREATE_FLAGS) || | 316 | if ((flags & ~TFD_CREATE_FLAGS) || |
261 | (clockid != CLOCK_MONOTONIC && | 317 | (clockid != CLOCK_MONOTONIC && |
262 | clockid != CLOCK_REALTIME)) | 318 | clockid != CLOCK_REALTIME && |
319 | clockid != CLOCK_REALTIME_ALARM && | ||
320 | clockid != CLOCK_BOOTTIME_ALARM)) | ||
263 | return -EINVAL; | 321 | return -EINVAL; |
264 | 322 | ||
265 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 323 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
@@ -268,7 +326,15 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
268 | 326 | ||
269 | init_waitqueue_head(&ctx->wqh); | 327 | init_waitqueue_head(&ctx->wqh); |
270 | ctx->clockid = clockid; | 328 | ctx->clockid = clockid; |
271 | hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); | 329 | |
330 | if (isalarm(ctx)) | ||
331 | alarm_init(&ctx->t.alarm, | ||
332 | ctx->clockid == CLOCK_REALTIME_ALARM ? | ||
333 | ALARM_REALTIME : ALARM_BOOTTIME, | ||
334 | timerfd_alarmproc); | ||
335 | else | ||
336 | hrtimer_init(&ctx->t.tmr, clockid, HRTIMER_MODE_ABS); | ||
337 | |||
272 | ctx->moffs = ktime_get_monotonic_offset(); | 338 | ctx->moffs = ktime_get_monotonic_offset(); |
273 | 339 | ||
274 | ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, | 340 | ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, |
@@ -305,8 +371,14 @@ static int do_timerfd_settime(int ufd, int flags, | |||
305 | */ | 371 | */ |
306 | for (;;) { | 372 | for (;;) { |
307 | spin_lock_irq(&ctx->wqh.lock); | 373 | spin_lock_irq(&ctx->wqh.lock); |
308 | if (hrtimer_try_to_cancel(&ctx->tmr) >= 0) | 374 | |
309 | break; | 375 | if (isalarm(ctx)) { |
376 | if (alarm_try_to_cancel(&ctx->t.alarm) >= 0) | ||
377 | break; | ||
378 | } else { | ||
379 | if (hrtimer_try_to_cancel(&ctx->t.tmr) >= 0) | ||
380 | break; | ||
381 | } | ||
310 | spin_unlock_irq(&ctx->wqh.lock); | 382 | spin_unlock_irq(&ctx->wqh.lock); |
311 | cpu_relax(); | 383 | cpu_relax(); |
312 | } | 384 | } |
@@ -317,8 +389,12 @@ static int do_timerfd_settime(int ufd, int flags, | |||
317 | * We do not update "ticks" and "expired" since the timer will be | 389 | * We do not update "ticks" and "expired" since the timer will be |
318 | * re-programmed again in the following timerfd_setup() call. | 390 | * re-programmed again in the following timerfd_setup() call. |
319 | */ | 391 | */ |
320 | if (ctx->expired && ctx->tintv.tv64) | 392 | if (ctx->expired && ctx->tintv.tv64) { |
321 | hrtimer_forward_now(&ctx->tmr, ctx->tintv); | 393 | if (isalarm(ctx)) |
394 | alarm_forward_now(&ctx->t.alarm, ctx->tintv); | ||
395 | else | ||
396 | hrtimer_forward_now(&ctx->t.tmr, ctx->tintv); | ||
397 | } | ||
322 | 398 | ||
323 | old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); | 399 | old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); |
324 | old->it_interval = ktime_to_timespec(ctx->tintv); | 400 | old->it_interval = ktime_to_timespec(ctx->tintv); |
@@ -345,9 +421,18 @@ static int do_timerfd_gettime(int ufd, struct itimerspec *t) | |||
345 | spin_lock_irq(&ctx->wqh.lock); | 421 | spin_lock_irq(&ctx->wqh.lock); |
346 | if (ctx->expired && ctx->tintv.tv64) { | 422 | if (ctx->expired && ctx->tintv.tv64) { |
347 | ctx->expired = 0; | 423 | ctx->expired = 0; |
348 | ctx->ticks += | 424 | |
349 | hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; | 425 | if (isalarm(ctx)) { |
350 | hrtimer_restart(&ctx->tmr); | 426 | ctx->ticks += |
427 | alarm_forward_now( | ||
428 | &ctx->t.alarm, ctx->tintv) - 1; | ||
429 | alarm_restart(&ctx->t.alarm); | ||
430 | } else { | ||
431 | ctx->ticks += | ||
432 | hrtimer_forward_now(&ctx->t.tmr, ctx->tintv) | ||
433 | - 1; | ||
434 | hrtimer_restart(&ctx->t.tmr); | ||
435 | } | ||
351 | } | 436 | } |
352 | t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); | 437 | t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); |
353 | t->it_interval = ktime_to_timespec(ctx->tintv); | 438 | t->it_interval = ktime_to_timespec(ctx->tintv); |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index f21acf0ef01f..879b9976c12b 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -1412,7 +1412,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1412 | 1412 | ||
1413 | ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"%s", | 1413 | ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"%s", |
1414 | c->vi.ubi_num, c->vi.vol_id, c->vi.name, | 1414 | c->vi.ubi_num, c->vi.vol_id, c->vi.name, |
1415 | c->ro_mount ? ", R/O mode" : NULL); | 1415 | c->ro_mount ? ", R/O mode" : ""); |
1416 | x = (long long)c->main_lebs * c->leb_size; | 1416 | x = (long long)c->main_lebs * c->leb_size; |
1417 | y = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes; | 1417 | y = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes; |
1418 | ubifs_msg("LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes", | 1418 | ubifs_msg("LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes", |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c74d88baea60..69732d279e8b 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -174,8 +174,6 @@ | |||
174 | *(.data) \ | 174 | *(.data) \ |
175 | *(.ref.data) \ | 175 | *(.ref.data) \ |
176 | *(.data..shared_aligned) /* percpu related */ \ | 176 | *(.data..shared_aligned) /* percpu related */ \ |
177 | CPU_KEEP(init.data) \ | ||
178 | CPU_KEEP(exit.data) \ | ||
179 | MEM_KEEP(init.data) \ | 177 | MEM_KEEP(init.data) \ |
180 | MEM_KEEP(exit.data) \ | 178 | MEM_KEEP(exit.data) \ |
181 | *(.data.unlikely) \ | 179 | *(.data.unlikely) \ |
@@ -355,8 +353,6 @@ | |||
355 | /* __*init sections */ \ | 353 | /* __*init sections */ \ |
356 | __init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \ | 354 | __init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \ |
357 | *(.ref.rodata) \ | 355 | *(.ref.rodata) \ |
358 | CPU_KEEP(init.rodata) \ | ||
359 | CPU_KEEP(exit.rodata) \ | ||
360 | MEM_KEEP(init.rodata) \ | 356 | MEM_KEEP(init.rodata) \ |
361 | MEM_KEEP(exit.rodata) \ | 357 | MEM_KEEP(exit.rodata) \ |
362 | } \ | 358 | } \ |
@@ -397,8 +393,6 @@ | |||
397 | *(.text.hot) \ | 393 | *(.text.hot) \ |
398 | *(.text) \ | 394 | *(.text) \ |
399 | *(.ref.text) \ | 395 | *(.ref.text) \ |
400 | CPU_KEEP(init.text) \ | ||
401 | CPU_KEEP(exit.text) \ | ||
402 | MEM_KEEP(init.text) \ | 396 | MEM_KEEP(init.text) \ |
403 | MEM_KEEP(exit.text) \ | 397 | MEM_KEEP(exit.text) \ |
404 | *(.text.unlikely) | 398 | *(.text.unlikely) |
@@ -482,14 +476,12 @@ | |||
482 | /* init and exit section handling */ | 476 | /* init and exit section handling */ |
483 | #define INIT_DATA \ | 477 | #define INIT_DATA \ |
484 | *(.init.data) \ | 478 | *(.init.data) \ |
485 | CPU_DISCARD(init.data) \ | ||
486 | MEM_DISCARD(init.data) \ | 479 | MEM_DISCARD(init.data) \ |
487 | KERNEL_CTORS() \ | 480 | KERNEL_CTORS() \ |
488 | MCOUNT_REC() \ | 481 | MCOUNT_REC() \ |
489 | *(.init.rodata) \ | 482 | *(.init.rodata) \ |
490 | FTRACE_EVENTS() \ | 483 | FTRACE_EVENTS() \ |
491 | TRACE_SYSCALLS() \ | 484 | TRACE_SYSCALLS() \ |
492 | CPU_DISCARD(init.rodata) \ | ||
493 | MEM_DISCARD(init.rodata) \ | 485 | MEM_DISCARD(init.rodata) \ |
494 | CLK_OF_TABLES() \ | 486 | CLK_OF_TABLES() \ |
495 | CLKSRC_OF_TABLES() \ | 487 | CLKSRC_OF_TABLES() \ |
@@ -498,19 +490,15 @@ | |||
498 | 490 | ||
499 | #define INIT_TEXT \ | 491 | #define INIT_TEXT \ |
500 | *(.init.text) \ | 492 | *(.init.text) \ |
501 | CPU_DISCARD(init.text) \ | ||
502 | MEM_DISCARD(init.text) | 493 | MEM_DISCARD(init.text) |
503 | 494 | ||
504 | #define EXIT_DATA \ | 495 | #define EXIT_DATA \ |
505 | *(.exit.data) \ | 496 | *(.exit.data) \ |
506 | CPU_DISCARD(exit.data) \ | ||
507 | CPU_DISCARD(exit.rodata) \ | ||
508 | MEM_DISCARD(exit.data) \ | 497 | MEM_DISCARD(exit.data) \ |
509 | MEM_DISCARD(exit.rodata) | 498 | MEM_DISCARD(exit.rodata) |
510 | 499 | ||
511 | #define EXIT_TEXT \ | 500 | #define EXIT_TEXT \ |
512 | *(.exit.text) \ | 501 | *(.exit.text) \ |
513 | CPU_DISCARD(exit.text) \ | ||
514 | MEM_DISCARD(exit.text) | 502 | MEM_DISCARD(exit.text) |
515 | 503 | ||
516 | #define EXIT_CALL \ | 504 | #define EXIT_CALL \ |
diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 9069694e70eb..a899402a5a0e 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h | |||
@@ -44,10 +44,14 @@ struct alarm { | |||
44 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | 44 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, |
45 | enum alarmtimer_restart (*function)(struct alarm *, ktime_t)); | 45 | enum alarmtimer_restart (*function)(struct alarm *, ktime_t)); |
46 | int alarm_start(struct alarm *alarm, ktime_t start); | 46 | int alarm_start(struct alarm *alarm, ktime_t start); |
47 | int alarm_start_relative(struct alarm *alarm, ktime_t start); | ||
48 | void alarm_restart(struct alarm *alarm); | ||
47 | int alarm_try_to_cancel(struct alarm *alarm); | 49 | int alarm_try_to_cancel(struct alarm *alarm); |
48 | int alarm_cancel(struct alarm *alarm); | 50 | int alarm_cancel(struct alarm *alarm); |
49 | 51 | ||
50 | u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval); | 52 | u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval); |
53 | u64 alarm_forward_now(struct alarm *alarm, ktime_t interval); | ||
54 | ktime_t alarm_expires_remaining(const struct alarm *alarm); | ||
51 | 55 | ||
52 | /* Provide way to access the rtc device being used by alarmtimers */ | 56 | /* Provide way to access the rtc device being used by alarmtimers */ |
53 | struct rtc_device *alarmtimer_get_rtcdev(void); | 57 | struct rtc_device *alarmtimer_get_rtcdev(void); |
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h index 2a5f64a11b77..10fe2a211c2e 100644 --- a/include/linux/amba/pl08x.h +++ b/include/linux/amba/pl08x.h | |||
@@ -76,11 +76,11 @@ struct pl08x_channel_data { | |||
76 | * platform, all inclusive, including multiplexed channels. The available | 76 | * platform, all inclusive, including multiplexed channels. The available |
77 | * physical channels will be multiplexed around these signals as they are | 77 | * physical channels will be multiplexed around these signals as they are |
78 | * requested, just enumerate all possible channels. | 78 | * requested, just enumerate all possible channels. |
79 | * @get_signal: request a physical signal to be used for a DMA transfer | 79 | * @get_xfer_signal: request a physical signal to be used for a DMA transfer |
80 | * immediately: if there is some multiplexing or similar blocking the use | 80 | * immediately: if there is some multiplexing or similar blocking the use |
81 | * of the channel the transfer can be denied by returning less than zero, | 81 | * of the channel the transfer can be denied by returning less than zero, |
82 | * else it returns the allocated signal number | 82 | * else it returns the allocated signal number |
83 | * @put_signal: indicate to the platform that this physical signal is not | 83 | * @put_xfer_signal: indicate to the platform that this physical signal is not |
84 | * running any DMA transfer and multiplexing can be recycled | 84 | * running any DMA transfer and multiplexing can be recycled |
85 | * @lli_buses: buses which LLIs can be fetched from: PL08X_AHB1 | PL08X_AHB2 | 85 | * @lli_buses: buses which LLIs can be fetched from: PL08X_AHB1 | PL08X_AHB2 |
86 | * @mem_buses: buses which memory can be accessed from: PL08X_AHB1 | PL08X_AHB2 | 86 | * @mem_buses: buses which memory can be accessed from: PL08X_AHB1 | PL08X_AHB2 |
@@ -89,8 +89,8 @@ struct pl08x_platform_data { | |||
89 | const struct pl08x_channel_data *slave_channels; | 89 | const struct pl08x_channel_data *slave_channels; |
90 | unsigned int num_slave_channels; | 90 | unsigned int num_slave_channels; |
91 | struct pl08x_channel_data memcpy_channel; | 91 | struct pl08x_channel_data memcpy_channel; |
92 | int (*get_signal)(const struct pl08x_channel_data *); | 92 | int (*get_xfer_signal)(const struct pl08x_channel_data *); |
93 | void (*put_signal)(const struct pl08x_channel_data *, int); | 93 | void (*put_xfer_signal)(const struct pl08x_channel_data *, int); |
94 | u8 lli_buses; | 94 | u8 lli_buses; |
95 | u8 mem_buses; | 95 | u8 mem_buses; |
96 | }; | 96 | }; |
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 963d71431388..0857922e8ad0 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h | |||
@@ -30,6 +30,7 @@ enum clock_event_nofitiers { | |||
30 | #include <linux/notifier.h> | 30 | #include <linux/notifier.h> |
31 | 31 | ||
32 | struct clock_event_device; | 32 | struct clock_event_device; |
33 | struct module; | ||
33 | 34 | ||
34 | /* Clock event mode commands */ | 35 | /* Clock event mode commands */ |
35 | enum clock_event_mode { | 36 | enum clock_event_mode { |
@@ -83,6 +84,7 @@ enum clock_event_mode { | |||
83 | * @irq: IRQ number (only for non CPU local devices) | 84 | * @irq: IRQ number (only for non CPU local devices) |
84 | * @cpumask: cpumask to indicate for which CPUs this device works | 85 | * @cpumask: cpumask to indicate for which CPUs this device works |
85 | * @list: list head for the management code | 86 | * @list: list head for the management code |
87 | * @owner: module reference | ||
86 | */ | 88 | */ |
87 | struct clock_event_device { | 89 | struct clock_event_device { |
88 | void (*event_handler)(struct clock_event_device *); | 90 | void (*event_handler)(struct clock_event_device *); |
@@ -112,6 +114,7 @@ struct clock_event_device { | |||
112 | int irq; | 114 | int irq; |
113 | const struct cpumask *cpumask; | 115 | const struct cpumask *cpumask; |
114 | struct list_head list; | 116 | struct list_head list; |
117 | struct module *owner; | ||
115 | } ____cacheline_aligned; | 118 | } ____cacheline_aligned; |
116 | 119 | ||
117 | /* | 120 | /* |
@@ -138,6 +141,7 @@ static inline unsigned long div_sc(unsigned long ticks, unsigned long nsec, | |||
138 | extern u64 clockevent_delta2ns(unsigned long latch, | 141 | extern u64 clockevent_delta2ns(unsigned long latch, |
139 | struct clock_event_device *evt); | 142 | struct clock_event_device *evt); |
140 | extern void clockevents_register_device(struct clock_event_device *dev); | 143 | extern void clockevents_register_device(struct clock_event_device *dev); |
144 | extern int clockevents_unbind_device(struct clock_event_device *ced, int cpu); | ||
141 | 145 | ||
142 | extern void clockevents_config(struct clock_event_device *dev, u32 freq); | 146 | extern void clockevents_config(struct clock_event_device *dev, u32 freq); |
143 | extern void clockevents_config_and_register(struct clock_event_device *dev, | 147 | extern void clockevents_config_and_register(struct clock_event_device *dev, |
@@ -150,7 +154,6 @@ extern void clockevents_exchange_device(struct clock_event_device *old, | |||
150 | struct clock_event_device *new); | 154 | struct clock_event_device *new); |
151 | extern void clockevents_set_mode(struct clock_event_device *dev, | 155 | extern void clockevents_set_mode(struct clock_event_device *dev, |
152 | enum clock_event_mode mode); | 156 | enum clock_event_mode mode); |
153 | extern int clockevents_register_notifier(struct notifier_block *nb); | ||
154 | extern int clockevents_program_event(struct clock_event_device *dev, | 157 | extern int clockevents_program_event(struct clock_event_device *dev, |
155 | ktime_t expires, bool force); | 158 | ktime_t expires, bool force); |
156 | 159 | ||
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7279b94c01da..dbbf8aa7731b 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h | |||
@@ -21,6 +21,7 @@ | |||
21 | /* clocksource cycle base type */ | 21 | /* clocksource cycle base type */ |
22 | typedef u64 cycle_t; | 22 | typedef u64 cycle_t; |
23 | struct clocksource; | 23 | struct clocksource; |
24 | struct module; | ||
24 | 25 | ||
25 | #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA | 26 | #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA |
26 | #include <asm/clocksource.h> | 27 | #include <asm/clocksource.h> |
@@ -162,6 +163,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc, | |||
162 | * @suspend: suspend function for the clocksource, if necessary | 163 | * @suspend: suspend function for the clocksource, if necessary |
163 | * @resume: resume function for the clocksource, if necessary | 164 | * @resume: resume function for the clocksource, if necessary |
164 | * @cycle_last: most recent cycle counter value seen by ::read() | 165 | * @cycle_last: most recent cycle counter value seen by ::read() |
166 | * @owner: module reference, must be set by clocksource in modules | ||
165 | */ | 167 | */ |
166 | struct clocksource { | 168 | struct clocksource { |
167 | /* | 169 | /* |
@@ -195,6 +197,7 @@ struct clocksource { | |||
195 | cycle_t cs_last; | 197 | cycle_t cs_last; |
196 | cycle_t wd_last; | 198 | cycle_t wd_last; |
197 | #endif | 199 | #endif |
200 | struct module *owner; | ||
198 | } ____cacheline_aligned; | 201 | } ____cacheline_aligned; |
199 | 202 | ||
200 | /* | 203 | /* |
@@ -207,6 +210,7 @@ struct clocksource { | |||
207 | #define CLOCK_SOURCE_VALID_FOR_HRES 0x20 | 210 | #define CLOCK_SOURCE_VALID_FOR_HRES 0x20 |
208 | #define CLOCK_SOURCE_UNSTABLE 0x40 | 211 | #define CLOCK_SOURCE_UNSTABLE 0x40 |
209 | #define CLOCK_SOURCE_SUSPEND_NONSTOP 0x80 | 212 | #define CLOCK_SOURCE_SUSPEND_NONSTOP 0x80 |
213 | #define CLOCK_SOURCE_RESELECT 0x100 | ||
210 | 214 | ||
211 | /* simplify initialization of mask field */ | 215 | /* simplify initialization of mask field */ |
212 | #define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1) | 216 | #define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1) |
@@ -279,7 +283,7 @@ static inline s64 clocksource_cyc2ns(cycle_t cycles, u32 mult, u32 shift) | |||
279 | 283 | ||
280 | 284 | ||
281 | extern int clocksource_register(struct clocksource*); | 285 | extern int clocksource_register(struct clocksource*); |
282 | extern void clocksource_unregister(struct clocksource*); | 286 | extern int clocksource_unregister(struct clocksource*); |
283 | extern void clocksource_touch_watchdog(void); | 287 | extern void clocksource_touch_watchdog(void); |
284 | extern struct clocksource* clocksource_get_next(void); | 288 | extern struct clocksource* clocksource_get_next(void); |
285 | extern void clocksource_change_rating(struct clocksource *cs, int rating); | 289 | extern void clocksource_change_rating(struct clocksource *cs, int rating); |
@@ -321,7 +325,7 @@ static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz) | |||
321 | } | 325 | } |
322 | 326 | ||
323 | 327 | ||
324 | extern void timekeeping_notify(struct clocksource *clock); | 328 | extern int timekeeping_notify(struct clocksource *clock); |
325 | 329 | ||
326 | extern cycle_t clocksource_mmio_readl_up(struct clocksource *); | 330 | extern cycle_t clocksource_mmio_readl_up(struct clocksource *); |
327 | extern cycle_t clocksource_mmio_readl_down(struct clocksource *); | 331 | extern cycle_t clocksource_mmio_readl_down(struct clocksource *); |
diff --git a/include/linux/crc-t10dif.h b/include/linux/crc-t10dif.h index a9c96d865ee7..b3cb71f0d3b0 100644 --- a/include/linux/crc-t10dif.h +++ b/include/linux/crc-t10dif.h | |||
@@ -3,6 +3,10 @@ | |||
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | #define CRC_T10DIF_DIGEST_SIZE 2 | ||
7 | #define CRC_T10DIF_BLOCK_SIZE 1 | ||
8 | |||
9 | __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, size_t len); | ||
6 | __u16 crc_t10dif(unsigned char const *, size_t); | 10 | __u16 crc_t10dif(unsigned char const *, size_t); |
7 | 11 | ||
8 | #endif | 12 | #endif |
diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h index 07261d52a6df..1f79b20918b1 100644 --- a/include/linux/dw_apb_timer.h +++ b/include/linux/dw_apb_timer.h | |||
@@ -51,6 +51,5 @@ dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base, | |||
51 | void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs); | 51 | void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs); |
52 | void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs); | 52 | void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs); |
53 | cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs); | 53 | cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs); |
54 | void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs); | ||
55 | 54 | ||
56 | #endif /* __DW_APB_TIMER_H__ */ | 55 | #endif /* __DW_APB_TIMER_H__ */ |
diff --git a/include/linux/efi.h b/include/linux/efi.h index 21ae6b3c0359..5f8f176154f7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -594,8 +594,8 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); | |||
594 | extern int __init efi_uart_console_only (void); | 594 | extern int __init efi_uart_console_only (void); |
595 | extern void efi_initialize_iomem_resources(struct resource *code_resource, | 595 | extern void efi_initialize_iomem_resources(struct resource *code_resource, |
596 | struct resource *data_resource, struct resource *bss_resource); | 596 | struct resource *data_resource, struct resource *bss_resource); |
597 | extern unsigned long efi_get_time(void); | 597 | extern void efi_get_time(struct timespec *now); |
598 | extern int efi_set_rtc_mmss(unsigned long nowtime); | 598 | extern int efi_set_rtc_mmss(const struct timespec *now); |
599 | extern void efi_reserve_boot_services(void); | 599 | extern void efi_reserve_boot_services(void); |
600 | extern struct efi_memory_map memmap; | 600 | extern struct efi_memory_map memmap; |
601 | 601 | ||
diff --git a/include/linux/init.h b/include/linux/init.h index 861814710d52..e73f2b708525 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -93,13 +93,13 @@ | |||
93 | 93 | ||
94 | #define __exit __section(.exit.text) __exitused __cold notrace | 94 | #define __exit __section(.exit.text) __exitused __cold notrace |
95 | 95 | ||
96 | /* Used for HOTPLUG_CPU */ | 96 | /* temporary, until all users are removed */ |
97 | #define __cpuinit __section(.cpuinit.text) __cold notrace | 97 | #define __cpuinit |
98 | #define __cpuinitdata __section(.cpuinit.data) | 98 | #define __cpuinitdata |
99 | #define __cpuinitconst __constsection(.cpuinit.rodata) | 99 | #define __cpuinitconst |
100 | #define __cpuexit __section(.cpuexit.text) __exitused __cold notrace | 100 | #define __cpuexit |
101 | #define __cpuexitdata __section(.cpuexit.data) | 101 | #define __cpuexitdata |
102 | #define __cpuexitconst __constsection(.cpuexit.rodata) | 102 | #define __cpuexitconst |
103 | 103 | ||
104 | /* Used for MEMORY_HOTPLUG */ | 104 | /* Used for MEMORY_HOTPLUG */ |
105 | #define __meminit __section(.meminit.text) __cold notrace | 105 | #define __meminit __section(.meminit.text) __cold notrace |
@@ -118,9 +118,8 @@ | |||
118 | #define __INITRODATA .section ".init.rodata","a",%progbits | 118 | #define __INITRODATA .section ".init.rodata","a",%progbits |
119 | #define __FINITDATA .previous | 119 | #define __FINITDATA .previous |
120 | 120 | ||
121 | #define __CPUINIT .section ".cpuinit.text", "ax" | 121 | /* temporary, until all users are removed */ |
122 | #define __CPUINITDATA .section ".cpuinit.data", "aw" | 122 | #define __CPUINIT |
123 | #define __CPUINITRODATA .section ".cpuinit.rodata", "a" | ||
124 | 123 | ||
125 | #define __MEMINIT .section ".meminit.text", "ax" | 124 | #define __MEMINIT .section ".meminit.text", "ax" |
126 | #define __MEMINITDATA .section ".meminit.data", "aw" | 125 | #define __MEMINITDATA .section ".meminit.data", "aw" |
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index ba2c708adcff..c983ed18c332 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h | |||
@@ -73,57 +73,48 @@ struct irq_domain_chip_generic; | |||
73 | /** | 73 | /** |
74 | * struct irq_domain - Hardware interrupt number translation object | 74 | * struct irq_domain - Hardware interrupt number translation object |
75 | * @link: Element in global irq_domain list. | 75 | * @link: Element in global irq_domain list. |
76 | * @revmap_type: Method used for reverse mapping hwirq numbers to linux irq. This | 76 | * @name: Name of interrupt domain |
77 | * will be one of the IRQ_DOMAIN_MAP_* values. | ||
78 | * @revmap_data: Revmap method specific data. | ||
79 | * @ops: pointer to irq_domain methods | 77 | * @ops: pointer to irq_domain methods |
80 | * @host_data: private data pointer for use by owner. Not touched by irq_domain | 78 | * @host_data: private data pointer for use by owner. Not touched by irq_domain |
81 | * core code. | 79 | * core code. |
82 | * @irq_base: Start of irq_desc range assigned to the irq_domain. The creator | 80 | * |
83 | * of the irq_domain is responsible for allocating the array of | 81 | * Optional elements |
84 | * irq_desc structures. | 82 | * @of_node: Pointer to device tree nodes associated with the irq_domain. Used |
85 | * @nr_irq: Number of irqs managed by the irq domain | 83 | * when decoding device tree interrupt specifiers. |
86 | * @hwirq_base: Starting number for hwirqs managed by the irq domain | 84 | * @gc: Pointer to a list of generic chips. There is a helper function for |
87 | * @of_node: (optional) Pointer to device tree nodes associated with the | 85 | * setting up one or more generic chips for interrupt controllers |
88 | * irq_domain. Used when decoding device tree interrupt specifiers. | 86 | * drivers using the generic chip library which uses this pointer. |
87 | * | ||
88 | * Revmap data, used internally by irq_domain | ||
89 | * @revmap_direct_max_irq: The largest hwirq that can be set for controllers that | ||
90 | * support direct mapping | ||
91 | * @revmap_size: Size of the linear map table @linear_revmap[] | ||
92 | * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map | ||
93 | * @linear_revmap: Linear table of hwirq->virq reverse mappings | ||
89 | */ | 94 | */ |
90 | struct irq_domain { | 95 | struct irq_domain { |
91 | struct list_head link; | 96 | struct list_head link; |
92 | 97 | const char *name; | |
93 | /* type of reverse mapping_technique */ | ||
94 | unsigned int revmap_type; | ||
95 | union { | ||
96 | struct { | ||
97 | unsigned int size; | ||
98 | unsigned int first_irq; | ||
99 | irq_hw_number_t first_hwirq; | ||
100 | } legacy; | ||
101 | struct { | ||
102 | unsigned int size; | ||
103 | unsigned int *revmap; | ||
104 | } linear; | ||
105 | struct { | ||
106 | unsigned int max_irq; | ||
107 | } nomap; | ||
108 | struct radix_tree_root tree; | ||
109 | } revmap_data; | ||
110 | const struct irq_domain_ops *ops; | 98 | const struct irq_domain_ops *ops; |
111 | void *host_data; | 99 | void *host_data; |
112 | irq_hw_number_t inval_irq; | ||
113 | 100 | ||
114 | /* Optional device node pointer */ | 101 | /* Optional data */ |
115 | struct device_node *of_node; | 102 | struct device_node *of_node; |
116 | /* Optional pointer to generic interrupt chips */ | ||
117 | struct irq_domain_chip_generic *gc; | 103 | struct irq_domain_chip_generic *gc; |
118 | }; | ||
119 | 104 | ||
120 | #define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs. | 105 | /* reverse map data. The linear map gets appended to the irq_domain */ |
121 | * ie. legacy 8259, gets irqs 1..15 */ | 106 | irq_hw_number_t hwirq_max; |
122 | #define IRQ_DOMAIN_MAP_NOMAP 1 /* no fast reverse mapping */ | 107 | unsigned int revmap_direct_max_irq; |
123 | #define IRQ_DOMAIN_MAP_LINEAR 2 /* linear map of interrupts */ | 108 | unsigned int revmap_size; |
124 | #define IRQ_DOMAIN_MAP_TREE 3 /* radix tree */ | 109 | struct radix_tree_root revmap_tree; |
110 | unsigned int linear_revmap[]; | ||
111 | }; | ||
125 | 112 | ||
126 | #ifdef CONFIG_IRQ_DOMAIN | 113 | #ifdef CONFIG_IRQ_DOMAIN |
114 | struct irq_domain *__irq_domain_add(struct device_node *of_node, int size, | ||
115 | irq_hw_number_t hwirq_max, int direct_max, | ||
116 | const struct irq_domain_ops *ops, | ||
117 | void *host_data); | ||
127 | struct irq_domain *irq_domain_add_simple(struct device_node *of_node, | 118 | struct irq_domain *irq_domain_add_simple(struct device_node *of_node, |
128 | unsigned int size, | 119 | unsigned int size, |
129 | unsigned int first_irq, | 120 | unsigned int first_irq, |
@@ -135,21 +126,30 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, | |||
135 | irq_hw_number_t first_hwirq, | 126 | irq_hw_number_t first_hwirq, |
136 | const struct irq_domain_ops *ops, | 127 | const struct irq_domain_ops *ops, |
137 | void *host_data); | 128 | void *host_data); |
138 | struct irq_domain *irq_domain_add_linear(struct device_node *of_node, | 129 | extern struct irq_domain *irq_find_host(struct device_node *node); |
130 | extern void irq_set_default_host(struct irq_domain *host); | ||
131 | |||
132 | /** | ||
133 | * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain. | ||
134 | * @of_node: pointer to interrupt controller's device tree node. | ||
135 | * @size: Number of interrupts in the domain. | ||
136 | * @ops: map/unmap domain callbacks | ||
137 | * @host_data: Controller private data pointer | ||
138 | */ | ||
139 | static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_node, | ||
139 | unsigned int size, | 140 | unsigned int size, |
140 | const struct irq_domain_ops *ops, | 141 | const struct irq_domain_ops *ops, |
141 | void *host_data); | 142 | void *host_data) |
142 | struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, | 143 | { |
144 | return __irq_domain_add(of_node, size, size, 0, ops, host_data); | ||
145 | } | ||
146 | static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, | ||
143 | unsigned int max_irq, | 147 | unsigned int max_irq, |
144 | const struct irq_domain_ops *ops, | 148 | const struct irq_domain_ops *ops, |
145 | void *host_data); | 149 | void *host_data) |
146 | struct irq_domain *irq_domain_add_tree(struct device_node *of_node, | 150 | { |
147 | const struct irq_domain_ops *ops, | 151 | return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data); |
148 | void *host_data); | 152 | } |
149 | |||
150 | extern struct irq_domain *irq_find_host(struct device_node *node); | ||
151 | extern void irq_set_default_host(struct irq_domain *host); | ||
152 | |||
153 | static inline struct irq_domain *irq_domain_add_legacy_isa( | 153 | static inline struct irq_domain *irq_domain_add_legacy_isa( |
154 | struct device_node *of_node, | 154 | struct device_node *of_node, |
155 | const struct irq_domain_ops *ops, | 155 | const struct irq_domain_ops *ops, |
@@ -158,21 +158,40 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( | |||
158 | return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops, | 158 | return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops, |
159 | host_data); | 159 | host_data); |
160 | } | 160 | } |
161 | static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node, | ||
162 | const struct irq_domain_ops *ops, | ||
163 | void *host_data) | ||
164 | { | ||
165 | return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data); | ||
166 | } | ||
161 | 167 | ||
162 | extern void irq_domain_remove(struct irq_domain *host); | 168 | extern void irq_domain_remove(struct irq_domain *host); |
163 | 169 | ||
164 | extern int irq_domain_associate_many(struct irq_domain *domain, | 170 | extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq, |
165 | unsigned int irq_base, | 171 | irq_hw_number_t hwirq); |
166 | irq_hw_number_t hwirq_base, int count); | 172 | extern void irq_domain_associate_many(struct irq_domain *domain, |
167 | static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq, | 173 | unsigned int irq_base, |
168 | irq_hw_number_t hwirq) | 174 | irq_hw_number_t hwirq_base, int count); |
169 | { | ||
170 | return irq_domain_associate_many(domain, irq, hwirq, 1); | ||
171 | } | ||
172 | 175 | ||
173 | extern unsigned int irq_create_mapping(struct irq_domain *host, | 176 | extern unsigned int irq_create_mapping(struct irq_domain *host, |
174 | irq_hw_number_t hwirq); | 177 | irq_hw_number_t hwirq); |
175 | extern void irq_dispose_mapping(unsigned int virq); | 178 | extern void irq_dispose_mapping(unsigned int virq); |
179 | |||
180 | /** | ||
181 | * irq_linear_revmap() - Find a linux irq from a hw irq number. | ||
182 | * @domain: domain owning this hardware interrupt | ||
183 | * @hwirq: hardware irq number in that domain space | ||
184 | * | ||
185 | * This is a fast path alternative to irq_find_mapping() that can be | ||
186 | * called directly by irq controller code to save a handful of | ||
187 | * instructions. It is always safe to call, but won't find irqs mapped | ||
188 | * using the radix tree. | ||
189 | */ | ||
190 | static inline unsigned int irq_linear_revmap(struct irq_domain *domain, | ||
191 | irq_hw_number_t hwirq) | ||
192 | { | ||
193 | return hwirq < domain->revmap_size ? domain->linear_revmap[hwirq] : 0; | ||
194 | } | ||
176 | extern unsigned int irq_find_mapping(struct irq_domain *host, | 195 | extern unsigned int irq_find_mapping(struct irq_domain *host, |
177 | irq_hw_number_t hwirq); | 196 | irq_hw_number_t hwirq); |
178 | extern unsigned int irq_create_direct_mapping(struct irq_domain *host); | 197 | extern unsigned int irq_create_direct_mapping(struct irq_domain *host); |
@@ -186,9 +205,6 @@ static inline int irq_create_identity_mapping(struct irq_domain *host, | |||
186 | return irq_create_strict_mappings(host, hwirq, hwirq, 1); | 205 | return irq_create_strict_mappings(host, hwirq, hwirq, 1); |
187 | } | 206 | } |
188 | 207 | ||
189 | extern unsigned int irq_linear_revmap(struct irq_domain *host, | ||
190 | irq_hw_number_t hwirq); | ||
191 | |||
192 | extern const struct irq_domain_ops irq_domain_simple_ops; | 208 | extern const struct irq_domain_ops irq_domain_simple_ops; |
193 | 209 | ||
194 | /* stock xlate functions */ | 210 | /* stock xlate functions */ |
@@ -202,14 +218,6 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, | |||
202 | const u32 *intspec, unsigned int intsize, | 218 | const u32 *intspec, unsigned int intsize, |
203 | irq_hw_number_t *out_hwirq, unsigned int *out_type); | 219 | irq_hw_number_t *out_hwirq, unsigned int *out_type); |
204 | 220 | ||
205 | #if defined(CONFIG_OF_IRQ) | ||
206 | extern void irq_domain_generate_simple(const struct of_device_id *match, | ||
207 | u64 phys_base, unsigned int irq_start); | ||
208 | #else /* CONFIG_OF_IRQ */ | ||
209 | static inline void irq_domain_generate_simple(const struct of_device_id *match, | ||
210 | u64 phys_base, unsigned int irq_start) { } | ||
211 | #endif /* !CONFIG_OF_IRQ */ | ||
212 | |||
213 | #else /* CONFIG_IRQ_DOMAIN */ | 221 | #else /* CONFIG_IRQ_DOMAIN */ |
214 | static inline void irq_dispose_mapping(unsigned int virq) { } | 222 | static inline void irq_dispose_mapping(unsigned int virq) { } |
215 | #endif /* !CONFIG_IRQ_DOMAIN */ | 223 | #endif /* !CONFIG_IRQ_DOMAIN */ |
diff --git a/include/linux/ktime.h b/include/linux/ktime.h index bbca12804d12..fc66b301b648 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h | |||
@@ -229,7 +229,8 @@ static inline ktime_t timespec_to_ktime(const struct timespec ts) | |||
229 | static inline ktime_t timeval_to_ktime(const struct timeval tv) | 229 | static inline ktime_t timeval_to_ktime(const struct timeval tv) |
230 | { | 230 | { |
231 | return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec, | 231 | return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec, |
232 | .nsec = (s32)tv.tv_usec * 1000 } }; | 232 | .nsec = (s32)(tv.tv_usec * |
233 | NSEC_PER_USEC) } }; | ||
233 | } | 234 | } |
234 | 235 | ||
235 | /** | 236 | /** |
@@ -320,12 +321,12 @@ static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) | |||
320 | 321 | ||
321 | static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec) | 322 | static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec) |
322 | { | 323 | { |
323 | return ktime_add_ns(kt, usec * 1000); | 324 | return ktime_add_ns(kt, usec * NSEC_PER_USEC); |
324 | } | 325 | } |
325 | 326 | ||
326 | static inline ktime_t ktime_sub_us(const ktime_t kt, const u64 usec) | 327 | static inline ktime_t ktime_sub_us(const ktime_t kt, const u64 usec) |
327 | { | 328 | { |
328 | return ktime_sub_ns(kt, usec * 1000); | 329 | return ktime_sub_ns(kt, usec * NSEC_PER_USEC); |
329 | } | 330 | } |
330 | 331 | ||
331 | extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs); | 332 | extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs); |
@@ -338,7 +339,8 @@ extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs); | |||
338 | * | 339 | * |
339 | * Returns true if there was a successful conversion, false if kt was 0. | 340 | * Returns true if there was a successful conversion, false if kt was 0. |
340 | */ | 341 | */ |
341 | static inline bool ktime_to_timespec_cond(const ktime_t kt, struct timespec *ts) | 342 | static inline __must_check bool ktime_to_timespec_cond(const ktime_t kt, |
343 | struct timespec *ts) | ||
342 | { | 344 | { |
343 | if (kt.tv64) { | 345 | if (kt.tv64) { |
344 | *ts = ktime_to_timespec(kt); | 346 | *ts = ktime_to_timespec(kt); |
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h index 364dda734877..ae36298ba076 100644 --- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h | |||
@@ -21,7 +21,6 @@ struct device_node; | |||
21 | struct of_dma { | 21 | struct of_dma { |
22 | struct list_head of_dma_controllers; | 22 | struct list_head of_dma_controllers; |
23 | struct device_node *of_node; | 23 | struct device_node *of_node; |
24 | int of_dma_nbcells; | ||
25 | struct dma_chan *(*of_dma_xlate) | 24 | struct dma_chan *(*of_dma_xlate) |
26 | (struct of_phandle_args *, struct of_dma *); | 25 | (struct of_phandle_args *, struct of_dma *); |
27 | void *of_dma_data; | 26 | void *of_dma_data; |
diff --git a/include/linux/platform_data/dma-atmel.h b/include/linux/platform_data/dma-atmel.h index cab0997be3de..e95f19c65873 100644 --- a/include/linux/platform_data/dma-atmel.h +++ b/include/linux/platform_data/dma-atmel.h | |||
@@ -35,16 +35,20 @@ struct at_dma_slave { | |||
35 | 35 | ||
36 | 36 | ||
37 | /* Platform-configurable bits in CFG */ | 37 | /* Platform-configurable bits in CFG */ |
38 | #define ATC_PER_MSB(h) ((0x30U & (h)) >> 4) /* Extract most significant bits of a handshaking identifier */ | ||
39 | |||
38 | #define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */ | 40 | #define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */ |
39 | #define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */ | 41 | #define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */ |
40 | #define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */ | 42 | #define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */ |
41 | #define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */ | 43 | #define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */ |
42 | #define ATC_SRC_H2SEL_SW (0x0 << 9) | 44 | #define ATC_SRC_H2SEL_SW (0x0 << 9) |
43 | #define ATC_SRC_H2SEL_HW (0x1 << 9) | 45 | #define ATC_SRC_H2SEL_HW (0x1 << 9) |
46 | #define ATC_SRC_PER_MSB(h) (ATC_PER_MSB(h) << 10) /* Channel src rq (most significant bits) */ | ||
44 | #define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */ | 47 | #define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */ |
45 | #define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */ | 48 | #define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */ |
46 | #define ATC_DST_H2SEL_SW (0x0 << 13) | 49 | #define ATC_DST_H2SEL_SW (0x0 << 13) |
47 | #define ATC_DST_H2SEL_HW (0x1 << 13) | 50 | #define ATC_DST_H2SEL_HW (0x1 << 13) |
51 | #define ATC_DST_PER_MSB(h) (ATC_PER_MSB(h) << 14) /* Channel dst rq (most significant bits) */ | ||
48 | #define ATC_SOD (0x1 << 16) /* Stop On Done */ | 52 | #define ATC_SOD (0x1 << 16) /* Stop On Done */ |
49 | #define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */ | 53 | #define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */ |
50 | #define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */ | 54 | #define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */ |
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h index f6d30cc1cb77..beac6b8b6a7b 100644 --- a/include/linux/platform_data/dma-imx.h +++ b/include/linux/platform_data/dma-imx.h | |||
@@ -60,10 +60,8 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan) | |||
60 | 60 | ||
61 | static inline int imx_dma_is_general_purpose(struct dma_chan *chan) | 61 | static inline int imx_dma_is_general_purpose(struct dma_chan *chan) |
62 | { | 62 | { |
63 | return strstr(dev_name(chan->device->dev), "sdma") || | 63 | return !strcmp(chan->device->dev->driver->name, "imx-sdma") || |
64 | !strcmp(dev_name(chan->device->dev), "imx1-dma") || | 64 | !strcmp(chan->device->dev->driver->name, "imx-dma"); |
65 | !strcmp(dev_name(chan->device->dev), "imx21-dma") || | ||
66 | !strcmp(dev_name(chan->device->dev), "imx27-dma"); | ||
67 | } | 65 | } |
68 | 66 | ||
69 | #endif | 67 | #endif |
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 7794d75ed155..907f3fd191ac 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h | |||
@@ -7,14 +7,20 @@ | |||
7 | #include <linux/timex.h> | 7 | #include <linux/timex.h> |
8 | #include <linux/alarmtimer.h> | 8 | #include <linux/alarmtimer.h> |
9 | 9 | ||
10 | union cpu_time_count { | 10 | |
11 | cputime_t cpu; | 11 | static inline unsigned long long cputime_to_expires(cputime_t expires) |
12 | unsigned long long sched; | 12 | { |
13 | }; | 13 | return (__force unsigned long long)expires; |
14 | } | ||
15 | |||
16 | static inline cputime_t expires_to_cputime(unsigned long long expires) | ||
17 | { | ||
18 | return (__force cputime_t)expires; | ||
19 | } | ||
14 | 20 | ||
15 | struct cpu_timer_list { | 21 | struct cpu_timer_list { |
16 | struct list_head entry; | 22 | struct list_head entry; |
17 | union cpu_time_count expires, incr; | 23 | unsigned long long expires, incr; |
18 | struct task_struct *task; | 24 | struct task_struct *task; |
19 | int firing; | 25 | int firing; |
20 | }; | 26 | }; |
diff --git a/include/linux/pvclock_gtod.h b/include/linux/pvclock_gtod.h index 0ca75825b60d..a71d2dbd3610 100644 --- a/include/linux/pvclock_gtod.h +++ b/include/linux/pvclock_gtod.h | |||
@@ -3,6 +3,13 @@ | |||
3 | 3 | ||
4 | #include <linux/notifier.h> | 4 | #include <linux/notifier.h> |
5 | 5 | ||
6 | /* | ||
7 | * The pvclock gtod notifier is called when the system time is updated | ||
8 | * and is used to keep guest time synchronized with host time. | ||
9 | * | ||
10 | * The 'action' parameter in the notifier function is false (0), or | ||
11 | * true (non-zero) if system time was stepped. | ||
12 | */ | ||
6 | extern int pvclock_gtod_register_notifier(struct notifier_block *nb); | 13 | extern int pvclock_gtod_register_notifier(struct notifier_block *nb); |
7 | extern int pvclock_gtod_unregister_notifier(struct notifier_block *nb); | 14 | extern int pvclock_gtod_unregister_notifier(struct notifier_block *nb); |
8 | 15 | ||
diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h new file mode 100644 index 000000000000..fa7922c80a41 --- /dev/null +++ b/include/linux/sched_clock.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * sched_clock.h: support for extending counters to full 64-bit ns counter | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #ifndef LINUX_SCHED_CLOCK | ||
9 | #define LINUX_SCHED_CLOCK | ||
10 | |||
11 | #ifdef CONFIG_GENERIC_SCHED_CLOCK | ||
12 | extern void sched_clock_postinit(void); | ||
13 | #else | ||
14 | static inline void sched_clock_postinit(void) { } | ||
15 | #endif | ||
16 | |||
17 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); | ||
18 | |||
19 | extern unsigned long long (*sched_clock_func)(void); | ||
20 | |||
21 | #endif | ||
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index b64d6bec6f90..4e83f3e034f3 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h | |||
@@ -99,6 +99,4 @@ struct sh_dmae_pdata { | |||
99 | #define CHCR_TE 0x00000002 | 99 | #define CHCR_TE 0x00000002 |
100 | #define CHCR_IE 0x00000004 | 100 | #define CHCR_IE 0x00000004 |
101 | 101 | ||
102 | bool shdma_chan_filter(struct dma_chan *chan, void *arg); | ||
103 | |||
104 | #endif | 102 | #endif |
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h index a3728bf66f0e..382cf710ca9a 100644 --- a/include/linux/shdma-base.h +++ b/include/linux/shdma-base.h | |||
@@ -68,6 +68,8 @@ struct shdma_chan { | |||
68 | int id; /* Raw id of this channel */ | 68 | int id; /* Raw id of this channel */ |
69 | int irq; /* Channel IRQ */ | 69 | int irq; /* Channel IRQ */ |
70 | int slave_id; /* Client ID for slave DMA */ | 70 | int slave_id; /* Client ID for slave DMA */ |
71 | int hw_req; /* DMA request line for slave DMA - same | ||
72 | * as MID/RID, used with DT */ | ||
71 | enum shdma_pm_state pm_state; | 73 | enum shdma_pm_state pm_state; |
72 | }; | 74 | }; |
73 | 75 | ||
@@ -122,5 +124,6 @@ void shdma_chan_remove(struct shdma_chan *schan); | |||
122 | int shdma_init(struct device *dev, struct shdma_dev *sdev, | 124 | int shdma_init(struct device *dev, struct shdma_dev *sdev, |
123 | int chan_num); | 125 | int chan_num); |
124 | void shdma_cleanup(struct shdma_dev *sdev); | 126 | void shdma_cleanup(struct shdma_dev *sdev); |
127 | bool shdma_chan_filter(struct dma_chan *chan, void *arg); | ||
125 | 128 | ||
126 | #endif | 129 | #endif |
diff --git a/include/uapi/mtd/ubi-user.h b/include/uapi/mtd/ubi-user.h index 53cae1e11e57..723c324590c1 100644 --- a/include/uapi/mtd/ubi-user.h +++ b/include/uapi/mtd/ubi-user.h | |||
@@ -173,7 +173,10 @@ | |||
173 | 173 | ||
174 | #define UBI_VOL_IOC_MAGIC 'O' | 174 | #define UBI_VOL_IOC_MAGIC 'O' |
175 | 175 | ||
176 | /* Start UBI volume update */ | 176 | /* Start UBI volume update |
177 | * Note: This actually takes a pointer (__s64*), but we can't change | ||
178 | * that without breaking the ABI on 32bit systems | ||
179 | */ | ||
177 | #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, __s64) | 180 | #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, __s64) |
178 | /* LEB erasure command, used for debugging, disabled by default */ | 181 | /* LEB erasure command, used for debugging, disabled by default */ |
179 | #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, __s32) | 182 | #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, __s32) |
diff --git a/init/Kconfig b/init/Kconfig index ef10d83bc379..ea1be003275a 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -780,6 +780,9 @@ config LOG_BUF_SHIFT | |||
780 | config HAVE_UNSTABLE_SCHED_CLOCK | 780 | config HAVE_UNSTABLE_SCHED_CLOCK |
781 | bool | 781 | bool |
782 | 782 | ||
783 | config GENERIC_SCHED_CLOCK | ||
784 | bool | ||
785 | |||
783 | # | 786 | # |
784 | # For architectures that want to enable the support for NUMA-affine scheduler | 787 | # For architectures that want to enable the support for NUMA-affine scheduler |
785 | # balancing logic: | 788 | # balancing logic: |
diff --git a/init/main.c b/init/main.c index f2366533c922..d03d2ec2eacf 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/ptrace.h> | 74 | #include <linux/ptrace.h> |
75 | #include <linux/blkdev.h> | 75 | #include <linux/blkdev.h> |
76 | #include <linux/elevator.h> | 76 | #include <linux/elevator.h> |
77 | #include <linux/sched_clock.h> | ||
77 | 78 | ||
78 | #include <asm/io.h> | 79 | #include <asm/io.h> |
79 | #include <asm/bugs.h> | 80 | #include <asm/bugs.h> |
@@ -554,6 +555,7 @@ asmlinkage void __init start_kernel(void) | |||
554 | softirq_init(); | 555 | softirq_init(); |
555 | timekeeping_init(); | 556 | timekeeping_init(); |
556 | time_init(); | 557 | time_init(); |
558 | sched_clock_postinit(); | ||
557 | perf_event_init(); | 559 | perf_event_init(); |
558 | profile_init(); | 560 | profile_init(); |
559 | call_function_init(); | 561 | call_function_init(); |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 3ee4d06c6fc2..f0f4fe29cd21 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -722,17 +722,20 @@ static int hrtimer_switch_to_hres(void) | |||
722 | return 1; | 722 | return 1; |
723 | } | 723 | } |
724 | 724 | ||
725 | static void clock_was_set_work(struct work_struct *work) | ||
726 | { | ||
727 | clock_was_set(); | ||
728 | } | ||
729 | |||
730 | static DECLARE_WORK(hrtimer_work, clock_was_set_work); | ||
731 | |||
725 | /* | 732 | /* |
726 | * Called from timekeeping code to reprogramm the hrtimer interrupt | 733 | * Called from timekeeping and resume code to reprogramm the hrtimer |
727 | * device. If called from the timer interrupt context we defer it to | 734 | * interrupt device on all cpus. |
728 | * softirq context. | ||
729 | */ | 735 | */ |
730 | void clock_was_set_delayed(void) | 736 | void clock_was_set_delayed(void) |
731 | { | 737 | { |
732 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | 738 | schedule_work(&hrtimer_work); |
733 | |||
734 | cpu_base->clock_was_set = 1; | ||
735 | __raise_softirq_irqoff(HRTIMER_SOFTIRQ); | ||
736 | } | 739 | } |
737 | 740 | ||
738 | #else | 741 | #else |
@@ -774,15 +777,19 @@ void clock_was_set(void) | |||
774 | 777 | ||
775 | /* | 778 | /* |
776 | * During resume we might have to reprogram the high resolution timer | 779 | * During resume we might have to reprogram the high resolution timer |
777 | * interrupt (on the local CPU): | 780 | * interrupt on all online CPUs. However, all other CPUs will be |
781 | * stopped with IRQs interrupts disabled so the clock_was_set() call | ||
782 | * must be deferred. | ||
778 | */ | 783 | */ |
779 | void hrtimers_resume(void) | 784 | void hrtimers_resume(void) |
780 | { | 785 | { |
781 | WARN_ONCE(!irqs_disabled(), | 786 | WARN_ONCE(!irqs_disabled(), |
782 | KERN_INFO "hrtimers_resume() called with IRQs enabled!"); | 787 | KERN_INFO "hrtimers_resume() called with IRQs enabled!"); |
783 | 788 | ||
789 | /* Retrigger on the local CPU */ | ||
784 | retrigger_next_event(NULL); | 790 | retrigger_next_event(NULL); |
785 | timerfd_clock_was_set(); | 791 | /* And schedule a retrigger for all others */ |
792 | clock_was_set_delayed(); | ||
786 | } | 793 | } |
787 | 794 | ||
788 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) | 795 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) |
@@ -1433,13 +1440,6 @@ void hrtimer_peek_ahead_timers(void) | |||
1433 | 1440 | ||
1434 | static void run_hrtimer_softirq(struct softirq_action *h) | 1441 | static void run_hrtimer_softirq(struct softirq_action *h) |
1435 | { | 1442 | { |
1436 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | ||
1437 | |||
1438 | if (cpu_base->clock_was_set) { | ||
1439 | cpu_base->clock_was_set = 0; | ||
1440 | clock_was_set(); | ||
1441 | } | ||
1442 | |||
1443 | hrtimer_peek_ahead_timers(); | 1443 | hrtimer_peek_ahead_timers(); |
1444 | } | 1444 | } |
1445 | 1445 | ||
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index e3544c19bdd2..10e663ab1f4a 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c | |||
@@ -275,10 +275,7 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, | |||
275 | if (d->gc) | 275 | if (d->gc) |
276 | return -EBUSY; | 276 | return -EBUSY; |
277 | 277 | ||
278 | if (d->revmap_type != IRQ_DOMAIN_MAP_LINEAR) | 278 | numchips = d->revmap_size / irqs_per_chip; |
279 | return -EINVAL; | ||
280 | |||
281 | numchips = d->revmap_data.linear.size / irqs_per_chip; | ||
282 | if (!numchips) | 279 | if (!numchips) |
283 | return -EINVAL; | 280 | return -EINVAL; |
284 | 281 | ||
@@ -310,6 +307,7 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, | |||
310 | /* Calc pointer to the next generic chip */ | 307 | /* Calc pointer to the next generic chip */ |
311 | tmp += sizeof(*gc) + num_ct * sizeof(struct irq_chip_type); | 308 | tmp += sizeof(*gc) + num_ct * sizeof(struct irq_chip_type); |
312 | } | 309 | } |
310 | d->name = name; | ||
313 | return 0; | 311 | return 0; |
314 | } | 312 | } |
315 | EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips); | 313 | EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips); |
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 1ed8dff17eb9..2d7cd3428365 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
@@ -23,9 +23,11 @@ static DEFINE_MUTEX(revmap_trees_mutex); | |||
23 | static struct irq_domain *irq_default_domain; | 23 | static struct irq_domain *irq_default_domain; |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * irq_domain_alloc() - Allocate a new irq_domain data structure | 26 | * __irq_domain_add() - Allocate a new irq_domain data structure |
27 | * @of_node: optional device-tree node of the interrupt controller | 27 | * @of_node: optional device-tree node of the interrupt controller |
28 | * @revmap_type: type of reverse mapping to use | 28 | * @size: Size of linear map; 0 for radix mapping only |
29 | * @direct_max: Maximum value of direct maps; Use ~0 for no limit; 0 for no | ||
30 | * direct mapping | ||
29 | * @ops: map/unmap domain callbacks | 31 | * @ops: map/unmap domain callbacks |
30 | * @host_data: Controller private data pointer | 32 | * @host_data: Controller private data pointer |
31 | * | 33 | * |
@@ -33,41 +35,35 @@ static struct irq_domain *irq_default_domain; | |||
33 | * register allocated irq_domain with irq_domain_register(). Returns pointer | 35 | * register allocated irq_domain with irq_domain_register(). Returns pointer |
34 | * to IRQ domain, or NULL on failure. | 36 | * to IRQ domain, or NULL on failure. |
35 | */ | 37 | */ |
36 | static struct irq_domain *irq_domain_alloc(struct device_node *of_node, | 38 | struct irq_domain *__irq_domain_add(struct device_node *of_node, int size, |
37 | unsigned int revmap_type, | 39 | irq_hw_number_t hwirq_max, int direct_max, |
38 | const struct irq_domain_ops *ops, | 40 | const struct irq_domain_ops *ops, |
39 | void *host_data) | 41 | void *host_data) |
40 | { | 42 | { |
41 | struct irq_domain *domain; | 43 | struct irq_domain *domain; |
42 | 44 | ||
43 | domain = kzalloc_node(sizeof(*domain), GFP_KERNEL, | 45 | domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size), |
44 | of_node_to_nid(of_node)); | 46 | GFP_KERNEL, of_node_to_nid(of_node)); |
45 | if (WARN_ON(!domain)) | 47 | if (WARN_ON(!domain)) |
46 | return NULL; | 48 | return NULL; |
47 | 49 | ||
48 | /* Fill structure */ | 50 | /* Fill structure */ |
49 | domain->revmap_type = revmap_type; | 51 | INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); |
50 | domain->ops = ops; | 52 | domain->ops = ops; |
51 | domain->host_data = host_data; | 53 | domain->host_data = host_data; |
52 | domain->of_node = of_node_get(of_node); | 54 | domain->of_node = of_node_get(of_node); |
55 | domain->hwirq_max = hwirq_max; | ||
56 | domain->revmap_size = size; | ||
57 | domain->revmap_direct_max_irq = direct_max; | ||
53 | 58 | ||
54 | return domain; | ||
55 | } | ||
56 | |||
57 | static void irq_domain_free(struct irq_domain *domain) | ||
58 | { | ||
59 | of_node_put(domain->of_node); | ||
60 | kfree(domain); | ||
61 | } | ||
62 | |||
63 | static void irq_domain_add(struct irq_domain *domain) | ||
64 | { | ||
65 | mutex_lock(&irq_domain_mutex); | 59 | mutex_lock(&irq_domain_mutex); |
66 | list_add(&domain->link, &irq_domain_list); | 60 | list_add(&domain->link, &irq_domain_list); |
67 | mutex_unlock(&irq_domain_mutex); | 61 | mutex_unlock(&irq_domain_mutex); |
68 | pr_debug("Allocated domain of type %d @0x%p\n", | 62 | |
69 | domain->revmap_type, domain); | 63 | pr_debug("Added domain %s\n", domain->name); |
64 | return domain; | ||
70 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(__irq_domain_add); | ||
71 | 67 | ||
72 | /** | 68 | /** |
73 | * irq_domain_remove() - Remove an irq domain. | 69 | * irq_domain_remove() - Remove an irq domain. |
@@ -81,29 +77,12 @@ void irq_domain_remove(struct irq_domain *domain) | |||
81 | { | 77 | { |
82 | mutex_lock(&irq_domain_mutex); | 78 | mutex_lock(&irq_domain_mutex); |
83 | 79 | ||
84 | switch (domain->revmap_type) { | 80 | /* |
85 | case IRQ_DOMAIN_MAP_LEGACY: | 81 | * radix_tree_delete() takes care of destroying the root |
86 | /* | 82 | * node when all entries are removed. Shout if there are |
87 | * Legacy domains don't manage their own irq_desc | 83 | * any mappings left. |
88 | * allocations, we expect the caller to handle irq_desc | 84 | */ |
89 | * freeing on their own. | 85 | WARN_ON(domain->revmap_tree.height); |
90 | */ | ||
91 | break; | ||
92 | case IRQ_DOMAIN_MAP_TREE: | ||
93 | /* | ||
94 | * radix_tree_delete() takes care of destroying the root | ||
95 | * node when all entries are removed. Shout if there are | ||
96 | * any mappings left. | ||
97 | */ | ||
98 | WARN_ON(domain->revmap_data.tree.height); | ||
99 | break; | ||
100 | case IRQ_DOMAIN_MAP_LINEAR: | ||
101 | kfree(domain->revmap_data.linear.revmap); | ||
102 | domain->revmap_data.linear.size = 0; | ||
103 | break; | ||
104 | case IRQ_DOMAIN_MAP_NOMAP: | ||
105 | break; | ||
106 | } | ||
107 | 86 | ||
108 | list_del(&domain->link); | 87 | list_del(&domain->link); |
109 | 88 | ||
@@ -115,44 +94,30 @@ void irq_domain_remove(struct irq_domain *domain) | |||
115 | 94 | ||
116 | mutex_unlock(&irq_domain_mutex); | 95 | mutex_unlock(&irq_domain_mutex); |
117 | 96 | ||
118 | pr_debug("Removed domain of type %d @0x%p\n", | 97 | pr_debug("Removed domain %s\n", domain->name); |
119 | domain->revmap_type, domain); | ||
120 | 98 | ||
121 | irq_domain_free(domain); | 99 | of_node_put(domain->of_node); |
100 | kfree(domain); | ||
122 | } | 101 | } |
123 | EXPORT_SYMBOL_GPL(irq_domain_remove); | 102 | EXPORT_SYMBOL_GPL(irq_domain_remove); |
124 | 103 | ||
125 | static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain, | ||
126 | irq_hw_number_t hwirq) | ||
127 | { | ||
128 | irq_hw_number_t first_hwirq = domain->revmap_data.legacy.first_hwirq; | ||
129 | int size = domain->revmap_data.legacy.size; | ||
130 | |||
131 | if (WARN_ON(hwirq < first_hwirq || hwirq >= first_hwirq + size)) | ||
132 | return 0; | ||
133 | return hwirq - first_hwirq + domain->revmap_data.legacy.first_irq; | ||
134 | } | ||
135 | |||
136 | /** | 104 | /** |
137 | * irq_domain_add_simple() - Allocate and register a simple irq_domain. | 105 | * irq_domain_add_simple() - Register an irq_domain and optionally map a range of irqs |
138 | * @of_node: pointer to interrupt controller's device tree node. | 106 | * @of_node: pointer to interrupt controller's device tree node. |
139 | * @size: total number of irqs in mapping | 107 | * @size: total number of irqs in mapping |
140 | * @first_irq: first number of irq block assigned to the domain, | 108 | * @first_irq: first number of irq block assigned to the domain, |
141 | * pass zero to assign irqs on-the-fly. This will result in a | 109 | * pass zero to assign irqs on-the-fly. If first_irq is non-zero, then |
142 | * linear IRQ domain so it is important to use irq_create_mapping() | 110 | * pre-map all of the irqs in the domain to virqs starting at first_irq. |
143 | * for each used IRQ, especially when SPARSE_IRQ is enabled. | ||
144 | * @ops: map/unmap domain callbacks | 111 | * @ops: map/unmap domain callbacks |
145 | * @host_data: Controller private data pointer | 112 | * @host_data: Controller private data pointer |
146 | * | 113 | * |
147 | * Allocates a legacy irq_domain if irq_base is positive or a linear | 114 | * Allocates an irq_domain, and optionally if first_irq is positive then also |
148 | * domain otherwise. For the legacy domain, IRQ descriptors will also | 115 | * allocate irq_descs and map all of the hwirqs to virqs starting at first_irq. |
149 | * be allocated. | ||
150 | * | 116 | * |
151 | * This is intended to implement the expected behaviour for most | 117 | * This is intended to implement the expected behaviour for most |
152 | * interrupt controllers which is that a linear mapping should | 118 | * interrupt controllers. If device tree is used, then first_irq will be 0 and |
153 | * normally be used unless the system requires a legacy mapping in | 119 | * irqs get mapped dynamically on the fly. However, if the controller requires |
154 | * order to support supplying interrupt numbers during non-DT | 120 | * static virq assignments (non-DT boot) then it will set that up correctly. |
155 | * registration of devices. | ||
156 | */ | 121 | */ |
157 | struct irq_domain *irq_domain_add_simple(struct device_node *of_node, | 122 | struct irq_domain *irq_domain_add_simple(struct device_node *of_node, |
158 | unsigned int size, | 123 | unsigned int size, |
@@ -160,33 +125,25 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node, | |||
160 | const struct irq_domain_ops *ops, | 125 | const struct irq_domain_ops *ops, |
161 | void *host_data) | 126 | void *host_data) |
162 | { | 127 | { |
163 | if (first_irq > 0) { | 128 | struct irq_domain *domain; |
164 | int irq_base; | 129 | |
130 | domain = __irq_domain_add(of_node, size, size, 0, ops, host_data); | ||
131 | if (!domain) | ||
132 | return NULL; | ||
165 | 133 | ||
134 | if (first_irq > 0) { | ||
166 | if (IS_ENABLED(CONFIG_SPARSE_IRQ)) { | 135 | if (IS_ENABLED(CONFIG_SPARSE_IRQ)) { |
167 | /* | 136 | /* attempt to allocated irq_descs */ |
168 | * Set the descriptor allocator to search for a | 137 | int rc = irq_alloc_descs(first_irq, first_irq, size, |
169 | * 1-to-1 mapping, such as irq_alloc_desc_at(). | 138 | of_node_to_nid(of_node)); |
170 | * Use of_node_to_nid() which is defined to | 139 | if (rc < 0) |
171 | * numa_node_id() on platforms that have no custom | ||
172 | * implementation. | ||
173 | */ | ||
174 | irq_base = irq_alloc_descs(first_irq, first_irq, size, | ||
175 | of_node_to_nid(of_node)); | ||
176 | if (irq_base < 0) { | ||
177 | pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", | 140 | pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", |
178 | first_irq); | 141 | first_irq); |
179 | irq_base = first_irq; | 142 | } |
180 | } | 143 | irq_domain_associate_many(domain, first_irq, 0, size); |
181 | } else | ||
182 | irq_base = first_irq; | ||
183 | |||
184 | return irq_domain_add_legacy(of_node, size, irq_base, 0, | ||
185 | ops, host_data); | ||
186 | } | 144 | } |
187 | 145 | ||
188 | /* A linear domain is the default */ | 146 | return domain; |
189 | return irq_domain_add_linear(of_node, size, ops, host_data); | ||
190 | } | 147 | } |
191 | EXPORT_SYMBOL_GPL(irq_domain_add_simple); | 148 | EXPORT_SYMBOL_GPL(irq_domain_add_simple); |
192 | 149 | ||
@@ -213,131 +170,19 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, | |||
213 | void *host_data) | 170 | void *host_data) |
214 | { | 171 | { |
215 | struct irq_domain *domain; | 172 | struct irq_domain *domain; |
216 | unsigned int i; | ||
217 | 173 | ||
218 | domain = irq_domain_alloc(of_node, IRQ_DOMAIN_MAP_LEGACY, ops, host_data); | 174 | domain = __irq_domain_add(of_node, first_hwirq + size, |
175 | first_hwirq + size, 0, ops, host_data); | ||
219 | if (!domain) | 176 | if (!domain) |
220 | return NULL; | 177 | return NULL; |
221 | 178 | ||
222 | domain->revmap_data.legacy.first_irq = first_irq; | 179 | irq_domain_associate_many(domain, first_irq, first_hwirq, size); |
223 | domain->revmap_data.legacy.first_hwirq = first_hwirq; | ||
224 | domain->revmap_data.legacy.size = size; | ||
225 | 180 | ||
226 | mutex_lock(&irq_domain_mutex); | ||
227 | /* Verify that all the irqs are available */ | ||
228 | for (i = 0; i < size; i++) { | ||
229 | int irq = first_irq + i; | ||
230 | struct irq_data *irq_data = irq_get_irq_data(irq); | ||
231 | |||
232 | if (WARN_ON(!irq_data || irq_data->domain)) { | ||
233 | mutex_unlock(&irq_domain_mutex); | ||
234 | irq_domain_free(domain); | ||
235 | return NULL; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /* Claim all of the irqs before registering a legacy domain */ | ||
240 | for (i = 0; i < size; i++) { | ||
241 | struct irq_data *irq_data = irq_get_irq_data(first_irq + i); | ||
242 | irq_data->hwirq = first_hwirq + i; | ||
243 | irq_data->domain = domain; | ||
244 | } | ||
245 | mutex_unlock(&irq_domain_mutex); | ||
246 | |||
247 | for (i = 0; i < size; i++) { | ||
248 | int irq = first_irq + i; | ||
249 | int hwirq = first_hwirq + i; | ||
250 | |||
251 | /* IRQ0 gets ignored */ | ||
252 | if (!irq) | ||
253 | continue; | ||
254 | |||
255 | /* Legacy flags are left to default at this point, | ||
256 | * one can then use irq_create_mapping() to | ||
257 | * explicitly change them | ||
258 | */ | ||
259 | if (ops->map) | ||
260 | ops->map(domain, irq, hwirq); | ||
261 | |||
262 | /* Clear norequest flags */ | ||
263 | irq_clear_status_flags(irq, IRQ_NOREQUEST); | ||
264 | } | ||
265 | |||
266 | irq_domain_add(domain); | ||
267 | return domain; | 181 | return domain; |
268 | } | 182 | } |
269 | EXPORT_SYMBOL_GPL(irq_domain_add_legacy); | 183 | EXPORT_SYMBOL_GPL(irq_domain_add_legacy); |
270 | 184 | ||
271 | /** | 185 | /** |
272 | * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain. | ||
273 | * @of_node: pointer to interrupt controller's device tree node. | ||
274 | * @size: Number of interrupts in the domain. | ||
275 | * @ops: map/unmap domain callbacks | ||
276 | * @host_data: Controller private data pointer | ||
277 | */ | ||
278 | struct irq_domain *irq_domain_add_linear(struct device_node *of_node, | ||
279 | unsigned int size, | ||
280 | const struct irq_domain_ops *ops, | ||
281 | void *host_data) | ||
282 | { | ||
283 | struct irq_domain *domain; | ||
284 | unsigned int *revmap; | ||
285 | |||
286 | revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL, | ||
287 | of_node_to_nid(of_node)); | ||
288 | if (WARN_ON(!revmap)) | ||
289 | return NULL; | ||
290 | |||
291 | domain = irq_domain_alloc(of_node, IRQ_DOMAIN_MAP_LINEAR, ops, host_data); | ||
292 | if (!domain) { | ||
293 | kfree(revmap); | ||
294 | return NULL; | ||
295 | } | ||
296 | domain->revmap_data.linear.size = size; | ||
297 | domain->revmap_data.linear.revmap = revmap; | ||
298 | irq_domain_add(domain); | ||
299 | return domain; | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(irq_domain_add_linear); | ||
302 | |||
303 | struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, | ||
304 | unsigned int max_irq, | ||
305 | const struct irq_domain_ops *ops, | ||
306 | void *host_data) | ||
307 | { | ||
308 | struct irq_domain *domain = irq_domain_alloc(of_node, | ||
309 | IRQ_DOMAIN_MAP_NOMAP, ops, host_data); | ||
310 | if (domain) { | ||
311 | domain->revmap_data.nomap.max_irq = max_irq ? max_irq : ~0; | ||
312 | irq_domain_add(domain); | ||
313 | } | ||
314 | return domain; | ||
315 | } | ||
316 | EXPORT_SYMBOL_GPL(irq_domain_add_nomap); | ||
317 | |||
318 | /** | ||
319 | * irq_domain_add_tree() | ||
320 | * @of_node: pointer to interrupt controller's device tree node. | ||
321 | * @ops: map/unmap domain callbacks | ||
322 | * | ||
323 | * Note: The radix tree will be allocated later during boot automatically | ||
324 | * (the reverse mapping will use the slow path until that happens). | ||
325 | */ | ||
326 | struct irq_domain *irq_domain_add_tree(struct device_node *of_node, | ||
327 | const struct irq_domain_ops *ops, | ||
328 | void *host_data) | ||
329 | { | ||
330 | struct irq_domain *domain = irq_domain_alloc(of_node, | ||
331 | IRQ_DOMAIN_MAP_TREE, ops, host_data); | ||
332 | if (domain) { | ||
333 | INIT_RADIX_TREE(&domain->revmap_data.tree, GFP_KERNEL); | ||
334 | irq_domain_add(domain); | ||
335 | } | ||
336 | return domain; | ||
337 | } | ||
338 | EXPORT_SYMBOL_GPL(irq_domain_add_tree); | ||
339 | |||
340 | /** | ||
341 | * irq_find_host() - Locates a domain for a given device node | 186 | * irq_find_host() - Locates a domain for a given device node |
342 | * @node: device-tree node of the interrupt controller | 187 | * @node: device-tree node of the interrupt controller |
343 | */ | 188 | */ |
@@ -385,125 +230,108 @@ void irq_set_default_host(struct irq_domain *domain) | |||
385 | } | 230 | } |
386 | EXPORT_SYMBOL_GPL(irq_set_default_host); | 231 | EXPORT_SYMBOL_GPL(irq_set_default_host); |
387 | 232 | ||
388 | static void irq_domain_disassociate_many(struct irq_domain *domain, | 233 | static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq) |
389 | unsigned int irq_base, int count) | ||
390 | { | 234 | { |
391 | /* | 235 | struct irq_data *irq_data = irq_get_irq_data(irq); |
392 | * disassociate in reverse order; | 236 | irq_hw_number_t hwirq; |
393 | * not strictly necessary, but nice for unwinding | ||
394 | */ | ||
395 | while (count--) { | ||
396 | int irq = irq_base + count; | ||
397 | struct irq_data *irq_data = irq_get_irq_data(irq); | ||
398 | irq_hw_number_t hwirq; | ||
399 | 237 | ||
400 | if (WARN_ON(!irq_data || irq_data->domain != domain)) | 238 | if (WARN(!irq_data || irq_data->domain != domain, |
401 | continue; | 239 | "virq%i doesn't exist; cannot disassociate\n", irq)) |
240 | return; | ||
402 | 241 | ||
403 | hwirq = irq_data->hwirq; | 242 | hwirq = irq_data->hwirq; |
404 | irq_set_status_flags(irq, IRQ_NOREQUEST); | 243 | irq_set_status_flags(irq, IRQ_NOREQUEST); |
405 | 244 | ||
406 | /* remove chip and handler */ | 245 | /* remove chip and handler */ |
407 | irq_set_chip_and_handler(irq, NULL, NULL); | 246 | irq_set_chip_and_handler(irq, NULL, NULL); |
408 | 247 | ||
409 | /* Make sure it's completed */ | 248 | /* Make sure it's completed */ |
410 | synchronize_irq(irq); | 249 | synchronize_irq(irq); |
411 | 250 | ||
412 | /* Tell the PIC about it */ | 251 | /* Tell the PIC about it */ |
413 | if (domain->ops->unmap) | 252 | if (domain->ops->unmap) |
414 | domain->ops->unmap(domain, irq); | 253 | domain->ops->unmap(domain, irq); |
415 | smp_mb(); | 254 | smp_mb(); |
416 | 255 | ||
417 | irq_data->domain = NULL; | 256 | irq_data->domain = NULL; |
418 | irq_data->hwirq = 0; | 257 | irq_data->hwirq = 0; |
419 | 258 | ||
420 | /* Clear reverse map */ | 259 | /* Clear reverse map for this hwirq */ |
421 | switch(domain->revmap_type) { | 260 | if (hwirq < domain->revmap_size) { |
422 | case IRQ_DOMAIN_MAP_LINEAR: | 261 | domain->linear_revmap[hwirq] = 0; |
423 | if (hwirq < domain->revmap_data.linear.size) | 262 | } else { |
424 | domain->revmap_data.linear.revmap[hwirq] = 0; | 263 | mutex_lock(&revmap_trees_mutex); |
425 | break; | 264 | radix_tree_delete(&domain->revmap_tree, hwirq); |
426 | case IRQ_DOMAIN_MAP_TREE: | 265 | mutex_unlock(&revmap_trees_mutex); |
427 | mutex_lock(&revmap_trees_mutex); | ||
428 | radix_tree_delete(&domain->revmap_data.tree, hwirq); | ||
429 | mutex_unlock(&revmap_trees_mutex); | ||
430 | break; | ||
431 | } | ||
432 | } | 266 | } |
433 | } | 267 | } |
434 | 268 | ||
435 | int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, | 269 | int irq_domain_associate(struct irq_domain *domain, unsigned int virq, |
436 | irq_hw_number_t hwirq_base, int count) | 270 | irq_hw_number_t hwirq) |
437 | { | 271 | { |
438 | unsigned int virq = irq_base; | 272 | struct irq_data *irq_data = irq_get_irq_data(virq); |
439 | irq_hw_number_t hwirq = hwirq_base; | 273 | int ret; |
440 | int i, ret; | ||
441 | 274 | ||
442 | pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__, | 275 | if (WARN(hwirq >= domain->hwirq_max, |
443 | of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count); | 276 | "error: hwirq 0x%x is too large for %s\n", (int)hwirq, domain->name)) |
277 | return -EINVAL; | ||
278 | if (WARN(!irq_data, "error: virq%i is not allocated", virq)) | ||
279 | return -EINVAL; | ||
280 | if (WARN(irq_data->domain, "error: virq%i is already associated", virq)) | ||
281 | return -EINVAL; | ||
444 | 282 | ||
445 | for (i = 0; i < count; i++) { | 283 | mutex_lock(&irq_domain_mutex); |
446 | struct irq_data *irq_data = irq_get_irq_data(virq + i); | 284 | irq_data->hwirq = hwirq; |
447 | 285 | irq_data->domain = domain; | |
448 | if (WARN(!irq_data, "error: irq_desc not allocated; " | 286 | if (domain->ops->map) { |
449 | "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i)) | 287 | ret = domain->ops->map(domain, virq, hwirq); |
450 | return -EINVAL; | 288 | if (ret != 0) { |
451 | if (WARN(irq_data->domain, "error: irq_desc already associated; " | 289 | /* |
452 | "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i)) | 290 | * If map() returns -EPERM, this interrupt is protected |
453 | return -EINVAL; | 291 | * by the firmware or some other service and shall not |
454 | }; | 292 | * be mapped. Don't bother telling the user about it. |
455 | 293 | */ | |
456 | for (i = 0; i < count; i++, virq++, hwirq++) { | 294 | if (ret != -EPERM) { |
457 | struct irq_data *irq_data = irq_get_irq_data(virq); | 295 | pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n", |
458 | 296 | domain->name, hwirq, virq, ret); | |
459 | irq_data->hwirq = hwirq; | ||
460 | irq_data->domain = domain; | ||
461 | if (domain->ops->map) { | ||
462 | ret = domain->ops->map(domain, virq, hwirq); | ||
463 | if (ret != 0) { | ||
464 | /* | ||
465 | * If map() returns -EPERM, this interrupt is protected | ||
466 | * by the firmware or some other service and shall not | ||
467 | * be mapped. | ||
468 | * | ||
469 | * Since on some platforms we blindly try to map everything | ||
470 | * we end up with a log full of backtraces. | ||
471 | * | ||
472 | * So instead, we silently fail on -EPERM, it is the | ||
473 | * responsibility of the PIC driver to display a relevant | ||
474 | * message if needed. | ||
475 | */ | ||
476 | if (ret != -EPERM) { | ||
477 | pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n", | ||
478 | virq, hwirq, ret); | ||
479 | WARN_ON(1); | ||
480 | } | ||
481 | irq_data->domain = NULL; | ||
482 | irq_data->hwirq = 0; | ||
483 | goto err_unmap; | ||
484 | } | 297 | } |
298 | irq_data->domain = NULL; | ||
299 | irq_data->hwirq = 0; | ||
300 | mutex_unlock(&irq_domain_mutex); | ||
301 | return ret; | ||
485 | } | 302 | } |
486 | 303 | ||
487 | switch (domain->revmap_type) { | 304 | /* If not already assigned, give the domain the chip's name */ |
488 | case IRQ_DOMAIN_MAP_LINEAR: | 305 | if (!domain->name && irq_data->chip) |
489 | if (hwirq < domain->revmap_data.linear.size) | 306 | domain->name = irq_data->chip->name; |
490 | domain->revmap_data.linear.revmap[hwirq] = virq; | 307 | } |
491 | break; | ||
492 | case IRQ_DOMAIN_MAP_TREE: | ||
493 | mutex_lock(&revmap_trees_mutex); | ||
494 | radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data); | ||
495 | mutex_unlock(&revmap_trees_mutex); | ||
496 | break; | ||
497 | } | ||
498 | 308 | ||
499 | irq_clear_status_flags(virq, IRQ_NOREQUEST); | 309 | if (hwirq < domain->revmap_size) { |
310 | domain->linear_revmap[hwirq] = virq; | ||
311 | } else { | ||
312 | mutex_lock(&revmap_trees_mutex); | ||
313 | radix_tree_insert(&domain->revmap_tree, hwirq, irq_data); | ||
314 | mutex_unlock(&revmap_trees_mutex); | ||
500 | } | 315 | } |
316 | mutex_unlock(&irq_domain_mutex); | ||
317 | |||
318 | irq_clear_status_flags(virq, IRQ_NOREQUEST); | ||
501 | 319 | ||
502 | return 0; | 320 | return 0; |
321 | } | ||
322 | EXPORT_SYMBOL_GPL(irq_domain_associate); | ||
503 | 323 | ||
504 | err_unmap: | 324 | void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, |
505 | irq_domain_disassociate_many(domain, irq_base, i); | 325 | irq_hw_number_t hwirq_base, int count) |
506 | return -EINVAL; | 326 | { |
327 | int i; | ||
328 | |||
329 | pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__, | ||
330 | of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count); | ||
331 | |||
332 | for (i = 0; i < count; i++) { | ||
333 | irq_domain_associate(domain, irq_base + i, hwirq_base + i); | ||
334 | } | ||
507 | } | 335 | } |
508 | EXPORT_SYMBOL_GPL(irq_domain_associate_many); | 336 | EXPORT_SYMBOL_GPL(irq_domain_associate_many); |
509 | 337 | ||
@@ -513,7 +341,9 @@ EXPORT_SYMBOL_GPL(irq_domain_associate_many); | |||
513 | * | 341 | * |
514 | * This routine is used for irq controllers which can choose the hardware | 342 | * This routine is used for irq controllers which can choose the hardware |
515 | * interrupt numbers they generate. In such a case it's simplest to use | 343 | * interrupt numbers they generate. In such a case it's simplest to use |
516 | * the linux irq as the hardware interrupt number. | 344 | * the linux irq as the hardware interrupt number. It still uses the linear |
345 | * or radix tree to store the mapping, but the irq controller can optimize | ||
346 | * the revmap path by using the hwirq directly. | ||
517 | */ | 347 | */ |
518 | unsigned int irq_create_direct_mapping(struct irq_domain *domain) | 348 | unsigned int irq_create_direct_mapping(struct irq_domain *domain) |
519 | { | 349 | { |
@@ -522,17 +352,14 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) | |||
522 | if (domain == NULL) | 352 | if (domain == NULL) |
523 | domain = irq_default_domain; | 353 | domain = irq_default_domain; |
524 | 354 | ||
525 | if (WARN_ON(!domain || domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP)) | ||
526 | return 0; | ||
527 | |||
528 | virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); | 355 | virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); |
529 | if (!virq) { | 356 | if (!virq) { |
530 | pr_debug("create_direct virq allocation failed\n"); | 357 | pr_debug("create_direct virq allocation failed\n"); |
531 | return 0; | 358 | return 0; |
532 | } | 359 | } |
533 | if (virq >= domain->revmap_data.nomap.max_irq) { | 360 | if (virq >= domain->revmap_direct_max_irq) { |
534 | pr_err("ERROR: no free irqs available below %i maximum\n", | 361 | pr_err("ERROR: no free irqs available below %i maximum\n", |
535 | domain->revmap_data.nomap.max_irq); | 362 | domain->revmap_direct_max_irq); |
536 | irq_free_desc(virq); | 363 | irq_free_desc(virq); |
537 | return 0; | 364 | return 0; |
538 | } | 365 | } |
@@ -569,9 +396,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, | |||
569 | if (domain == NULL) | 396 | if (domain == NULL) |
570 | domain = irq_default_domain; | 397 | domain = irq_default_domain; |
571 | if (domain == NULL) { | 398 | if (domain == NULL) { |
572 | pr_warning("irq_create_mapping called for" | 399 | WARN(1, "%s(, %lx) called with NULL domain\n", __func__, hwirq); |
573 | " NULL domain, hwirq=%lx\n", hwirq); | ||
574 | WARN_ON(1); | ||
575 | return 0; | 400 | return 0; |
576 | } | 401 | } |
577 | pr_debug("-> using domain @%p\n", domain); | 402 | pr_debug("-> using domain @%p\n", domain); |
@@ -583,10 +408,6 @@ unsigned int irq_create_mapping(struct irq_domain *domain, | |||
583 | return virq; | 408 | return virq; |
584 | } | 409 | } |
585 | 410 | ||
586 | /* Get a virtual interrupt number */ | ||
587 | if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) | ||
588 | return irq_domain_legacy_revmap(domain, hwirq); | ||
589 | |||
590 | /* Allocate a virtual interrupt number */ | 411 | /* Allocate a virtual interrupt number */ |
591 | hint = hwirq % nr_irqs; | 412 | hint = hwirq % nr_irqs; |
592 | if (hint == 0) | 413 | if (hint == 0) |
@@ -639,12 +460,7 @@ int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base, | |||
639 | if (unlikely(ret < 0)) | 460 | if (unlikely(ret < 0)) |
640 | return ret; | 461 | return ret; |
641 | 462 | ||
642 | ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count); | 463 | irq_domain_associate_many(domain, irq_base, hwirq_base, count); |
643 | if (unlikely(ret < 0)) { | ||
644 | irq_free_descs(irq_base, count); | ||
645 | return ret; | ||
646 | } | ||
647 | |||
648 | return 0; | 464 | return 0; |
649 | } | 465 | } |
650 | EXPORT_SYMBOL_GPL(irq_create_strict_mappings); | 466 | EXPORT_SYMBOL_GPL(irq_create_strict_mappings); |
@@ -671,8 +487,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller, | |||
671 | if (intsize > 0) | 487 | if (intsize > 0) |
672 | return intspec[0]; | 488 | return intspec[0]; |
673 | #endif | 489 | #endif |
674 | pr_warning("no irq domain found for %s !\n", | 490 | pr_warn("no irq domain found for %s !\n", |
675 | of_node_full_name(controller)); | 491 | of_node_full_name(controller)); |
676 | return 0; | 492 | return 0; |
677 | } | 493 | } |
678 | 494 | ||
@@ -714,11 +530,7 @@ void irq_dispose_mapping(unsigned int virq) | |||
714 | if (WARN_ON(domain == NULL)) | 530 | if (WARN_ON(domain == NULL)) |
715 | return; | 531 | return; |
716 | 532 | ||
717 | /* Never unmap legacy interrupts */ | 533 | irq_domain_disassociate(domain, virq); |
718 | if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) | ||
719 | return; | ||
720 | |||
721 | irq_domain_disassociate_many(domain, virq, 1); | ||
722 | irq_free_desc(virq); | 534 | irq_free_desc(virq); |
723 | } | 535 | } |
724 | EXPORT_SYMBOL_GPL(irq_dispose_mapping); | 536 | EXPORT_SYMBOL_GPL(irq_dispose_mapping); |
@@ -739,63 +551,51 @@ unsigned int irq_find_mapping(struct irq_domain *domain, | |||
739 | if (domain == NULL) | 551 | if (domain == NULL) |
740 | return 0; | 552 | return 0; |
741 | 553 | ||
742 | switch (domain->revmap_type) { | 554 | if (hwirq < domain->revmap_direct_max_irq) { |
743 | case IRQ_DOMAIN_MAP_LEGACY: | ||
744 | return irq_domain_legacy_revmap(domain, hwirq); | ||
745 | case IRQ_DOMAIN_MAP_LINEAR: | ||
746 | return irq_linear_revmap(domain, hwirq); | ||
747 | case IRQ_DOMAIN_MAP_TREE: | ||
748 | rcu_read_lock(); | ||
749 | data = radix_tree_lookup(&domain->revmap_data.tree, hwirq); | ||
750 | rcu_read_unlock(); | ||
751 | if (data) | ||
752 | return data->irq; | ||
753 | break; | ||
754 | case IRQ_DOMAIN_MAP_NOMAP: | ||
755 | data = irq_get_irq_data(hwirq); | 555 | data = irq_get_irq_data(hwirq); |
756 | if (data && (data->domain == domain) && (data->hwirq == hwirq)) | 556 | if (data && (data->domain == domain) && (data->hwirq == hwirq)) |
757 | return hwirq; | 557 | return hwirq; |
758 | break; | ||
759 | } | 558 | } |
760 | 559 | ||
761 | return 0; | 560 | /* Check if the hwirq is in the linear revmap. */ |
762 | } | 561 | if (hwirq < domain->revmap_size) |
763 | EXPORT_SYMBOL_GPL(irq_find_mapping); | 562 | return domain->linear_revmap[hwirq]; |
764 | 563 | ||
765 | /** | 564 | rcu_read_lock(); |
766 | * irq_linear_revmap() - Find a linux irq from a hw irq number. | 565 | data = radix_tree_lookup(&domain->revmap_tree, hwirq); |
767 | * @domain: domain owning this hardware interrupt | 566 | rcu_read_unlock(); |
768 | * @hwirq: hardware irq number in that domain space | 567 | return data ? data->irq : 0; |
769 | * | ||
770 | * This is a fast path that can be called directly by irq controller code to | ||
771 | * save a handful of instructions. | ||
772 | */ | ||
773 | unsigned int irq_linear_revmap(struct irq_domain *domain, | ||
774 | irq_hw_number_t hwirq) | ||
775 | { | ||
776 | BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR); | ||
777 | |||
778 | /* Check revmap bounds; complain if exceeded */ | ||
779 | if (WARN_ON(hwirq >= domain->revmap_data.linear.size)) | ||
780 | return 0; | ||
781 | |||
782 | return domain->revmap_data.linear.revmap[hwirq]; | ||
783 | } | 568 | } |
784 | EXPORT_SYMBOL_GPL(irq_linear_revmap); | 569 | EXPORT_SYMBOL_GPL(irq_find_mapping); |
785 | 570 | ||
786 | #ifdef CONFIG_IRQ_DOMAIN_DEBUG | 571 | #ifdef CONFIG_IRQ_DOMAIN_DEBUG |
787 | static int virq_debug_show(struct seq_file *m, void *private) | 572 | static int virq_debug_show(struct seq_file *m, void *private) |
788 | { | 573 | { |
789 | unsigned long flags; | 574 | unsigned long flags; |
790 | struct irq_desc *desc; | 575 | struct irq_desc *desc; |
791 | const char *p; | 576 | struct irq_domain *domain; |
792 | static const char none[] = "none"; | 577 | struct radix_tree_iter iter; |
793 | void *data; | 578 | void *data, **slot; |
794 | int i; | 579 | int i; |
795 | 580 | ||
796 | seq_printf(m, "%-5s %-7s %-15s %-*s %s\n", "irq", "hwirq", | 581 | seq_printf(m, " %-16s %-6s %-10s %-10s %s\n", |
582 | "name", "mapped", "linear-max", "direct-max", "devtree-node"); | ||
583 | mutex_lock(&irq_domain_mutex); | ||
584 | list_for_each_entry(domain, &irq_domain_list, link) { | ||
585 | int count = 0; | ||
586 | radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0) | ||
587 | count++; | ||
588 | seq_printf(m, "%c%-16s %6u %10u %10u %s\n", | ||
589 | domain == irq_default_domain ? '*' : ' ', domain->name, | ||
590 | domain->revmap_size + count, domain->revmap_size, | ||
591 | domain->revmap_direct_max_irq, | ||
592 | domain->of_node ? of_node_full_name(domain->of_node) : ""); | ||
593 | } | ||
594 | mutex_unlock(&irq_domain_mutex); | ||
595 | |||
596 | seq_printf(m, "%-5s %-7s %-15s %-*s %6s %-14s %s\n", "irq", "hwirq", | ||
797 | "chip name", (int)(2 * sizeof(void *) + 2), "chip data", | 597 | "chip name", (int)(2 * sizeof(void *) + 2), "chip data", |
798 | "domain name"); | 598 | "active", "type", "domain"); |
799 | 599 | ||
800 | for (i = 1; i < nr_irqs; i++) { | 600 | for (i = 1; i < nr_irqs; i++) { |
801 | desc = irq_to_desc(i); | 601 | desc = irq_to_desc(i); |
@@ -803,28 +603,28 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
803 | continue; | 603 | continue; |
804 | 604 | ||
805 | raw_spin_lock_irqsave(&desc->lock, flags); | 605 | raw_spin_lock_irqsave(&desc->lock, flags); |
606 | domain = desc->irq_data.domain; | ||
806 | 607 | ||
807 | if (desc->action && desc->action->handler) { | 608 | if (domain) { |
808 | struct irq_chip *chip; | 609 | struct irq_chip *chip; |
610 | int hwirq = desc->irq_data.hwirq; | ||
611 | bool direct; | ||
809 | 612 | ||
810 | seq_printf(m, "%5d ", i); | 613 | seq_printf(m, "%5d ", i); |
811 | seq_printf(m, "0x%05lx ", desc->irq_data.hwirq); | 614 | seq_printf(m, "0x%05x ", hwirq); |
812 | 615 | ||
813 | chip = irq_desc_get_chip(desc); | 616 | chip = irq_desc_get_chip(desc); |
814 | if (chip && chip->name) | 617 | seq_printf(m, "%-15s ", (chip && chip->name) ? chip->name : "none"); |
815 | p = chip->name; | ||
816 | else | ||
817 | p = none; | ||
818 | seq_printf(m, "%-15s ", p); | ||
819 | 618 | ||
820 | data = irq_desc_get_chip_data(desc); | 619 | data = irq_desc_get_chip_data(desc); |
821 | seq_printf(m, data ? "0x%p " : " %p ", data); | 620 | seq_printf(m, data ? "0x%p " : " %p ", data); |
822 | 621 | ||
823 | if (desc->irq_data.domain) | 622 | seq_printf(m, " %c ", (desc->action && desc->action->handler) ? '*' : ' '); |
824 | p = of_node_full_name(desc->irq_data.domain->of_node); | 623 | direct = (i == hwirq) && (i < domain->revmap_direct_max_irq); |
825 | else | 624 | seq_printf(m, "%6s%-8s ", |
826 | p = none; | 625 | (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX", |
827 | seq_printf(m, "%s\n", p); | 626 | direct ? "(DIRECT)" : ""); |
627 | seq_printf(m, "%s\n", desc->irq_data.domain->name); | ||
828 | } | 628 | } |
829 | 629 | ||
830 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 630 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
@@ -921,18 +721,3 @@ const struct irq_domain_ops irq_domain_simple_ops = { | |||
921 | .xlate = irq_domain_xlate_onetwocell, | 721 | .xlate = irq_domain_xlate_onetwocell, |
922 | }; | 722 | }; |
923 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); | 723 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); |
924 | |||
925 | #ifdef CONFIG_OF_IRQ | ||
926 | void irq_domain_generate_simple(const struct of_device_id *match, | ||
927 | u64 phys_base, unsigned int irq_start) | ||
928 | { | ||
929 | struct device_node *node; | ||
930 | pr_debug("looking for phys_base=%llx, irq_start=%i\n", | ||
931 | (unsigned long long) phys_base, (int) irq_start); | ||
932 | node = of_find_matching_node_by_address(NULL, match, phys_base); | ||
933 | if (node) | ||
934 | irq_domain_add_legacy(node, 32, irq_start, 0, | ||
935 | &irq_domain_simple_ops, NULL); | ||
936 | } | ||
937 | EXPORT_SYMBOL_GPL(irq_domain_generate_simple); | ||
938 | #endif | ||
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 19ed5c425c3b..36f6ee181b0c 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -462,6 +462,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
462 | } else { | 462 | } else { |
463 | seq_printf(p, " %8s", "None"); | 463 | seq_printf(p, " %8s", "None"); |
464 | } | 464 | } |
465 | if (desc->irq_data.domain) | ||
466 | seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq); | ||
465 | #ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL | 467 | #ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL |
466 | seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge"); | 468 | seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge"); |
467 | #endif | 469 | #endif |
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 42670e9b44e0..c7f31aa272f7 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -51,59 +51,28 @@ static int check_clock(const clockid_t which_clock) | |||
51 | return error; | 51 | return error; |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline union cpu_time_count | 54 | static inline unsigned long long |
55 | timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) | 55 | timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) |
56 | { | 56 | { |
57 | union cpu_time_count ret; | 57 | unsigned long long ret; |
58 | ret.sched = 0; /* high half always zero when .cpu used */ | 58 | |
59 | ret = 0; /* high half always zero when .cpu used */ | ||
59 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | 60 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { |
60 | ret.sched = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec; | 61 | ret = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec; |
61 | } else { | 62 | } else { |
62 | ret.cpu = timespec_to_cputime(tp); | 63 | ret = cputime_to_expires(timespec_to_cputime(tp)); |
63 | } | 64 | } |
64 | return ret; | 65 | return ret; |
65 | } | 66 | } |
66 | 67 | ||
67 | static void sample_to_timespec(const clockid_t which_clock, | 68 | static void sample_to_timespec(const clockid_t which_clock, |
68 | union cpu_time_count cpu, | 69 | unsigned long long expires, |
69 | struct timespec *tp) | 70 | struct timespec *tp) |
70 | { | 71 | { |
71 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) | 72 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) |
72 | *tp = ns_to_timespec(cpu.sched); | 73 | *tp = ns_to_timespec(expires); |
73 | else | 74 | else |
74 | cputime_to_timespec(cpu.cpu, tp); | 75 | cputime_to_timespec((__force cputime_t)expires, tp); |
75 | } | ||
76 | |||
77 | static inline int cpu_time_before(const clockid_t which_clock, | ||
78 | union cpu_time_count now, | ||
79 | union cpu_time_count then) | ||
80 | { | ||
81 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | ||
82 | return now.sched < then.sched; | ||
83 | } else { | ||
84 | return now.cpu < then.cpu; | ||
85 | } | ||
86 | } | ||
87 | static inline void cpu_time_add(const clockid_t which_clock, | ||
88 | union cpu_time_count *acc, | ||
89 | union cpu_time_count val) | ||
90 | { | ||
91 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | ||
92 | acc->sched += val.sched; | ||
93 | } else { | ||
94 | acc->cpu += val.cpu; | ||
95 | } | ||
96 | } | ||
97 | static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock, | ||
98 | union cpu_time_count a, | ||
99 | union cpu_time_count b) | ||
100 | { | ||
101 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | ||
102 | a.sched -= b.sched; | ||
103 | } else { | ||
104 | a.cpu -= b.cpu; | ||
105 | } | ||
106 | return a; | ||
107 | } | 76 | } |
108 | 77 | ||
109 | /* | 78 | /* |
@@ -111,47 +80,31 @@ static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock, | |||
111 | * given the current clock sample. | 80 | * given the current clock sample. |
112 | */ | 81 | */ |
113 | static void bump_cpu_timer(struct k_itimer *timer, | 82 | static void bump_cpu_timer(struct k_itimer *timer, |
114 | union cpu_time_count now) | 83 | unsigned long long now) |
115 | { | 84 | { |
116 | int i; | 85 | int i; |
86 | unsigned long long delta, incr; | ||
117 | 87 | ||
118 | if (timer->it.cpu.incr.sched == 0) | 88 | if (timer->it.cpu.incr == 0) |
119 | return; | 89 | return; |
120 | 90 | ||
121 | if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) { | 91 | if (now < timer->it.cpu.expires) |
122 | unsigned long long delta, incr; | 92 | return; |
123 | 93 | ||
124 | if (now.sched < timer->it.cpu.expires.sched) | 94 | incr = timer->it.cpu.incr; |
125 | return; | 95 | delta = now + incr - timer->it.cpu.expires; |
126 | incr = timer->it.cpu.incr.sched; | ||
127 | delta = now.sched + incr - timer->it.cpu.expires.sched; | ||
128 | /* Don't use (incr*2 < delta), incr*2 might overflow. */ | ||
129 | for (i = 0; incr < delta - incr; i++) | ||
130 | incr = incr << 1; | ||
131 | for (; i >= 0; incr >>= 1, i--) { | ||
132 | if (delta < incr) | ||
133 | continue; | ||
134 | timer->it.cpu.expires.sched += incr; | ||
135 | timer->it_overrun += 1 << i; | ||
136 | delta -= incr; | ||
137 | } | ||
138 | } else { | ||
139 | cputime_t delta, incr; | ||
140 | 96 | ||
141 | if (now.cpu < timer->it.cpu.expires.cpu) | 97 | /* Don't use (incr*2 < delta), incr*2 might overflow. */ |
142 | return; | 98 | for (i = 0; incr < delta - incr; i++) |
143 | incr = timer->it.cpu.incr.cpu; | 99 | incr = incr << 1; |
144 | delta = now.cpu + incr - timer->it.cpu.expires.cpu; | 100 | |
145 | /* Don't use (incr*2 < delta), incr*2 might overflow. */ | 101 | for (; i >= 0; incr >>= 1, i--) { |
146 | for (i = 0; incr < delta - incr; i++) | 102 | if (delta < incr) |
147 | incr += incr; | 103 | continue; |
148 | for (; i >= 0; incr = incr >> 1, i--) { | 104 | |
149 | if (delta < incr) | 105 | timer->it.cpu.expires += incr; |
150 | continue; | 106 | timer->it_overrun += 1 << i; |
151 | timer->it.cpu.expires.cpu += incr; | 107 | delta -= incr; |
152 | timer->it_overrun += 1 << i; | ||
153 | delta -= incr; | ||
154 | } | ||
155 | } | 108 | } |
156 | } | 109 | } |
157 | 110 | ||
@@ -170,21 +123,21 @@ static inline int task_cputime_zero(const struct task_cputime *cputime) | |||
170 | return 0; | 123 | return 0; |
171 | } | 124 | } |
172 | 125 | ||
173 | static inline cputime_t prof_ticks(struct task_struct *p) | 126 | static inline unsigned long long prof_ticks(struct task_struct *p) |
174 | { | 127 | { |
175 | cputime_t utime, stime; | 128 | cputime_t utime, stime; |
176 | 129 | ||
177 | task_cputime(p, &utime, &stime); | 130 | task_cputime(p, &utime, &stime); |
178 | 131 | ||
179 | return utime + stime; | 132 | return cputime_to_expires(utime + stime); |
180 | } | 133 | } |
181 | static inline cputime_t virt_ticks(struct task_struct *p) | 134 | static inline unsigned long long virt_ticks(struct task_struct *p) |
182 | { | 135 | { |
183 | cputime_t utime; | 136 | cputime_t utime; |
184 | 137 | ||
185 | task_cputime(p, &utime, NULL); | 138 | task_cputime(p, &utime, NULL); |
186 | 139 | ||
187 | return utime; | 140 | return cputime_to_expires(utime); |
188 | } | 141 | } |
189 | 142 | ||
190 | static int | 143 | static int |
@@ -225,19 +178,19 @@ posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) | |||
225 | * Sample a per-thread clock for the given task. | 178 | * Sample a per-thread clock for the given task. |
226 | */ | 179 | */ |
227 | static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p, | 180 | static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p, |
228 | union cpu_time_count *cpu) | 181 | unsigned long long *sample) |
229 | { | 182 | { |
230 | switch (CPUCLOCK_WHICH(which_clock)) { | 183 | switch (CPUCLOCK_WHICH(which_clock)) { |
231 | default: | 184 | default: |
232 | return -EINVAL; | 185 | return -EINVAL; |
233 | case CPUCLOCK_PROF: | 186 | case CPUCLOCK_PROF: |
234 | cpu->cpu = prof_ticks(p); | 187 | *sample = prof_ticks(p); |
235 | break; | 188 | break; |
236 | case CPUCLOCK_VIRT: | 189 | case CPUCLOCK_VIRT: |
237 | cpu->cpu = virt_ticks(p); | 190 | *sample = virt_ticks(p); |
238 | break; | 191 | break; |
239 | case CPUCLOCK_SCHED: | 192 | case CPUCLOCK_SCHED: |
240 | cpu->sched = task_sched_runtime(p); | 193 | *sample = task_sched_runtime(p); |
241 | break; | 194 | break; |
242 | } | 195 | } |
243 | return 0; | 196 | return 0; |
@@ -284,7 +237,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times) | |||
284 | */ | 237 | */ |
285 | static int cpu_clock_sample_group(const clockid_t which_clock, | 238 | static int cpu_clock_sample_group(const clockid_t which_clock, |
286 | struct task_struct *p, | 239 | struct task_struct *p, |
287 | union cpu_time_count *cpu) | 240 | unsigned long long *sample) |
288 | { | 241 | { |
289 | struct task_cputime cputime; | 242 | struct task_cputime cputime; |
290 | 243 | ||
@@ -293,15 +246,15 @@ static int cpu_clock_sample_group(const clockid_t which_clock, | |||
293 | return -EINVAL; | 246 | return -EINVAL; |
294 | case CPUCLOCK_PROF: | 247 | case CPUCLOCK_PROF: |
295 | thread_group_cputime(p, &cputime); | 248 | thread_group_cputime(p, &cputime); |
296 | cpu->cpu = cputime.utime + cputime.stime; | 249 | *sample = cputime_to_expires(cputime.utime + cputime.stime); |
297 | break; | 250 | break; |
298 | case CPUCLOCK_VIRT: | 251 | case CPUCLOCK_VIRT: |
299 | thread_group_cputime(p, &cputime); | 252 | thread_group_cputime(p, &cputime); |
300 | cpu->cpu = cputime.utime; | 253 | *sample = cputime_to_expires(cputime.utime); |
301 | break; | 254 | break; |
302 | case CPUCLOCK_SCHED: | 255 | case CPUCLOCK_SCHED: |
303 | thread_group_cputime(p, &cputime); | 256 | thread_group_cputime(p, &cputime); |
304 | cpu->sched = cputime.sum_exec_runtime; | 257 | *sample = cputime.sum_exec_runtime; |
305 | break; | 258 | break; |
306 | } | 259 | } |
307 | return 0; | 260 | return 0; |
@@ -312,7 +265,7 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | |||
312 | { | 265 | { |
313 | const pid_t pid = CPUCLOCK_PID(which_clock); | 266 | const pid_t pid = CPUCLOCK_PID(which_clock); |
314 | int error = -EINVAL; | 267 | int error = -EINVAL; |
315 | union cpu_time_count rtn; | 268 | unsigned long long rtn; |
316 | 269 | ||
317 | if (pid == 0) { | 270 | if (pid == 0) { |
318 | /* | 271 | /* |
@@ -446,6 +399,15 @@ static int posix_cpu_timer_del(struct k_itimer *timer) | |||
446 | return ret; | 399 | return ret; |
447 | } | 400 | } |
448 | 401 | ||
402 | static void cleanup_timers_list(struct list_head *head, | ||
403 | unsigned long long curr) | ||
404 | { | ||
405 | struct cpu_timer_list *timer, *next; | ||
406 | |||
407 | list_for_each_entry_safe(timer, next, head, entry) | ||
408 | list_del_init(&timer->entry); | ||
409 | } | ||
410 | |||
449 | /* | 411 | /* |
450 | * Clean out CPU timers still ticking when a thread exited. The task | 412 | * Clean out CPU timers still ticking when a thread exited. The task |
451 | * pointer is cleared, and the expiry time is replaced with the residual | 413 | * pointer is cleared, and the expiry time is replaced with the residual |
@@ -456,37 +418,12 @@ static void cleanup_timers(struct list_head *head, | |||
456 | cputime_t utime, cputime_t stime, | 418 | cputime_t utime, cputime_t stime, |
457 | unsigned long long sum_exec_runtime) | 419 | unsigned long long sum_exec_runtime) |
458 | { | 420 | { |
459 | struct cpu_timer_list *timer, *next; | ||
460 | cputime_t ptime = utime + stime; | ||
461 | |||
462 | list_for_each_entry_safe(timer, next, head, entry) { | ||
463 | list_del_init(&timer->entry); | ||
464 | if (timer->expires.cpu < ptime) { | ||
465 | timer->expires.cpu = 0; | ||
466 | } else { | ||
467 | timer->expires.cpu -= ptime; | ||
468 | } | ||
469 | } | ||
470 | 421 | ||
471 | ++head; | 422 | cputime_t ptime = utime + stime; |
472 | list_for_each_entry_safe(timer, next, head, entry) { | ||
473 | list_del_init(&timer->entry); | ||
474 | if (timer->expires.cpu < utime) { | ||
475 | timer->expires.cpu = 0; | ||
476 | } else { | ||
477 | timer->expires.cpu -= utime; | ||
478 | } | ||
479 | } | ||
480 | 423 | ||
481 | ++head; | 424 | cleanup_timers_list(head, cputime_to_expires(ptime)); |
482 | list_for_each_entry_safe(timer, next, head, entry) { | 425 | cleanup_timers_list(++head, cputime_to_expires(utime)); |
483 | list_del_init(&timer->entry); | 426 | cleanup_timers_list(++head, sum_exec_runtime); |
484 | if (timer->expires.sched < sum_exec_runtime) { | ||
485 | timer->expires.sched = 0; | ||
486 | } else { | ||
487 | timer->expires.sched -= sum_exec_runtime; | ||
488 | } | ||
489 | } | ||
490 | } | 427 | } |
491 | 428 | ||
492 | /* | 429 | /* |
@@ -516,17 +453,21 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk) | |||
516 | tsk->se.sum_exec_runtime + sig->sum_sched_runtime); | 453 | tsk->se.sum_exec_runtime + sig->sum_sched_runtime); |
517 | } | 454 | } |
518 | 455 | ||
519 | static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now) | 456 | static void clear_dead_task(struct k_itimer *itimer, unsigned long long now) |
520 | { | 457 | { |
458 | struct cpu_timer_list *timer = &itimer->it.cpu; | ||
459 | |||
521 | /* | 460 | /* |
522 | * That's all for this thread or process. | 461 | * That's all for this thread or process. |
523 | * We leave our residual in expires to be reported. | 462 | * We leave our residual in expires to be reported. |
524 | */ | 463 | */ |
525 | put_task_struct(timer->it.cpu.task); | 464 | put_task_struct(timer->task); |
526 | timer->it.cpu.task = NULL; | 465 | timer->task = NULL; |
527 | timer->it.cpu.expires = cpu_time_sub(timer->it_clock, | 466 | if (timer->expires < now) { |
528 | timer->it.cpu.expires, | 467 | timer->expires = 0; |
529 | now); | 468 | } else { |
469 | timer->expires -= now; | ||
470 | } | ||
530 | } | 471 | } |
531 | 472 | ||
532 | static inline int expires_gt(cputime_t expires, cputime_t new_exp) | 473 | static inline int expires_gt(cputime_t expires, cputime_t new_exp) |
@@ -558,14 +499,14 @@ static void arm_timer(struct k_itimer *timer) | |||
558 | 499 | ||
559 | listpos = head; | 500 | listpos = head; |
560 | list_for_each_entry(next, head, entry) { | 501 | list_for_each_entry(next, head, entry) { |
561 | if (cpu_time_before(timer->it_clock, nt->expires, next->expires)) | 502 | if (nt->expires < next->expires) |
562 | break; | 503 | break; |
563 | listpos = &next->entry; | 504 | listpos = &next->entry; |
564 | } | 505 | } |
565 | list_add(&nt->entry, listpos); | 506 | list_add(&nt->entry, listpos); |
566 | 507 | ||
567 | if (listpos == head) { | 508 | if (listpos == head) { |
568 | union cpu_time_count *exp = &nt->expires; | 509 | unsigned long long exp = nt->expires; |
569 | 510 | ||
570 | /* | 511 | /* |
571 | * We are the new earliest-expiring POSIX 1.b timer, hence | 512 | * We are the new earliest-expiring POSIX 1.b timer, hence |
@@ -576,17 +517,17 @@ static void arm_timer(struct k_itimer *timer) | |||
576 | 517 | ||
577 | switch (CPUCLOCK_WHICH(timer->it_clock)) { | 518 | switch (CPUCLOCK_WHICH(timer->it_clock)) { |
578 | case CPUCLOCK_PROF: | 519 | case CPUCLOCK_PROF: |
579 | if (expires_gt(cputime_expires->prof_exp, exp->cpu)) | 520 | if (expires_gt(cputime_expires->prof_exp, expires_to_cputime(exp))) |
580 | cputime_expires->prof_exp = exp->cpu; | 521 | cputime_expires->prof_exp = expires_to_cputime(exp); |
581 | break; | 522 | break; |
582 | case CPUCLOCK_VIRT: | 523 | case CPUCLOCK_VIRT: |
583 | if (expires_gt(cputime_expires->virt_exp, exp->cpu)) | 524 | if (expires_gt(cputime_expires->virt_exp, expires_to_cputime(exp))) |
584 | cputime_expires->virt_exp = exp->cpu; | 525 | cputime_expires->virt_exp = expires_to_cputime(exp); |
585 | break; | 526 | break; |
586 | case CPUCLOCK_SCHED: | 527 | case CPUCLOCK_SCHED: |
587 | if (cputime_expires->sched_exp == 0 || | 528 | if (cputime_expires->sched_exp == 0 || |
588 | cputime_expires->sched_exp > exp->sched) | 529 | cputime_expires->sched_exp > exp) |
589 | cputime_expires->sched_exp = exp->sched; | 530 | cputime_expires->sched_exp = exp; |
590 | break; | 531 | break; |
591 | } | 532 | } |
592 | } | 533 | } |
@@ -601,20 +542,20 @@ static void cpu_timer_fire(struct k_itimer *timer) | |||
601 | /* | 542 | /* |
602 | * User don't want any signal. | 543 | * User don't want any signal. |
603 | */ | 544 | */ |
604 | timer->it.cpu.expires.sched = 0; | 545 | timer->it.cpu.expires = 0; |
605 | } else if (unlikely(timer->sigq == NULL)) { | 546 | } else if (unlikely(timer->sigq == NULL)) { |
606 | /* | 547 | /* |
607 | * This a special case for clock_nanosleep, | 548 | * This a special case for clock_nanosleep, |
608 | * not a normal timer from sys_timer_create. | 549 | * not a normal timer from sys_timer_create. |
609 | */ | 550 | */ |
610 | wake_up_process(timer->it_process); | 551 | wake_up_process(timer->it_process); |
611 | timer->it.cpu.expires.sched = 0; | 552 | timer->it.cpu.expires = 0; |
612 | } else if (timer->it.cpu.incr.sched == 0) { | 553 | } else if (timer->it.cpu.incr == 0) { |
613 | /* | 554 | /* |
614 | * One-shot timer. Clear it as soon as it's fired. | 555 | * One-shot timer. Clear it as soon as it's fired. |
615 | */ | 556 | */ |
616 | posix_timer_event(timer, 0); | 557 | posix_timer_event(timer, 0); |
617 | timer->it.cpu.expires.sched = 0; | 558 | timer->it.cpu.expires = 0; |
618 | } else if (posix_timer_event(timer, ++timer->it_requeue_pending)) { | 559 | } else if (posix_timer_event(timer, ++timer->it_requeue_pending)) { |
619 | /* | 560 | /* |
620 | * The signal did not get queued because the signal | 561 | * The signal did not get queued because the signal |
@@ -632,7 +573,7 @@ static void cpu_timer_fire(struct k_itimer *timer) | |||
632 | */ | 573 | */ |
633 | static int cpu_timer_sample_group(const clockid_t which_clock, | 574 | static int cpu_timer_sample_group(const clockid_t which_clock, |
634 | struct task_struct *p, | 575 | struct task_struct *p, |
635 | union cpu_time_count *cpu) | 576 | unsigned long long *sample) |
636 | { | 577 | { |
637 | struct task_cputime cputime; | 578 | struct task_cputime cputime; |
638 | 579 | ||
@@ -641,13 +582,13 @@ static int cpu_timer_sample_group(const clockid_t which_clock, | |||
641 | default: | 582 | default: |
642 | return -EINVAL; | 583 | return -EINVAL; |
643 | case CPUCLOCK_PROF: | 584 | case CPUCLOCK_PROF: |
644 | cpu->cpu = cputime.utime + cputime.stime; | 585 | *sample = cputime_to_expires(cputime.utime + cputime.stime); |
645 | break; | 586 | break; |
646 | case CPUCLOCK_VIRT: | 587 | case CPUCLOCK_VIRT: |
647 | cpu->cpu = cputime.utime; | 588 | *sample = cputime_to_expires(cputime.utime); |
648 | break; | 589 | break; |
649 | case CPUCLOCK_SCHED: | 590 | case CPUCLOCK_SCHED: |
650 | cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p); | 591 | *sample = cputime.sum_exec_runtime + task_delta_exec(p); |
651 | break; | 592 | break; |
652 | } | 593 | } |
653 | return 0; | 594 | return 0; |
@@ -694,7 +635,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
694 | struct itimerspec *new, struct itimerspec *old) | 635 | struct itimerspec *new, struct itimerspec *old) |
695 | { | 636 | { |
696 | struct task_struct *p = timer->it.cpu.task; | 637 | struct task_struct *p = timer->it.cpu.task; |
697 | union cpu_time_count old_expires, new_expires, old_incr, val; | 638 | unsigned long long old_expires, new_expires, old_incr, val; |
698 | int ret; | 639 | int ret; |
699 | 640 | ||
700 | if (unlikely(p == NULL)) { | 641 | if (unlikely(p == NULL)) { |
@@ -749,7 +690,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
749 | } | 690 | } |
750 | 691 | ||
751 | if (old) { | 692 | if (old) { |
752 | if (old_expires.sched == 0) { | 693 | if (old_expires == 0) { |
753 | old->it_value.tv_sec = 0; | 694 | old->it_value.tv_sec = 0; |
754 | old->it_value.tv_nsec = 0; | 695 | old->it_value.tv_nsec = 0; |
755 | } else { | 696 | } else { |
@@ -764,11 +705,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
764 | * new setting. | 705 | * new setting. |
765 | */ | 706 | */ |
766 | bump_cpu_timer(timer, val); | 707 | bump_cpu_timer(timer, val); |
767 | if (cpu_time_before(timer->it_clock, val, | 708 | if (val < timer->it.cpu.expires) { |
768 | timer->it.cpu.expires)) { | 709 | old_expires = timer->it.cpu.expires - val; |
769 | old_expires = cpu_time_sub( | ||
770 | timer->it_clock, | ||
771 | timer->it.cpu.expires, val); | ||
772 | sample_to_timespec(timer->it_clock, | 710 | sample_to_timespec(timer->it_clock, |
773 | old_expires, | 711 | old_expires, |
774 | &old->it_value); | 712 | &old->it_value); |
@@ -791,8 +729,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
791 | goto out; | 729 | goto out; |
792 | } | 730 | } |
793 | 731 | ||
794 | if (new_expires.sched != 0 && !(flags & TIMER_ABSTIME)) { | 732 | if (new_expires != 0 && !(flags & TIMER_ABSTIME)) { |
795 | cpu_time_add(timer->it_clock, &new_expires, val); | 733 | new_expires += val; |
796 | } | 734 | } |
797 | 735 | ||
798 | /* | 736 | /* |
@@ -801,8 +739,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
801 | * arm the timer (we'll just fake it for timer_gettime). | 739 | * arm the timer (we'll just fake it for timer_gettime). |
802 | */ | 740 | */ |
803 | timer->it.cpu.expires = new_expires; | 741 | timer->it.cpu.expires = new_expires; |
804 | if (new_expires.sched != 0 && | 742 | if (new_expires != 0 && val < new_expires) { |
805 | cpu_time_before(timer->it_clock, val, new_expires)) { | ||
806 | arm_timer(timer); | 743 | arm_timer(timer); |
807 | } | 744 | } |
808 | 745 | ||
@@ -826,8 +763,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
826 | timer->it_overrun_last = 0; | 763 | timer->it_overrun_last = 0; |
827 | timer->it_overrun = -1; | 764 | timer->it_overrun = -1; |
828 | 765 | ||
829 | if (new_expires.sched != 0 && | 766 | if (new_expires != 0 && !(val < new_expires)) { |
830 | !cpu_time_before(timer->it_clock, val, new_expires)) { | ||
831 | /* | 767 | /* |
832 | * The designated time already passed, so we notify | 768 | * The designated time already passed, so we notify |
833 | * immediately, even if the thread never runs to | 769 | * immediately, even if the thread never runs to |
@@ -849,7 +785,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
849 | 785 | ||
850 | static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | 786 | static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) |
851 | { | 787 | { |
852 | union cpu_time_count now; | 788 | unsigned long long now; |
853 | struct task_struct *p = timer->it.cpu.task; | 789 | struct task_struct *p = timer->it.cpu.task; |
854 | int clear_dead; | 790 | int clear_dead; |
855 | 791 | ||
@@ -859,7 +795,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
859 | sample_to_timespec(timer->it_clock, | 795 | sample_to_timespec(timer->it_clock, |
860 | timer->it.cpu.incr, &itp->it_interval); | 796 | timer->it.cpu.incr, &itp->it_interval); |
861 | 797 | ||
862 | if (timer->it.cpu.expires.sched == 0) { /* Timer not armed at all. */ | 798 | if (timer->it.cpu.expires == 0) { /* Timer not armed at all. */ |
863 | itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; | 799 | itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; |
864 | return; | 800 | return; |
865 | } | 801 | } |
@@ -891,7 +827,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
891 | */ | 827 | */ |
892 | put_task_struct(p); | 828 | put_task_struct(p); |
893 | timer->it.cpu.task = NULL; | 829 | timer->it.cpu.task = NULL; |
894 | timer->it.cpu.expires.sched = 0; | 830 | timer->it.cpu.expires = 0; |
895 | read_unlock(&tasklist_lock); | 831 | read_unlock(&tasklist_lock); |
896 | goto dead; | 832 | goto dead; |
897 | } else { | 833 | } else { |
@@ -912,10 +848,9 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
912 | goto dead; | 848 | goto dead; |
913 | } | 849 | } |
914 | 850 | ||
915 | if (cpu_time_before(timer->it_clock, now, timer->it.cpu.expires)) { | 851 | if (now < timer->it.cpu.expires) { |
916 | sample_to_timespec(timer->it_clock, | 852 | sample_to_timespec(timer->it_clock, |
917 | cpu_time_sub(timer->it_clock, | 853 | timer->it.cpu.expires - now, |
918 | timer->it.cpu.expires, now), | ||
919 | &itp->it_value); | 854 | &itp->it_value); |
920 | } else { | 855 | } else { |
921 | /* | 856 | /* |
@@ -927,6 +862,28 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
927 | } | 862 | } |
928 | } | 863 | } |
929 | 864 | ||
865 | static unsigned long long | ||
866 | check_timers_list(struct list_head *timers, | ||
867 | struct list_head *firing, | ||
868 | unsigned long long curr) | ||
869 | { | ||
870 | int maxfire = 20; | ||
871 | |||
872 | while (!list_empty(timers)) { | ||
873 | struct cpu_timer_list *t; | ||
874 | |||
875 | t = list_first_entry(timers, struct cpu_timer_list, entry); | ||
876 | |||
877 | if (!--maxfire || curr < t->expires) | ||
878 | return t->expires; | ||
879 | |||
880 | t->firing = 1; | ||
881 | list_move_tail(&t->entry, firing); | ||
882 | } | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
930 | /* | 887 | /* |
931 | * Check for any per-thread CPU timers that have fired and move them off | 888 | * Check for any per-thread CPU timers that have fired and move them off |
932 | * the tsk->cpu_timers[N] list onto the firing list. Here we update the | 889 | * the tsk->cpu_timers[N] list onto the firing list. Here we update the |
@@ -935,54 +892,20 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
935 | static void check_thread_timers(struct task_struct *tsk, | 892 | static void check_thread_timers(struct task_struct *tsk, |
936 | struct list_head *firing) | 893 | struct list_head *firing) |
937 | { | 894 | { |
938 | int maxfire; | ||
939 | struct list_head *timers = tsk->cpu_timers; | 895 | struct list_head *timers = tsk->cpu_timers; |
940 | struct signal_struct *const sig = tsk->signal; | 896 | struct signal_struct *const sig = tsk->signal; |
897 | struct task_cputime *tsk_expires = &tsk->cputime_expires; | ||
898 | unsigned long long expires; | ||
941 | unsigned long soft; | 899 | unsigned long soft; |
942 | 900 | ||
943 | maxfire = 20; | 901 | expires = check_timers_list(timers, firing, prof_ticks(tsk)); |
944 | tsk->cputime_expires.prof_exp = 0; | 902 | tsk_expires->prof_exp = expires_to_cputime(expires); |
945 | while (!list_empty(timers)) { | ||
946 | struct cpu_timer_list *t = list_first_entry(timers, | ||
947 | struct cpu_timer_list, | ||
948 | entry); | ||
949 | if (!--maxfire || prof_ticks(tsk) < t->expires.cpu) { | ||
950 | tsk->cputime_expires.prof_exp = t->expires.cpu; | ||
951 | break; | ||
952 | } | ||
953 | t->firing = 1; | ||
954 | list_move_tail(&t->entry, firing); | ||
955 | } | ||
956 | 903 | ||
957 | ++timers; | 904 | expires = check_timers_list(++timers, firing, virt_ticks(tsk)); |
958 | maxfire = 20; | 905 | tsk_expires->virt_exp = expires_to_cputime(expires); |
959 | tsk->cputime_expires.virt_exp = 0; | ||
960 | while (!list_empty(timers)) { | ||
961 | struct cpu_timer_list *t = list_first_entry(timers, | ||
962 | struct cpu_timer_list, | ||
963 | entry); | ||
964 | if (!--maxfire || virt_ticks(tsk) < t->expires.cpu) { | ||
965 | tsk->cputime_expires.virt_exp = t->expires.cpu; | ||
966 | break; | ||
967 | } | ||
968 | t->firing = 1; | ||
969 | list_move_tail(&t->entry, firing); | ||
970 | } | ||
971 | 906 | ||
972 | ++timers; | 907 | tsk_expires->sched_exp = check_timers_list(++timers, firing, |
973 | maxfire = 20; | 908 | tsk->se.sum_exec_runtime); |
974 | tsk->cputime_expires.sched_exp = 0; | ||
975 | while (!list_empty(timers)) { | ||
976 | struct cpu_timer_list *t = list_first_entry(timers, | ||
977 | struct cpu_timer_list, | ||
978 | entry); | ||
979 | if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) { | ||
980 | tsk->cputime_expires.sched_exp = t->expires.sched; | ||
981 | break; | ||
982 | } | ||
983 | t->firing = 1; | ||
984 | list_move_tail(&t->entry, firing); | ||
985 | } | ||
986 | 909 | ||
987 | /* | 910 | /* |
988 | * Check for the special case thread timers. | 911 | * Check for the special case thread timers. |
@@ -1030,7 +953,8 @@ static void stop_process_timers(struct signal_struct *sig) | |||
1030 | static u32 onecputick; | 953 | static u32 onecputick; |
1031 | 954 | ||
1032 | static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, | 955 | static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, |
1033 | cputime_t *expires, cputime_t cur_time, int signo) | 956 | unsigned long long *expires, |
957 | unsigned long long cur_time, int signo) | ||
1034 | { | 958 | { |
1035 | if (!it->expires) | 959 | if (!it->expires) |
1036 | return; | 960 | return; |
@@ -1066,9 +990,8 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, | |||
1066 | static void check_process_timers(struct task_struct *tsk, | 990 | static void check_process_timers(struct task_struct *tsk, |
1067 | struct list_head *firing) | 991 | struct list_head *firing) |
1068 | { | 992 | { |
1069 | int maxfire; | ||
1070 | struct signal_struct *const sig = tsk->signal; | 993 | struct signal_struct *const sig = tsk->signal; |
1071 | cputime_t utime, ptime, virt_expires, prof_expires; | 994 | unsigned long long utime, ptime, virt_expires, prof_expires; |
1072 | unsigned long long sum_sched_runtime, sched_expires; | 995 | unsigned long long sum_sched_runtime, sched_expires; |
1073 | struct list_head *timers = sig->cpu_timers; | 996 | struct list_head *timers = sig->cpu_timers; |
1074 | struct task_cputime cputime; | 997 | struct task_cputime cputime; |
@@ -1078,52 +1001,13 @@ static void check_process_timers(struct task_struct *tsk, | |||
1078 | * Collect the current process totals. | 1001 | * Collect the current process totals. |
1079 | */ | 1002 | */ |
1080 | thread_group_cputimer(tsk, &cputime); | 1003 | thread_group_cputimer(tsk, &cputime); |
1081 | utime = cputime.utime; | 1004 | utime = cputime_to_expires(cputime.utime); |
1082 | ptime = utime + cputime.stime; | 1005 | ptime = utime + cputime_to_expires(cputime.stime); |
1083 | sum_sched_runtime = cputime.sum_exec_runtime; | 1006 | sum_sched_runtime = cputime.sum_exec_runtime; |
1084 | maxfire = 20; | ||
1085 | prof_expires = 0; | ||
1086 | while (!list_empty(timers)) { | ||
1087 | struct cpu_timer_list *tl = list_first_entry(timers, | ||
1088 | struct cpu_timer_list, | ||
1089 | entry); | ||
1090 | if (!--maxfire || ptime < tl->expires.cpu) { | ||
1091 | prof_expires = tl->expires.cpu; | ||
1092 | break; | ||
1093 | } | ||
1094 | tl->firing = 1; | ||
1095 | list_move_tail(&tl->entry, firing); | ||
1096 | } | ||
1097 | 1007 | ||
1098 | ++timers; | 1008 | prof_expires = check_timers_list(timers, firing, ptime); |
1099 | maxfire = 20; | 1009 | virt_expires = check_timers_list(++timers, firing, utime); |
1100 | virt_expires = 0; | 1010 | sched_expires = check_timers_list(++timers, firing, sum_sched_runtime); |
1101 | while (!list_empty(timers)) { | ||
1102 | struct cpu_timer_list *tl = list_first_entry(timers, | ||
1103 | struct cpu_timer_list, | ||
1104 | entry); | ||
1105 | if (!--maxfire || utime < tl->expires.cpu) { | ||
1106 | virt_expires = tl->expires.cpu; | ||
1107 | break; | ||
1108 | } | ||
1109 | tl->firing = 1; | ||
1110 | list_move_tail(&tl->entry, firing); | ||
1111 | } | ||
1112 | |||
1113 | ++timers; | ||
1114 | maxfire = 20; | ||
1115 | sched_expires = 0; | ||
1116 | while (!list_empty(timers)) { | ||
1117 | struct cpu_timer_list *tl = list_first_entry(timers, | ||
1118 | struct cpu_timer_list, | ||
1119 | entry); | ||
1120 | if (!--maxfire || sum_sched_runtime < tl->expires.sched) { | ||
1121 | sched_expires = tl->expires.sched; | ||
1122 | break; | ||
1123 | } | ||
1124 | tl->firing = 1; | ||
1125 | list_move_tail(&tl->entry, firing); | ||
1126 | } | ||
1127 | 1011 | ||
1128 | /* | 1012 | /* |
1129 | * Check for the special case process timers. | 1013 | * Check for the special case process timers. |
@@ -1162,8 +1046,8 @@ static void check_process_timers(struct task_struct *tsk, | |||
1162 | } | 1046 | } |
1163 | } | 1047 | } |
1164 | 1048 | ||
1165 | sig->cputime_expires.prof_exp = prof_expires; | 1049 | sig->cputime_expires.prof_exp = expires_to_cputime(prof_expires); |
1166 | sig->cputime_expires.virt_exp = virt_expires; | 1050 | sig->cputime_expires.virt_exp = expires_to_cputime(virt_expires); |
1167 | sig->cputime_expires.sched_exp = sched_expires; | 1051 | sig->cputime_expires.sched_exp = sched_expires; |
1168 | if (task_cputime_zero(&sig->cputime_expires)) | 1052 | if (task_cputime_zero(&sig->cputime_expires)) |
1169 | stop_process_timers(sig); | 1053 | stop_process_timers(sig); |
@@ -1176,7 +1060,7 @@ static void check_process_timers(struct task_struct *tsk, | |||
1176 | void posix_cpu_timer_schedule(struct k_itimer *timer) | 1060 | void posix_cpu_timer_schedule(struct k_itimer *timer) |
1177 | { | 1061 | { |
1178 | struct task_struct *p = timer->it.cpu.task; | 1062 | struct task_struct *p = timer->it.cpu.task; |
1179 | union cpu_time_count now; | 1063 | unsigned long long now; |
1180 | 1064 | ||
1181 | if (unlikely(p == NULL)) | 1065 | if (unlikely(p == NULL)) |
1182 | /* | 1066 | /* |
@@ -1205,7 +1089,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1205 | */ | 1089 | */ |
1206 | put_task_struct(p); | 1090 | put_task_struct(p); |
1207 | timer->it.cpu.task = p = NULL; | 1091 | timer->it.cpu.task = p = NULL; |
1208 | timer->it.cpu.expires.sched = 0; | 1092 | timer->it.cpu.expires = 0; |
1209 | goto out_unlock; | 1093 | goto out_unlock; |
1210 | } else if (unlikely(p->exit_state) && thread_group_empty(p)) { | 1094 | } else if (unlikely(p->exit_state) && thread_group_empty(p)) { |
1211 | /* | 1095 | /* |
@@ -1213,6 +1097,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1213 | * not yet reaped. Take this opportunity to | 1097 | * not yet reaped. Take this opportunity to |
1214 | * drop our task ref. | 1098 | * drop our task ref. |
1215 | */ | 1099 | */ |
1100 | cpu_timer_sample_group(timer->it_clock, p, &now); | ||
1216 | clear_dead_task(timer, now); | 1101 | clear_dead_task(timer, now); |
1217 | goto out_unlock; | 1102 | goto out_unlock; |
1218 | } | 1103 | } |
@@ -1387,7 +1272,7 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
1387 | void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | 1272 | void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, |
1388 | cputime_t *newval, cputime_t *oldval) | 1273 | cputime_t *newval, cputime_t *oldval) |
1389 | { | 1274 | { |
1390 | union cpu_time_count now; | 1275 | unsigned long long now; |
1391 | 1276 | ||
1392 | BUG_ON(clock_idx == CPUCLOCK_SCHED); | 1277 | BUG_ON(clock_idx == CPUCLOCK_SCHED); |
1393 | cpu_timer_sample_group(clock_idx, tsk, &now); | 1278 | cpu_timer_sample_group(clock_idx, tsk, &now); |
@@ -1399,17 +1284,17 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | |||
1399 | * it to be absolute. | 1284 | * it to be absolute. |
1400 | */ | 1285 | */ |
1401 | if (*oldval) { | 1286 | if (*oldval) { |
1402 | if (*oldval <= now.cpu) { | 1287 | if (*oldval <= now) { |
1403 | /* Just about to fire. */ | 1288 | /* Just about to fire. */ |
1404 | *oldval = cputime_one_jiffy; | 1289 | *oldval = cputime_one_jiffy; |
1405 | } else { | 1290 | } else { |
1406 | *oldval -= now.cpu; | 1291 | *oldval -= now; |
1407 | } | 1292 | } |
1408 | } | 1293 | } |
1409 | 1294 | ||
1410 | if (!*newval) | 1295 | if (!*newval) |
1411 | goto out; | 1296 | goto out; |
1412 | *newval += now.cpu; | 1297 | *newval += now; |
1413 | } | 1298 | } |
1414 | 1299 | ||
1415 | /* | 1300 | /* |
@@ -1459,7 +1344,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, | |||
1459 | } | 1344 | } |
1460 | 1345 | ||
1461 | while (!signal_pending(current)) { | 1346 | while (!signal_pending(current)) { |
1462 | if (timer.it.cpu.expires.sched == 0) { | 1347 | if (timer.it.cpu.expires == 0) { |
1463 | /* | 1348 | /* |
1464 | * Our timer fired and was reset, below | 1349 | * Our timer fired and was reset, below |
1465 | * deletion can not fail. | 1350 | * deletion can not fail. |
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h index 17d7065c3872..5aef494fc8b4 100644 --- a/kernel/sched/stats.h +++ b/kernel/sched/stats.h | |||
@@ -162,6 +162,39 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next) | |||
162 | */ | 162 | */ |
163 | 163 | ||
164 | /** | 164 | /** |
165 | * cputimer_running - return true if cputimer is running | ||
166 | * | ||
167 | * @tsk: Pointer to target task. | ||
168 | */ | ||
169 | static inline bool cputimer_running(struct task_struct *tsk) | ||
170 | |||
171 | { | ||
172 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | ||
173 | |||
174 | if (!cputimer->running) | ||
175 | return false; | ||
176 | |||
177 | /* | ||
178 | * After we flush the task's sum_exec_runtime to sig->sum_sched_runtime | ||
179 | * in __exit_signal(), we won't account to the signal struct further | ||
180 | * cputime consumed by that task, even though the task can still be | ||
181 | * ticking after __exit_signal(). | ||
182 | * | ||
183 | * In order to keep a consistent behaviour between thread group cputime | ||
184 | * and thread group cputimer accounting, lets also ignore the cputime | ||
185 | * elapsing after __exit_signal() in any thread group timer running. | ||
186 | * | ||
187 | * This makes sure that POSIX CPU clocks and timers are synchronized, so | ||
188 | * that a POSIX CPU timer won't expire while the corresponding POSIX CPU | ||
189 | * clock delta is behind the expiring timer value. | ||
190 | */ | ||
191 | if (unlikely(!tsk->sighand)) | ||
192 | return false; | ||
193 | |||
194 | return true; | ||
195 | } | ||
196 | |||
197 | /** | ||
165 | * account_group_user_time - Maintain utime for a thread group. | 198 | * account_group_user_time - Maintain utime for a thread group. |
166 | * | 199 | * |
167 | * @tsk: Pointer to task structure. | 200 | * @tsk: Pointer to task structure. |
@@ -176,7 +209,7 @@ static inline void account_group_user_time(struct task_struct *tsk, | |||
176 | { | 209 | { |
177 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | 210 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; |
178 | 211 | ||
179 | if (!cputimer->running) | 212 | if (!cputimer_running(tsk)) |
180 | return; | 213 | return; |
181 | 214 | ||
182 | raw_spin_lock(&cputimer->lock); | 215 | raw_spin_lock(&cputimer->lock); |
@@ -199,7 +232,7 @@ static inline void account_group_system_time(struct task_struct *tsk, | |||
199 | { | 232 | { |
200 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | 233 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; |
201 | 234 | ||
202 | if (!cputimer->running) | 235 | if (!cputimer_running(tsk)) |
203 | return; | 236 | return; |
204 | 237 | ||
205 | raw_spin_lock(&cputimer->lock); | 238 | raw_spin_lock(&cputimer->lock); |
@@ -222,7 +255,7 @@ static inline void account_group_exec_runtime(struct task_struct *tsk, | |||
222 | { | 255 | { |
223 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | 256 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; |
224 | 257 | ||
225 | if (!cputimer->running) | 258 | if (!cputimer_running(tsk)) |
226 | return; | 259 | return; |
227 | 260 | ||
228 | raw_spin_lock(&cputimer->lock); | 261 | raw_spin_lock(&cputimer->lock); |
diff --git a/kernel/time/Makefile b/kernel/time/Makefile index ff7d9d2ab504..9250130646f5 100644 --- a/kernel/time/Makefile +++ b/kernel/time/Makefile | |||
@@ -4,6 +4,8 @@ obj-y += timeconv.o posix-clock.o alarmtimer.o | |||
4 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o | 4 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o |
5 | obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o | 5 | obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o |
6 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o | 6 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o |
7 | obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o | ||
7 | obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o | 8 | obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o |
8 | obj-$(CONFIG_TICK_ONESHOT) += tick-sched.o | 9 | obj-$(CONFIG_TICK_ONESHOT) += tick-sched.o |
9 | obj-$(CONFIG_TIMER_STATS) += timer_stats.o | 10 | obj-$(CONFIG_TIMER_STATS) += timer_stats.o |
11 | obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o | ||
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index f11d83b12949..eec50fcef9e4 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -199,6 +199,13 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) | |||
199 | 199 | ||
200 | } | 200 | } |
201 | 201 | ||
202 | ktime_t alarm_expires_remaining(const struct alarm *alarm) | ||
203 | { | ||
204 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
205 | return ktime_sub(alarm->node.expires, base->gettime()); | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(alarm_expires_remaining); | ||
208 | |||
202 | #ifdef CONFIG_RTC_CLASS | 209 | #ifdef CONFIG_RTC_CLASS |
203 | /** | 210 | /** |
204 | * alarmtimer_suspend - Suspend time callback | 211 | * alarmtimer_suspend - Suspend time callback |
@@ -303,9 +310,10 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | |||
303 | alarm->type = type; | 310 | alarm->type = type; |
304 | alarm->state = ALARMTIMER_STATE_INACTIVE; | 311 | alarm->state = ALARMTIMER_STATE_INACTIVE; |
305 | } | 312 | } |
313 | EXPORT_SYMBOL_GPL(alarm_init); | ||
306 | 314 | ||
307 | /** | 315 | /** |
308 | * alarm_start - Sets an alarm to fire | 316 | * alarm_start - Sets an absolute alarm to fire |
309 | * @alarm: ptr to alarm to set | 317 | * @alarm: ptr to alarm to set |
310 | * @start: time to run the alarm | 318 | * @start: time to run the alarm |
311 | */ | 319 | */ |
@@ -323,6 +331,34 @@ int alarm_start(struct alarm *alarm, ktime_t start) | |||
323 | spin_unlock_irqrestore(&base->lock, flags); | 331 | spin_unlock_irqrestore(&base->lock, flags); |
324 | return ret; | 332 | return ret; |
325 | } | 333 | } |
334 | EXPORT_SYMBOL_GPL(alarm_start); | ||
335 | |||
336 | /** | ||
337 | * alarm_start_relative - Sets a relative alarm to fire | ||
338 | * @alarm: ptr to alarm to set | ||
339 | * @start: time relative to now to run the alarm | ||
340 | */ | ||
341 | int alarm_start_relative(struct alarm *alarm, ktime_t start) | ||
342 | { | ||
343 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
344 | |||
345 | start = ktime_add(start, base->gettime()); | ||
346 | return alarm_start(alarm, start); | ||
347 | } | ||
348 | EXPORT_SYMBOL_GPL(alarm_start_relative); | ||
349 | |||
350 | void alarm_restart(struct alarm *alarm) | ||
351 | { | ||
352 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
353 | unsigned long flags; | ||
354 | |||
355 | spin_lock_irqsave(&base->lock, flags); | ||
356 | hrtimer_set_expires(&alarm->timer, alarm->node.expires); | ||
357 | hrtimer_restart(&alarm->timer); | ||
358 | alarmtimer_enqueue(base, alarm); | ||
359 | spin_unlock_irqrestore(&base->lock, flags); | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(alarm_restart); | ||
326 | 362 | ||
327 | /** | 363 | /** |
328 | * alarm_try_to_cancel - Tries to cancel an alarm timer | 364 | * alarm_try_to_cancel - Tries to cancel an alarm timer |
@@ -344,6 +380,7 @@ int alarm_try_to_cancel(struct alarm *alarm) | |||
344 | spin_unlock_irqrestore(&base->lock, flags); | 380 | spin_unlock_irqrestore(&base->lock, flags); |
345 | return ret; | 381 | return ret; |
346 | } | 382 | } |
383 | EXPORT_SYMBOL_GPL(alarm_try_to_cancel); | ||
347 | 384 | ||
348 | 385 | ||
349 | /** | 386 | /** |
@@ -361,6 +398,7 @@ int alarm_cancel(struct alarm *alarm) | |||
361 | cpu_relax(); | 398 | cpu_relax(); |
362 | } | 399 | } |
363 | } | 400 | } |
401 | EXPORT_SYMBOL_GPL(alarm_cancel); | ||
364 | 402 | ||
365 | 403 | ||
366 | u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval) | 404 | u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval) |
@@ -393,8 +431,15 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval) | |||
393 | alarm->node.expires = ktime_add(alarm->node.expires, interval); | 431 | alarm->node.expires = ktime_add(alarm->node.expires, interval); |
394 | return overrun; | 432 | return overrun; |
395 | } | 433 | } |
434 | EXPORT_SYMBOL_GPL(alarm_forward); | ||
396 | 435 | ||
436 | u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) | ||
437 | { | ||
438 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
397 | 439 | ||
440 | return alarm_forward(alarm, base->gettime(), interval); | ||
441 | } | ||
442 | EXPORT_SYMBOL_GPL(alarm_forward_now); | ||
398 | 443 | ||
399 | 444 | ||
400 | /** | 445 | /** |
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index c6d6400ee137..38959c866789 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
@@ -15,20 +15,23 @@ | |||
15 | #include <linux/hrtimer.h> | 15 | #include <linux/hrtimer.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/notifier.h> | ||
19 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/device.h> | ||
20 | 20 | ||
21 | #include "tick-internal.h" | 21 | #include "tick-internal.h" |
22 | 22 | ||
23 | /* The registered clock event devices */ | 23 | /* The registered clock event devices */ |
24 | static LIST_HEAD(clockevent_devices); | 24 | static LIST_HEAD(clockevent_devices); |
25 | static LIST_HEAD(clockevents_released); | 25 | static LIST_HEAD(clockevents_released); |
26 | |||
27 | /* Notification for clock events */ | ||
28 | static RAW_NOTIFIER_HEAD(clockevents_chain); | ||
29 | |||
30 | /* Protection for the above */ | 26 | /* Protection for the above */ |
31 | static DEFINE_RAW_SPINLOCK(clockevents_lock); | 27 | static DEFINE_RAW_SPINLOCK(clockevents_lock); |
28 | /* Protection for unbind operations */ | ||
29 | static DEFINE_MUTEX(clockevents_mutex); | ||
30 | |||
31 | struct ce_unbind { | ||
32 | struct clock_event_device *ce; | ||
33 | int res; | ||
34 | }; | ||
32 | 35 | ||
33 | /** | 36 | /** |
34 | * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds | 37 | * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds |
@@ -232,47 +235,107 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, | |||
232 | return (rc && force) ? clockevents_program_min_delta(dev) : rc; | 235 | return (rc && force) ? clockevents_program_min_delta(dev) : rc; |
233 | } | 236 | } |
234 | 237 | ||
235 | /** | 238 | /* |
236 | * clockevents_register_notifier - register a clock events change listener | 239 | * Called after a notify add to make devices available which were |
240 | * released from the notifier call. | ||
237 | */ | 241 | */ |
238 | int clockevents_register_notifier(struct notifier_block *nb) | 242 | static void clockevents_notify_released(void) |
239 | { | 243 | { |
240 | unsigned long flags; | 244 | struct clock_event_device *dev; |
241 | int ret; | ||
242 | 245 | ||
243 | raw_spin_lock_irqsave(&clockevents_lock, flags); | 246 | while (!list_empty(&clockevents_released)) { |
244 | ret = raw_notifier_chain_register(&clockevents_chain, nb); | 247 | dev = list_entry(clockevents_released.next, |
245 | raw_spin_unlock_irqrestore(&clockevents_lock, flags); | 248 | struct clock_event_device, list); |
249 | list_del(&dev->list); | ||
250 | list_add(&dev->list, &clockevent_devices); | ||
251 | tick_check_new_device(dev); | ||
252 | } | ||
253 | } | ||
246 | 254 | ||
247 | return ret; | 255 | /* |
256 | * Try to install a replacement clock event device | ||
257 | */ | ||
258 | static int clockevents_replace(struct clock_event_device *ced) | ||
259 | { | ||
260 | struct clock_event_device *dev, *newdev = NULL; | ||
261 | |||
262 | list_for_each_entry(dev, &clockevent_devices, list) { | ||
263 | if (dev == ced || dev->mode != CLOCK_EVT_MODE_UNUSED) | ||
264 | continue; | ||
265 | |||
266 | if (!tick_check_replacement(newdev, dev)) | ||
267 | continue; | ||
268 | |||
269 | if (!try_module_get(dev->owner)) | ||
270 | continue; | ||
271 | |||
272 | if (newdev) | ||
273 | module_put(newdev->owner); | ||
274 | newdev = dev; | ||
275 | } | ||
276 | if (newdev) { | ||
277 | tick_install_replacement(newdev); | ||
278 | list_del_init(&ced->list); | ||
279 | } | ||
280 | return newdev ? 0 : -EBUSY; | ||
248 | } | 281 | } |
249 | 282 | ||
250 | /* | 283 | /* |
251 | * Notify about a clock event change. Called with clockevents_lock | 284 | * Called with clockevents_mutex and clockevents_lock held |
252 | * held. | ||
253 | */ | 285 | */ |
254 | static void clockevents_do_notify(unsigned long reason, void *dev) | 286 | static int __clockevents_try_unbind(struct clock_event_device *ced, int cpu) |
255 | { | 287 | { |
256 | raw_notifier_call_chain(&clockevents_chain, reason, dev); | 288 | /* Fast track. Device is unused */ |
289 | if (ced->mode == CLOCK_EVT_MODE_UNUSED) { | ||
290 | list_del_init(&ced->list); | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | return ced == per_cpu(tick_cpu_device, cpu).evtdev ? -EAGAIN : -EBUSY; | ||
257 | } | 295 | } |
258 | 296 | ||
259 | /* | 297 | /* |
260 | * Called after a notify add to make devices available which were | 298 | * SMP function call to unbind a device |
261 | * released from the notifier call. | ||
262 | */ | 299 | */ |
263 | static void clockevents_notify_released(void) | 300 | static void __clockevents_unbind(void *arg) |
264 | { | 301 | { |
265 | struct clock_event_device *dev; | 302 | struct ce_unbind *cu = arg; |
303 | int res; | ||
304 | |||
305 | raw_spin_lock(&clockevents_lock); | ||
306 | res = __clockevents_try_unbind(cu->ce, smp_processor_id()); | ||
307 | if (res == -EAGAIN) | ||
308 | res = clockevents_replace(cu->ce); | ||
309 | cu->res = res; | ||
310 | raw_spin_unlock(&clockevents_lock); | ||
311 | } | ||
266 | 312 | ||
267 | while (!list_empty(&clockevents_released)) { | 313 | /* |
268 | dev = list_entry(clockevents_released.next, | 314 | * Issues smp function call to unbind a per cpu device. Called with |
269 | struct clock_event_device, list); | 315 | * clockevents_mutex held. |
270 | list_del(&dev->list); | 316 | */ |
271 | list_add(&dev->list, &clockevent_devices); | 317 | static int clockevents_unbind(struct clock_event_device *ced, int cpu) |
272 | clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev); | 318 | { |
273 | } | 319 | struct ce_unbind cu = { .ce = ced, .res = -ENODEV }; |
320 | |||
321 | smp_call_function_single(cpu, __clockevents_unbind, &cu, 1); | ||
322 | return cu.res; | ||
274 | } | 323 | } |
275 | 324 | ||
325 | /* | ||
326 | * Unbind a clockevents device. | ||
327 | */ | ||
328 | int clockevents_unbind_device(struct clock_event_device *ced, int cpu) | ||
329 | { | ||
330 | int ret; | ||
331 | |||
332 | mutex_lock(&clockevents_mutex); | ||
333 | ret = clockevents_unbind(ced, cpu); | ||
334 | mutex_unlock(&clockevents_mutex); | ||
335 | return ret; | ||
336 | } | ||
337 | EXPORT_SYMBOL_GPL(clockevents_unbind); | ||
338 | |||
276 | /** | 339 | /** |
277 | * clockevents_register_device - register a clock event device | 340 | * clockevents_register_device - register a clock event device |
278 | * @dev: device to register | 341 | * @dev: device to register |
@@ -290,7 +353,7 @@ void clockevents_register_device(struct clock_event_device *dev) | |||
290 | raw_spin_lock_irqsave(&clockevents_lock, flags); | 353 | raw_spin_lock_irqsave(&clockevents_lock, flags); |
291 | 354 | ||
292 | list_add(&dev->list, &clockevent_devices); | 355 | list_add(&dev->list, &clockevent_devices); |
293 | clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev); | 356 | tick_check_new_device(dev); |
294 | clockevents_notify_released(); | 357 | clockevents_notify_released(); |
295 | 358 | ||
296 | raw_spin_unlock_irqrestore(&clockevents_lock, flags); | 359 | raw_spin_unlock_irqrestore(&clockevents_lock, flags); |
@@ -386,6 +449,7 @@ void clockevents_exchange_device(struct clock_event_device *old, | |||
386 | * released list and do a notify add later. | 449 | * released list and do a notify add later. |
387 | */ | 450 | */ |
388 | if (old) { | 451 | if (old) { |
452 | module_put(old->owner); | ||
389 | clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); | 453 | clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); |
390 | list_del(&old->list); | 454 | list_del(&old->list); |
391 | list_add(&old->list, &clockevents_released); | 455 | list_add(&old->list, &clockevents_released); |
@@ -433,10 +497,36 @@ void clockevents_notify(unsigned long reason, void *arg) | |||
433 | int cpu; | 497 | int cpu; |
434 | 498 | ||
435 | raw_spin_lock_irqsave(&clockevents_lock, flags); | 499 | raw_spin_lock_irqsave(&clockevents_lock, flags); |
436 | clockevents_do_notify(reason, arg); | ||
437 | 500 | ||
438 | switch (reason) { | 501 | switch (reason) { |
502 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | ||
503 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | ||
504 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | ||
505 | tick_broadcast_on_off(reason, arg); | ||
506 | break; | ||
507 | |||
508 | case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: | ||
509 | case CLOCK_EVT_NOTIFY_BROADCAST_EXIT: | ||
510 | tick_broadcast_oneshot_control(reason); | ||
511 | break; | ||
512 | |||
513 | case CLOCK_EVT_NOTIFY_CPU_DYING: | ||
514 | tick_handover_do_timer(arg); | ||
515 | break; | ||
516 | |||
517 | case CLOCK_EVT_NOTIFY_SUSPEND: | ||
518 | tick_suspend(); | ||
519 | tick_suspend_broadcast(); | ||
520 | break; | ||
521 | |||
522 | case CLOCK_EVT_NOTIFY_RESUME: | ||
523 | tick_resume(); | ||
524 | break; | ||
525 | |||
439 | case CLOCK_EVT_NOTIFY_CPU_DEAD: | 526 | case CLOCK_EVT_NOTIFY_CPU_DEAD: |
527 | tick_shutdown_broadcast_oneshot(arg); | ||
528 | tick_shutdown_broadcast(arg); | ||
529 | tick_shutdown(arg); | ||
440 | /* | 530 | /* |
441 | * Unregister the clock event devices which were | 531 | * Unregister the clock event devices which were |
442 | * released from the users in the notify chain. | 532 | * released from the users in the notify chain. |
@@ -462,4 +552,123 @@ void clockevents_notify(unsigned long reason, void *arg) | |||
462 | raw_spin_unlock_irqrestore(&clockevents_lock, flags); | 552 | raw_spin_unlock_irqrestore(&clockevents_lock, flags); |
463 | } | 553 | } |
464 | EXPORT_SYMBOL_GPL(clockevents_notify); | 554 | EXPORT_SYMBOL_GPL(clockevents_notify); |
555 | |||
556 | #ifdef CONFIG_SYSFS | ||
557 | struct bus_type clockevents_subsys = { | ||
558 | .name = "clockevents", | ||
559 | .dev_name = "clockevent", | ||
560 | }; | ||
561 | |||
562 | static DEFINE_PER_CPU(struct device, tick_percpu_dev); | ||
563 | static struct tick_device *tick_get_tick_dev(struct device *dev); | ||
564 | |||
565 | static ssize_t sysfs_show_current_tick_dev(struct device *dev, | ||
566 | struct device_attribute *attr, | ||
567 | char *buf) | ||
568 | { | ||
569 | struct tick_device *td; | ||
570 | ssize_t count = 0; | ||
571 | |||
572 | raw_spin_lock_irq(&clockevents_lock); | ||
573 | td = tick_get_tick_dev(dev); | ||
574 | if (td && td->evtdev) | ||
575 | count = snprintf(buf, PAGE_SIZE, "%s\n", td->evtdev->name); | ||
576 | raw_spin_unlock_irq(&clockevents_lock); | ||
577 | return count; | ||
578 | } | ||
579 | static DEVICE_ATTR(current_device, 0444, sysfs_show_current_tick_dev, NULL); | ||
580 | |||
581 | /* We don't support the abomination of removable broadcast devices */ | ||
582 | static ssize_t sysfs_unbind_tick_dev(struct device *dev, | ||
583 | struct device_attribute *attr, | ||
584 | const char *buf, size_t count) | ||
585 | { | ||
586 | char name[CS_NAME_LEN]; | ||
587 | size_t ret = sysfs_get_uname(buf, name, count); | ||
588 | struct clock_event_device *ce; | ||
589 | |||
590 | if (ret < 0) | ||
591 | return ret; | ||
592 | |||
593 | ret = -ENODEV; | ||
594 | mutex_lock(&clockevents_mutex); | ||
595 | raw_spin_lock_irq(&clockevents_lock); | ||
596 | list_for_each_entry(ce, &clockevent_devices, list) { | ||
597 | if (!strcmp(ce->name, name)) { | ||
598 | ret = __clockevents_try_unbind(ce, dev->id); | ||
599 | break; | ||
600 | } | ||
601 | } | ||
602 | raw_spin_unlock_irq(&clockevents_lock); | ||
603 | /* | ||
604 | * We hold clockevents_mutex, so ce can't go away | ||
605 | */ | ||
606 | if (ret == -EAGAIN) | ||
607 | ret = clockevents_unbind(ce, dev->id); | ||
608 | mutex_unlock(&clockevents_mutex); | ||
609 | return ret ? ret : count; | ||
610 | } | ||
611 | static DEVICE_ATTR(unbind_device, 0200, NULL, sysfs_unbind_tick_dev); | ||
612 | |||
613 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
614 | static struct device tick_bc_dev = { | ||
615 | .init_name = "broadcast", | ||
616 | .id = 0, | ||
617 | .bus = &clockevents_subsys, | ||
618 | }; | ||
619 | |||
620 | static struct tick_device *tick_get_tick_dev(struct device *dev) | ||
621 | { | ||
622 | return dev == &tick_bc_dev ? tick_get_broadcast_device() : | ||
623 | &per_cpu(tick_cpu_device, dev->id); | ||
624 | } | ||
625 | |||
626 | static __init int tick_broadcast_init_sysfs(void) | ||
627 | { | ||
628 | int err = device_register(&tick_bc_dev); | ||
629 | |||
630 | if (!err) | ||
631 | err = device_create_file(&tick_bc_dev, &dev_attr_current_device); | ||
632 | return err; | ||
633 | } | ||
634 | #else | ||
635 | static struct tick_device *tick_get_tick_dev(struct device *dev) | ||
636 | { | ||
637 | return &per_cpu(tick_cpu_device, dev->id); | ||
638 | } | ||
639 | static inline int tick_broadcast_init_sysfs(void) { return 0; } | ||
465 | #endif | 640 | #endif |
641 | |||
642 | static int __init tick_init_sysfs(void) | ||
643 | { | ||
644 | int cpu; | ||
645 | |||
646 | for_each_possible_cpu(cpu) { | ||
647 | struct device *dev = &per_cpu(tick_percpu_dev, cpu); | ||
648 | int err; | ||
649 | |||
650 | dev->id = cpu; | ||
651 | dev->bus = &clockevents_subsys; | ||
652 | err = device_register(dev); | ||
653 | if (!err) | ||
654 | err = device_create_file(dev, &dev_attr_current_device); | ||
655 | if (!err) | ||
656 | err = device_create_file(dev, &dev_attr_unbind_device); | ||
657 | if (err) | ||
658 | return err; | ||
659 | } | ||
660 | return tick_broadcast_init_sysfs(); | ||
661 | } | ||
662 | |||
663 | static int __init clockevents_init_sysfs(void) | ||
664 | { | ||
665 | int err = subsys_system_register(&clockevents_subsys, NULL); | ||
666 | |||
667 | if (!err) | ||
668 | err = tick_init_sysfs(); | ||
669 | return err; | ||
670 | } | ||
671 | device_initcall(clockevents_init_sysfs); | ||
672 | #endif /* SYSFS */ | ||
673 | |||
674 | #endif /* GENERIC_CLOCK_EVENTS */ | ||
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index c9583382141a..50a8736757f3 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/tick.h> | 31 | #include <linux/tick.h> |
32 | #include <linux/kthread.h> | 32 | #include <linux/kthread.h> |
33 | 33 | ||
34 | #include "tick-internal.h" | ||
35 | |||
34 | void timecounter_init(struct timecounter *tc, | 36 | void timecounter_init(struct timecounter *tc, |
35 | const struct cyclecounter *cc, | 37 | const struct cyclecounter *cc, |
36 | u64 start_tstamp) | 38 | u64 start_tstamp) |
@@ -174,11 +176,12 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec) | |||
174 | static struct clocksource *curr_clocksource; | 176 | static struct clocksource *curr_clocksource; |
175 | static LIST_HEAD(clocksource_list); | 177 | static LIST_HEAD(clocksource_list); |
176 | static DEFINE_MUTEX(clocksource_mutex); | 178 | static DEFINE_MUTEX(clocksource_mutex); |
177 | static char override_name[32]; | 179 | static char override_name[CS_NAME_LEN]; |
178 | static int finished_booting; | 180 | static int finished_booting; |
179 | 181 | ||
180 | #ifdef CONFIG_CLOCKSOURCE_WATCHDOG | 182 | #ifdef CONFIG_CLOCKSOURCE_WATCHDOG |
181 | static void clocksource_watchdog_work(struct work_struct *work); | 183 | static void clocksource_watchdog_work(struct work_struct *work); |
184 | static void clocksource_select(void); | ||
182 | 185 | ||
183 | static LIST_HEAD(watchdog_list); | 186 | static LIST_HEAD(watchdog_list); |
184 | static struct clocksource *watchdog; | 187 | static struct clocksource *watchdog; |
@@ -299,13 +302,30 @@ static void clocksource_watchdog(unsigned long data) | |||
299 | if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && | 302 | if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && |
300 | (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) && | 303 | (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) && |
301 | (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) { | 304 | (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) { |
305 | /* Mark it valid for high-res. */ | ||
302 | cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; | 306 | cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; |
307 | |||
308 | /* | ||
309 | * clocksource_done_booting() will sort it if | ||
310 | * finished_booting is not set yet. | ||
311 | */ | ||
312 | if (!finished_booting) | ||
313 | continue; | ||
314 | |||
303 | /* | 315 | /* |
304 | * We just marked the clocksource as highres-capable, | 316 | * If this is not the current clocksource let |
305 | * notify the rest of the system as well so that we | 317 | * the watchdog thread reselect it. Due to the |
306 | * transition into high-res mode: | 318 | * change to high res this clocksource might |
319 | * be preferred now. If it is the current | ||
320 | * clocksource let the tick code know about | ||
321 | * that change. | ||
307 | */ | 322 | */ |
308 | tick_clock_notify(); | 323 | if (cs != curr_clocksource) { |
324 | cs->flags |= CLOCK_SOURCE_RESELECT; | ||
325 | schedule_work(&watchdog_work); | ||
326 | } else { | ||
327 | tick_clock_notify(); | ||
328 | } | ||
309 | } | 329 | } |
310 | } | 330 | } |
311 | 331 | ||
@@ -388,44 +408,39 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs) | |||
388 | 408 | ||
389 | static void clocksource_dequeue_watchdog(struct clocksource *cs) | 409 | static void clocksource_dequeue_watchdog(struct clocksource *cs) |
390 | { | 410 | { |
391 | struct clocksource *tmp; | ||
392 | unsigned long flags; | 411 | unsigned long flags; |
393 | 412 | ||
394 | spin_lock_irqsave(&watchdog_lock, flags); | 413 | spin_lock_irqsave(&watchdog_lock, flags); |
395 | if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { | 414 | if (cs != watchdog) { |
396 | /* cs is a watched clocksource. */ | 415 | if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { |
397 | list_del_init(&cs->wd_list); | 416 | /* cs is a watched clocksource. */ |
398 | } else if (cs == watchdog) { | 417 | list_del_init(&cs->wd_list); |
399 | /* Reset watchdog cycles */ | 418 | /* Check if the watchdog timer needs to be stopped. */ |
400 | clocksource_reset_watchdog(); | 419 | clocksource_stop_watchdog(); |
401 | /* Current watchdog is removed. Find an alternative. */ | ||
402 | watchdog = NULL; | ||
403 | list_for_each_entry(tmp, &clocksource_list, list) { | ||
404 | if (tmp == cs || tmp->flags & CLOCK_SOURCE_MUST_VERIFY) | ||
405 | continue; | ||
406 | if (!watchdog || tmp->rating > watchdog->rating) | ||
407 | watchdog = tmp; | ||
408 | } | 420 | } |
409 | } | 421 | } |
410 | cs->flags &= ~CLOCK_SOURCE_WATCHDOG; | ||
411 | /* Check if the watchdog timer needs to be stopped. */ | ||
412 | clocksource_stop_watchdog(); | ||
413 | spin_unlock_irqrestore(&watchdog_lock, flags); | 422 | spin_unlock_irqrestore(&watchdog_lock, flags); |
414 | } | 423 | } |
415 | 424 | ||
416 | static int clocksource_watchdog_kthread(void *data) | 425 | static int __clocksource_watchdog_kthread(void) |
417 | { | 426 | { |
418 | struct clocksource *cs, *tmp; | 427 | struct clocksource *cs, *tmp; |
419 | unsigned long flags; | 428 | unsigned long flags; |
420 | LIST_HEAD(unstable); | 429 | LIST_HEAD(unstable); |
430 | int select = 0; | ||
421 | 431 | ||
422 | mutex_lock(&clocksource_mutex); | ||
423 | spin_lock_irqsave(&watchdog_lock, flags); | 432 | spin_lock_irqsave(&watchdog_lock, flags); |
424 | list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) | 433 | list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { |
425 | if (cs->flags & CLOCK_SOURCE_UNSTABLE) { | 434 | if (cs->flags & CLOCK_SOURCE_UNSTABLE) { |
426 | list_del_init(&cs->wd_list); | 435 | list_del_init(&cs->wd_list); |
427 | list_add(&cs->wd_list, &unstable); | 436 | list_add(&cs->wd_list, &unstable); |
437 | select = 1; | ||
428 | } | 438 | } |
439 | if (cs->flags & CLOCK_SOURCE_RESELECT) { | ||
440 | cs->flags &= ~CLOCK_SOURCE_RESELECT; | ||
441 | select = 1; | ||
442 | } | ||
443 | } | ||
429 | /* Check if the watchdog timer needs to be stopped. */ | 444 | /* Check if the watchdog timer needs to be stopped. */ |
430 | clocksource_stop_watchdog(); | 445 | clocksource_stop_watchdog(); |
431 | spin_unlock_irqrestore(&watchdog_lock, flags); | 446 | spin_unlock_irqrestore(&watchdog_lock, flags); |
@@ -435,10 +450,23 @@ static int clocksource_watchdog_kthread(void *data) | |||
435 | list_del_init(&cs->wd_list); | 450 | list_del_init(&cs->wd_list); |
436 | __clocksource_change_rating(cs, 0); | 451 | __clocksource_change_rating(cs, 0); |
437 | } | 452 | } |
453 | return select; | ||
454 | } | ||
455 | |||
456 | static int clocksource_watchdog_kthread(void *data) | ||
457 | { | ||
458 | mutex_lock(&clocksource_mutex); | ||
459 | if (__clocksource_watchdog_kthread()) | ||
460 | clocksource_select(); | ||
438 | mutex_unlock(&clocksource_mutex); | 461 | mutex_unlock(&clocksource_mutex); |
439 | return 0; | 462 | return 0; |
440 | } | 463 | } |
441 | 464 | ||
465 | static bool clocksource_is_watchdog(struct clocksource *cs) | ||
466 | { | ||
467 | return cs == watchdog; | ||
468 | } | ||
469 | |||
442 | #else /* CONFIG_CLOCKSOURCE_WATCHDOG */ | 470 | #else /* CONFIG_CLOCKSOURCE_WATCHDOG */ |
443 | 471 | ||
444 | static void clocksource_enqueue_watchdog(struct clocksource *cs) | 472 | static void clocksource_enqueue_watchdog(struct clocksource *cs) |
@@ -449,7 +477,8 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs) | |||
449 | 477 | ||
450 | static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { } | 478 | static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { } |
451 | static inline void clocksource_resume_watchdog(void) { } | 479 | static inline void clocksource_resume_watchdog(void) { } |
452 | static inline int clocksource_watchdog_kthread(void *data) { return 0; } | 480 | static inline int __clocksource_watchdog_kthread(void) { return 0; } |
481 | static bool clocksource_is_watchdog(struct clocksource *cs) { return false; } | ||
453 | 482 | ||
454 | #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */ | 483 | #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */ |
455 | 484 | ||
@@ -553,24 +582,42 @@ static u64 clocksource_max_deferment(struct clocksource *cs) | |||
553 | 582 | ||
554 | #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET | 583 | #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET |
555 | 584 | ||
556 | /** | 585 | static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur) |
557 | * clocksource_select - Select the best clocksource available | ||
558 | * | ||
559 | * Private function. Must hold clocksource_mutex when called. | ||
560 | * | ||
561 | * Select the clocksource with the best rating, or the clocksource, | ||
562 | * which is selected by userspace override. | ||
563 | */ | ||
564 | static void clocksource_select(void) | ||
565 | { | 586 | { |
566 | struct clocksource *best, *cs; | 587 | struct clocksource *cs; |
567 | 588 | ||
568 | if (!finished_booting || list_empty(&clocksource_list)) | 589 | if (!finished_booting || list_empty(&clocksource_list)) |
590 | return NULL; | ||
591 | |||
592 | /* | ||
593 | * We pick the clocksource with the highest rating. If oneshot | ||
594 | * mode is active, we pick the highres valid clocksource with | ||
595 | * the best rating. | ||
596 | */ | ||
597 | list_for_each_entry(cs, &clocksource_list, list) { | ||
598 | if (skipcur && cs == curr_clocksource) | ||
599 | continue; | ||
600 | if (oneshot && !(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES)) | ||
601 | continue; | ||
602 | return cs; | ||
603 | } | ||
604 | return NULL; | ||
605 | } | ||
606 | |||
607 | static void __clocksource_select(bool skipcur) | ||
608 | { | ||
609 | bool oneshot = tick_oneshot_mode_active(); | ||
610 | struct clocksource *best, *cs; | ||
611 | |||
612 | /* Find the best suitable clocksource */ | ||
613 | best = clocksource_find_best(oneshot, skipcur); | ||
614 | if (!best) | ||
569 | return; | 615 | return; |
570 | /* First clocksource on the list has the best rating. */ | 616 | |
571 | best = list_first_entry(&clocksource_list, struct clocksource, list); | ||
572 | /* Check for the override clocksource. */ | 617 | /* Check for the override clocksource. */ |
573 | list_for_each_entry(cs, &clocksource_list, list) { | 618 | list_for_each_entry(cs, &clocksource_list, list) { |
619 | if (skipcur && cs == curr_clocksource) | ||
620 | continue; | ||
574 | if (strcmp(cs->name, override_name) != 0) | 621 | if (strcmp(cs->name, override_name) != 0) |
575 | continue; | 622 | continue; |
576 | /* | 623 | /* |
@@ -578,8 +625,7 @@ static void clocksource_select(void) | |||
578 | * capable clocksource if the tick code is in oneshot | 625 | * capable clocksource if the tick code is in oneshot |
579 | * mode (highres or nohz) | 626 | * mode (highres or nohz) |
580 | */ | 627 | */ |
581 | if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && | 628 | if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && oneshot) { |
582 | tick_oneshot_mode_active()) { | ||
583 | /* Override clocksource cannot be used. */ | 629 | /* Override clocksource cannot be used. */ |
584 | printk(KERN_WARNING "Override clocksource %s is not " | 630 | printk(KERN_WARNING "Override clocksource %s is not " |
585 | "HRT compatible. Cannot switch while in " | 631 | "HRT compatible. Cannot switch while in " |
@@ -590,16 +636,35 @@ static void clocksource_select(void) | |||
590 | best = cs; | 636 | best = cs; |
591 | break; | 637 | break; |
592 | } | 638 | } |
593 | if (curr_clocksource != best) { | 639 | |
594 | printk(KERN_INFO "Switching to clocksource %s\n", best->name); | 640 | if (curr_clocksource != best && !timekeeping_notify(best)) { |
641 | pr_info("Switched to clocksource %s\n", best->name); | ||
595 | curr_clocksource = best; | 642 | curr_clocksource = best; |
596 | timekeeping_notify(curr_clocksource); | ||
597 | } | 643 | } |
598 | } | 644 | } |
599 | 645 | ||
646 | /** | ||
647 | * clocksource_select - Select the best clocksource available | ||
648 | * | ||
649 | * Private function. Must hold clocksource_mutex when called. | ||
650 | * | ||
651 | * Select the clocksource with the best rating, or the clocksource, | ||
652 | * which is selected by userspace override. | ||
653 | */ | ||
654 | static void clocksource_select(void) | ||
655 | { | ||
656 | return __clocksource_select(false); | ||
657 | } | ||
658 | |||
659 | static void clocksource_select_fallback(void) | ||
660 | { | ||
661 | return __clocksource_select(true); | ||
662 | } | ||
663 | |||
600 | #else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */ | 664 | #else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */ |
601 | 665 | ||
602 | static inline void clocksource_select(void) { } | 666 | static inline void clocksource_select(void) { } |
667 | static inline void clocksource_select_fallback(void) { } | ||
603 | 668 | ||
604 | #endif | 669 | #endif |
605 | 670 | ||
@@ -614,16 +679,11 @@ static int __init clocksource_done_booting(void) | |||
614 | { | 679 | { |
615 | mutex_lock(&clocksource_mutex); | 680 | mutex_lock(&clocksource_mutex); |
616 | curr_clocksource = clocksource_default_clock(); | 681 | curr_clocksource = clocksource_default_clock(); |
617 | mutex_unlock(&clocksource_mutex); | ||
618 | |||
619 | finished_booting = 1; | 682 | finished_booting = 1; |
620 | |||
621 | /* | 683 | /* |
622 | * Run the watchdog first to eliminate unstable clock sources | 684 | * Run the watchdog first to eliminate unstable clock sources |
623 | */ | 685 | */ |
624 | clocksource_watchdog_kthread(NULL); | 686 | __clocksource_watchdog_kthread(); |
625 | |||
626 | mutex_lock(&clocksource_mutex); | ||
627 | clocksource_select(); | 687 | clocksource_select(); |
628 | mutex_unlock(&clocksource_mutex); | 688 | mutex_unlock(&clocksource_mutex); |
629 | return 0; | 689 | return 0; |
@@ -756,7 +816,6 @@ static void __clocksource_change_rating(struct clocksource *cs, int rating) | |||
756 | list_del(&cs->list); | 816 | list_del(&cs->list); |
757 | cs->rating = rating; | 817 | cs->rating = rating; |
758 | clocksource_enqueue(cs); | 818 | clocksource_enqueue(cs); |
759 | clocksource_select(); | ||
760 | } | 819 | } |
761 | 820 | ||
762 | /** | 821 | /** |
@@ -768,21 +827,47 @@ void clocksource_change_rating(struct clocksource *cs, int rating) | |||
768 | { | 827 | { |
769 | mutex_lock(&clocksource_mutex); | 828 | mutex_lock(&clocksource_mutex); |
770 | __clocksource_change_rating(cs, rating); | 829 | __clocksource_change_rating(cs, rating); |
830 | clocksource_select(); | ||
771 | mutex_unlock(&clocksource_mutex); | 831 | mutex_unlock(&clocksource_mutex); |
772 | } | 832 | } |
773 | EXPORT_SYMBOL(clocksource_change_rating); | 833 | EXPORT_SYMBOL(clocksource_change_rating); |
774 | 834 | ||
835 | /* | ||
836 | * Unbind clocksource @cs. Called with clocksource_mutex held | ||
837 | */ | ||
838 | static int clocksource_unbind(struct clocksource *cs) | ||
839 | { | ||
840 | /* | ||
841 | * I really can't convince myself to support this on hardware | ||
842 | * designed by lobotomized monkeys. | ||
843 | */ | ||
844 | if (clocksource_is_watchdog(cs)) | ||
845 | return -EBUSY; | ||
846 | |||
847 | if (cs == curr_clocksource) { | ||
848 | /* Select and try to install a replacement clock source */ | ||
849 | clocksource_select_fallback(); | ||
850 | if (curr_clocksource == cs) | ||
851 | return -EBUSY; | ||
852 | } | ||
853 | clocksource_dequeue_watchdog(cs); | ||
854 | list_del_init(&cs->list); | ||
855 | return 0; | ||
856 | } | ||
857 | |||
775 | /** | 858 | /** |
776 | * clocksource_unregister - remove a registered clocksource | 859 | * clocksource_unregister - remove a registered clocksource |
777 | * @cs: clocksource to be unregistered | 860 | * @cs: clocksource to be unregistered |
778 | */ | 861 | */ |
779 | void clocksource_unregister(struct clocksource *cs) | 862 | int clocksource_unregister(struct clocksource *cs) |
780 | { | 863 | { |
864 | int ret = 0; | ||
865 | |||
781 | mutex_lock(&clocksource_mutex); | 866 | mutex_lock(&clocksource_mutex); |
782 | clocksource_dequeue_watchdog(cs); | 867 | if (!list_empty(&cs->list)) |
783 | list_del(&cs->list); | 868 | ret = clocksource_unbind(cs); |
784 | clocksource_select(); | ||
785 | mutex_unlock(&clocksource_mutex); | 869 | mutex_unlock(&clocksource_mutex); |
870 | return ret; | ||
786 | } | 871 | } |
787 | EXPORT_SYMBOL(clocksource_unregister); | 872 | EXPORT_SYMBOL(clocksource_unregister); |
788 | 873 | ||
@@ -808,6 +893,23 @@ sysfs_show_current_clocksources(struct device *dev, | |||
808 | return count; | 893 | return count; |
809 | } | 894 | } |
810 | 895 | ||
896 | size_t sysfs_get_uname(const char *buf, char *dst, size_t cnt) | ||
897 | { | ||
898 | size_t ret = cnt; | ||
899 | |||
900 | /* strings from sysfs write are not 0 terminated! */ | ||
901 | if (!cnt || cnt >= CS_NAME_LEN) | ||
902 | return -EINVAL; | ||
903 | |||
904 | /* strip of \n: */ | ||
905 | if (buf[cnt-1] == '\n') | ||
906 | cnt--; | ||
907 | if (cnt > 0) | ||
908 | memcpy(dst, buf, cnt); | ||
909 | dst[cnt] = 0; | ||
910 | return ret; | ||
911 | } | ||
912 | |||
811 | /** | 913 | /** |
812 | * sysfs_override_clocksource - interface for manually overriding clocksource | 914 | * sysfs_override_clocksource - interface for manually overriding clocksource |
813 | * @dev: unused | 915 | * @dev: unused |
@@ -822,22 +924,13 @@ static ssize_t sysfs_override_clocksource(struct device *dev, | |||
822 | struct device_attribute *attr, | 924 | struct device_attribute *attr, |
823 | const char *buf, size_t count) | 925 | const char *buf, size_t count) |
824 | { | 926 | { |
825 | size_t ret = count; | 927 | size_t ret; |
826 | |||
827 | /* strings from sysfs write are not 0 terminated! */ | ||
828 | if (count >= sizeof(override_name)) | ||
829 | return -EINVAL; | ||
830 | |||
831 | /* strip of \n: */ | ||
832 | if (buf[count-1] == '\n') | ||
833 | count--; | ||
834 | 928 | ||
835 | mutex_lock(&clocksource_mutex); | 929 | mutex_lock(&clocksource_mutex); |
836 | 930 | ||
837 | if (count > 0) | 931 | ret = sysfs_get_uname(buf, override_name, count); |
838 | memcpy(override_name, buf, count); | 932 | if (ret >= 0) |
839 | override_name[count] = 0; | 933 | clocksource_select(); |
840 | clocksource_select(); | ||
841 | 934 | ||
842 | mutex_unlock(&clocksource_mutex); | 935 | mutex_unlock(&clocksource_mutex); |
843 | 936 | ||
@@ -845,6 +938,40 @@ static ssize_t sysfs_override_clocksource(struct device *dev, | |||
845 | } | 938 | } |
846 | 939 | ||
847 | /** | 940 | /** |
941 | * sysfs_unbind_current_clocksource - interface for manually unbinding clocksource | ||
942 | * @dev: unused | ||
943 | * @attr: unused | ||
944 | * @buf: unused | ||
945 | * @count: length of buffer | ||
946 | * | ||
947 | * Takes input from sysfs interface for manually unbinding a clocksource. | ||
948 | */ | ||
949 | static ssize_t sysfs_unbind_clocksource(struct device *dev, | ||
950 | struct device_attribute *attr, | ||
951 | const char *buf, size_t count) | ||
952 | { | ||
953 | struct clocksource *cs; | ||
954 | char name[CS_NAME_LEN]; | ||
955 | size_t ret; | ||
956 | |||
957 | ret = sysfs_get_uname(buf, name, count); | ||
958 | if (ret < 0) | ||
959 | return ret; | ||
960 | |||
961 | ret = -ENODEV; | ||
962 | mutex_lock(&clocksource_mutex); | ||
963 | list_for_each_entry(cs, &clocksource_list, list) { | ||
964 | if (strcmp(cs->name, name)) | ||
965 | continue; | ||
966 | ret = clocksource_unbind(cs); | ||
967 | break; | ||
968 | } | ||
969 | mutex_unlock(&clocksource_mutex); | ||
970 | |||
971 | return ret ? ret : count; | ||
972 | } | ||
973 | |||
974 | /** | ||
848 | * sysfs_show_available_clocksources - sysfs interface for listing clocksource | 975 | * sysfs_show_available_clocksources - sysfs interface for listing clocksource |
849 | * @dev: unused | 976 | * @dev: unused |
850 | * @attr: unused | 977 | * @attr: unused |
@@ -886,6 +1013,8 @@ sysfs_show_available_clocksources(struct device *dev, | |||
886 | static DEVICE_ATTR(current_clocksource, 0644, sysfs_show_current_clocksources, | 1013 | static DEVICE_ATTR(current_clocksource, 0644, sysfs_show_current_clocksources, |
887 | sysfs_override_clocksource); | 1014 | sysfs_override_clocksource); |
888 | 1015 | ||
1016 | static DEVICE_ATTR(unbind_clocksource, 0200, NULL, sysfs_unbind_clocksource); | ||
1017 | |||
889 | static DEVICE_ATTR(available_clocksource, 0444, | 1018 | static DEVICE_ATTR(available_clocksource, 0444, |
890 | sysfs_show_available_clocksources, NULL); | 1019 | sysfs_show_available_clocksources, NULL); |
891 | 1020 | ||
@@ -910,6 +1039,9 @@ static int __init init_clocksource_sysfs(void) | |||
910 | &device_clocksource, | 1039 | &device_clocksource, |
911 | &dev_attr_current_clocksource); | 1040 | &dev_attr_current_clocksource); |
912 | if (!error) | 1041 | if (!error) |
1042 | error = device_create_file(&device_clocksource, | ||
1043 | &dev_attr_unbind_clocksource); | ||
1044 | if (!error) | ||
913 | error = device_create_file( | 1045 | error = device_create_file( |
914 | &device_clocksource, | 1046 | &device_clocksource, |
915 | &dev_attr_available_clocksource); | 1047 | &dev_attr_available_clocksource); |
diff --git a/arch/arm/kernel/sched_clock.c b/kernel/time/sched_clock.c index e8edcaa0e432..a326f27d7f09 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/kernel/time/sched_clock.c | |||
@@ -13,8 +13,7 @@ | |||
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/syscore_ops.h> | 14 | #include <linux/syscore_ops.h> |
15 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
16 | 16 | #include <linux/sched_clock.h> | |
17 | #include <asm/sched_clock.h> | ||
18 | 17 | ||
19 | struct clock_data { | 18 | struct clock_data { |
20 | u64 epoch_ns; | 19 | u64 epoch_ns; |
@@ -24,7 +23,6 @@ struct clock_data { | |||
24 | u32 mult; | 23 | u32 mult; |
25 | u32 shift; | 24 | u32 shift; |
26 | bool suspended; | 25 | bool suspended; |
27 | bool needs_suspend; | ||
28 | }; | 26 | }; |
29 | 27 | ||
30 | static void sched_clock_poll(unsigned long wrap_ticks); | 28 | static void sched_clock_poll(unsigned long wrap_ticks); |
@@ -51,10 +49,11 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift) | |||
51 | return (cyc * mult) >> shift; | 49 | return (cyc * mult) >> shift; |
52 | } | 50 | } |
53 | 51 | ||
54 | static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask) | 52 | static unsigned long long notrace sched_clock_32(void) |
55 | { | 53 | { |
56 | u64 epoch_ns; | 54 | u64 epoch_ns; |
57 | u32 epoch_cyc; | 55 | u32 epoch_cyc; |
56 | u32 cyc; | ||
58 | 57 | ||
59 | if (cd.suspended) | 58 | if (cd.suspended) |
60 | return cd.epoch_ns; | 59 | return cd.epoch_ns; |
@@ -73,7 +72,9 @@ static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask) | |||
73 | smp_rmb(); | 72 | smp_rmb(); |
74 | } while (epoch_cyc != cd.epoch_cyc_copy); | 73 | } while (epoch_cyc != cd.epoch_cyc_copy); |
75 | 74 | ||
76 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, cd.mult, cd.shift); | 75 | cyc = read_sched_clock(); |
76 | cyc = (cyc - epoch_cyc) & sched_clock_mask; | ||
77 | return epoch_ns + cyc_to_ns(cyc, cd.mult, cd.shift); | ||
77 | } | 78 | } |
78 | 79 | ||
79 | /* | 80 | /* |
@@ -165,12 +166,6 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) | |||
165 | pr_debug("Registered %pF as sched_clock source\n", read); | 166 | pr_debug("Registered %pF as sched_clock source\n", read); |
166 | } | 167 | } |
167 | 168 | ||
168 | static unsigned long long notrace sched_clock_32(void) | ||
169 | { | ||
170 | u32 cyc = read_sched_clock(); | ||
171 | return cyc_to_sched_clock(cyc, sched_clock_mask); | ||
172 | } | ||
173 | |||
174 | unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32; | 169 | unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32; |
175 | 170 | ||
176 | unsigned long long notrace sched_clock(void) | 171 | unsigned long long notrace sched_clock(void) |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 20d6fba70652..6d3f91631de6 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/profile.h> | 19 | #include <linux/profile.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/module.h> | ||
22 | 23 | ||
23 | #include "tick-internal.h" | 24 | #include "tick-internal.h" |
24 | 25 | ||
@@ -29,6 +30,7 @@ | |||
29 | 30 | ||
30 | static struct tick_device tick_broadcast_device; | 31 | static struct tick_device tick_broadcast_device; |
31 | static cpumask_var_t tick_broadcast_mask; | 32 | static cpumask_var_t tick_broadcast_mask; |
33 | static cpumask_var_t tick_broadcast_on; | ||
32 | static cpumask_var_t tmpmask; | 34 | static cpumask_var_t tmpmask; |
33 | static DEFINE_RAW_SPINLOCK(tick_broadcast_lock); | 35 | static DEFINE_RAW_SPINLOCK(tick_broadcast_lock); |
34 | static int tick_broadcast_force; | 36 | static int tick_broadcast_force; |
@@ -64,17 +66,34 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc) | |||
64 | /* | 66 | /* |
65 | * Check, if the device can be utilized as broadcast device: | 67 | * Check, if the device can be utilized as broadcast device: |
66 | */ | 68 | */ |
67 | int tick_check_broadcast_device(struct clock_event_device *dev) | 69 | static bool tick_check_broadcast_device(struct clock_event_device *curdev, |
70 | struct clock_event_device *newdev) | ||
71 | { | ||
72 | if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) || | ||
73 | (newdev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
74 | return false; | ||
75 | |||
76 | if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT && | ||
77 | !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) | ||
78 | return false; | ||
79 | |||
80 | return !curdev || newdev->rating > curdev->rating; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Conditionally install/replace broadcast device | ||
85 | */ | ||
86 | void tick_install_broadcast_device(struct clock_event_device *dev) | ||
68 | { | 87 | { |
69 | struct clock_event_device *cur = tick_broadcast_device.evtdev; | 88 | struct clock_event_device *cur = tick_broadcast_device.evtdev; |
70 | 89 | ||
71 | if ((dev->features & CLOCK_EVT_FEAT_DUMMY) || | 90 | if (!tick_check_broadcast_device(cur, dev)) |
72 | (tick_broadcast_device.evtdev && | 91 | return; |
73 | tick_broadcast_device.evtdev->rating >= dev->rating) || | ||
74 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
75 | return 0; | ||
76 | 92 | ||
77 | clockevents_exchange_device(tick_broadcast_device.evtdev, dev); | 93 | if (!try_module_get(dev->owner)) |
94 | return; | ||
95 | |||
96 | clockevents_exchange_device(cur, dev); | ||
78 | if (cur) | 97 | if (cur) |
79 | cur->event_handler = clockevents_handle_noop; | 98 | cur->event_handler = clockevents_handle_noop; |
80 | tick_broadcast_device.evtdev = dev; | 99 | tick_broadcast_device.evtdev = dev; |
@@ -90,7 +109,6 @@ int tick_check_broadcast_device(struct clock_event_device *dev) | |||
90 | */ | 109 | */ |
91 | if (dev->features & CLOCK_EVT_FEAT_ONESHOT) | 110 | if (dev->features & CLOCK_EVT_FEAT_ONESHOT) |
92 | tick_clock_notify(); | 111 | tick_clock_notify(); |
93 | return 1; | ||
94 | } | 112 | } |
95 | 113 | ||
96 | /* | 114 | /* |
@@ -123,8 +141,9 @@ static void tick_device_setup_broadcast_func(struct clock_event_device *dev) | |||
123 | */ | 141 | */ |
124 | int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) | 142 | int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) |
125 | { | 143 | { |
144 | struct clock_event_device *bc = tick_broadcast_device.evtdev; | ||
126 | unsigned long flags; | 145 | unsigned long flags; |
127 | int ret = 0; | 146 | int ret; |
128 | 147 | ||
129 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); | 148 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); |
130 | 149 | ||
@@ -138,20 +157,59 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) | |||
138 | dev->event_handler = tick_handle_periodic; | 157 | dev->event_handler = tick_handle_periodic; |
139 | tick_device_setup_broadcast_func(dev); | 158 | tick_device_setup_broadcast_func(dev); |
140 | cpumask_set_cpu(cpu, tick_broadcast_mask); | 159 | cpumask_set_cpu(cpu, tick_broadcast_mask); |
141 | tick_broadcast_start_periodic(tick_broadcast_device.evtdev); | 160 | tick_broadcast_start_periodic(bc); |
142 | ret = 1; | 161 | ret = 1; |
143 | } else { | 162 | } else { |
144 | /* | 163 | /* |
145 | * When the new device is not affected by the stop | 164 | * Clear the broadcast bit for this cpu if the |
146 | * feature and the cpu is marked in the broadcast mask | 165 | * device is not power state affected. |
147 | * then clear the broadcast bit. | ||
148 | */ | 166 | */ |
149 | if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) { | 167 | if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) |
150 | int cpu = smp_processor_id(); | ||
151 | cpumask_clear_cpu(cpu, tick_broadcast_mask); | 168 | cpumask_clear_cpu(cpu, tick_broadcast_mask); |
152 | tick_broadcast_clear_oneshot(cpu); | 169 | else |
153 | } else { | ||
154 | tick_device_setup_broadcast_func(dev); | 170 | tick_device_setup_broadcast_func(dev); |
171 | |||
172 | /* | ||
173 | * Clear the broadcast bit if the CPU is not in | ||
174 | * periodic broadcast on state. | ||
175 | */ | ||
176 | if (!cpumask_test_cpu(cpu, tick_broadcast_on)) | ||
177 | cpumask_clear_cpu(cpu, tick_broadcast_mask); | ||
178 | |||
179 | switch (tick_broadcast_device.mode) { | ||
180 | case TICKDEV_MODE_ONESHOT: | ||
181 | /* | ||
182 | * If the system is in oneshot mode we can | ||
183 | * unconditionally clear the oneshot mask bit, | ||
184 | * because the CPU is running and therefore | ||
185 | * not in an idle state which causes the power | ||
186 | * state affected device to stop. Let the | ||
187 | * caller initialize the device. | ||
188 | */ | ||
189 | tick_broadcast_clear_oneshot(cpu); | ||
190 | ret = 0; | ||
191 | break; | ||
192 | |||
193 | case TICKDEV_MODE_PERIODIC: | ||
194 | /* | ||
195 | * If the system is in periodic mode, check | ||
196 | * whether the broadcast device can be | ||
197 | * switched off now. | ||
198 | */ | ||
199 | if (cpumask_empty(tick_broadcast_mask) && bc) | ||
200 | clockevents_shutdown(bc); | ||
201 | /* | ||
202 | * If we kept the cpu in the broadcast mask, | ||
203 | * tell the caller to leave the per cpu device | ||
204 | * in shutdown state. The periodic interrupt | ||
205 | * is delivered by the broadcast device. | ||
206 | */ | ||
207 | ret = cpumask_test_cpu(cpu, tick_broadcast_mask); | ||
208 | break; | ||
209 | default: | ||
210 | /* Nothing to do */ | ||
211 | ret = 0; | ||
212 | break; | ||
155 | } | 213 | } |
156 | } | 214 | } |
157 | raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); | 215 | raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); |
@@ -281,6 +339,7 @@ static void tick_do_broadcast_on_off(unsigned long *reason) | |||
281 | switch (*reason) { | 339 | switch (*reason) { |
282 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | 340 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: |
283 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | 341 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: |
342 | cpumask_set_cpu(cpu, tick_broadcast_on); | ||
284 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { | 343 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { |
285 | if (tick_broadcast_device.mode == | 344 | if (tick_broadcast_device.mode == |
286 | TICKDEV_MODE_PERIODIC) | 345 | TICKDEV_MODE_PERIODIC) |
@@ -290,8 +349,12 @@ static void tick_do_broadcast_on_off(unsigned long *reason) | |||
290 | tick_broadcast_force = 1; | 349 | tick_broadcast_force = 1; |
291 | break; | 350 | break; |
292 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | 351 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: |
293 | if (!tick_broadcast_force && | 352 | if (tick_broadcast_force) |
294 | cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) { | 353 | break; |
354 | cpumask_clear_cpu(cpu, tick_broadcast_on); | ||
355 | if (!tick_device_is_functional(dev)) | ||
356 | break; | ||
357 | if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) { | ||
295 | if (tick_broadcast_device.mode == | 358 | if (tick_broadcast_device.mode == |
296 | TICKDEV_MODE_PERIODIC) | 359 | TICKDEV_MODE_PERIODIC) |
297 | tick_setup_periodic(dev, 0); | 360 | tick_setup_periodic(dev, 0); |
@@ -349,6 +412,7 @@ void tick_shutdown_broadcast(unsigned int *cpup) | |||
349 | 412 | ||
350 | bc = tick_broadcast_device.evtdev; | 413 | bc = tick_broadcast_device.evtdev; |
351 | cpumask_clear_cpu(cpu, tick_broadcast_mask); | 414 | cpumask_clear_cpu(cpu, tick_broadcast_mask); |
415 | cpumask_clear_cpu(cpu, tick_broadcast_on); | ||
352 | 416 | ||
353 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { | 417 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { |
354 | if (bc && cpumask_empty(tick_broadcast_mask)) | 418 | if (bc && cpumask_empty(tick_broadcast_mask)) |
@@ -475,7 +539,15 @@ void tick_check_oneshot_broadcast(int cpu) | |||
475 | if (cpumask_test_cpu(cpu, tick_broadcast_oneshot_mask)) { | 539 | if (cpumask_test_cpu(cpu, tick_broadcast_oneshot_mask)) { |
476 | struct tick_device *td = &per_cpu(tick_cpu_device, cpu); | 540 | struct tick_device *td = &per_cpu(tick_cpu_device, cpu); |
477 | 541 | ||
478 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_ONESHOT); | 542 | /* |
543 | * We might be in the middle of switching over from | ||
544 | * periodic to oneshot. If the CPU has not yet | ||
545 | * switched over, leave the device alone. | ||
546 | */ | ||
547 | if (td->mode == TICKDEV_MODE_ONESHOT) { | ||
548 | clockevents_set_mode(td->evtdev, | ||
549 | CLOCK_EVT_MODE_ONESHOT); | ||
550 | } | ||
479 | } | 551 | } |
480 | } | 552 | } |
481 | 553 | ||
@@ -522,6 +594,13 @@ again: | |||
522 | cpumask_clear(tick_broadcast_force_mask); | 594 | cpumask_clear(tick_broadcast_force_mask); |
523 | 595 | ||
524 | /* | 596 | /* |
597 | * Sanity check. Catch the case where we try to broadcast to | ||
598 | * offline cpus. | ||
599 | */ | ||
600 | if (WARN_ON_ONCE(!cpumask_subset(tmpmask, cpu_online_mask))) | ||
601 | cpumask_and(tmpmask, tmpmask, cpu_online_mask); | ||
602 | |||
603 | /* | ||
525 | * Wakeup the cpus which have an expired event. | 604 | * Wakeup the cpus which have an expired event. |
526 | */ | 605 | */ |
527 | tick_do_broadcast(tmpmask); | 606 | tick_do_broadcast(tmpmask); |
@@ -761,10 +840,12 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup) | |||
761 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); | 840 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); |
762 | 841 | ||
763 | /* | 842 | /* |
764 | * Clear the broadcast mask flag for the dead cpu, but do not | 843 | * Clear the broadcast masks for the dead cpu, but do not stop |
765 | * stop the broadcast device! | 844 | * the broadcast device! |
766 | */ | 845 | */ |
767 | cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); | 846 | cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); |
847 | cpumask_clear_cpu(cpu, tick_broadcast_pending_mask); | ||
848 | cpumask_clear_cpu(cpu, tick_broadcast_force_mask); | ||
768 | 849 | ||
769 | raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); | 850 | raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); |
770 | } | 851 | } |
@@ -792,6 +873,7 @@ bool tick_broadcast_oneshot_available(void) | |||
792 | void __init tick_broadcast_init(void) | 873 | void __init tick_broadcast_init(void) |
793 | { | 874 | { |
794 | zalloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT); | 875 | zalloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT); |
876 | zalloc_cpumask_var(&tick_broadcast_on, GFP_NOWAIT); | ||
795 | zalloc_cpumask_var(&tmpmask, GFP_NOWAIT); | 877 | zalloc_cpumask_var(&tmpmask, GFP_NOWAIT); |
796 | #ifdef CONFIG_TICK_ONESHOT | 878 | #ifdef CONFIG_TICK_ONESHOT |
797 | zalloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT); | 879 | zalloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT); |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 5d3fb100bc06..64522ecdfe0e 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/percpu.h> | 18 | #include <linux/percpu.h> |
19 | #include <linux/profile.h> | 19 | #include <linux/profile.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | #include <asm/irq_regs.h> | 23 | #include <asm/irq_regs.h> |
23 | 24 | ||
@@ -33,7 +34,6 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device); | |||
33 | ktime_t tick_next_period; | 34 | ktime_t tick_next_period; |
34 | ktime_t tick_period; | 35 | ktime_t tick_period; |
35 | int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; | 36 | int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; |
36 | static DEFINE_RAW_SPINLOCK(tick_device_lock); | ||
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Debugging: see timer_list.c | 39 | * Debugging: see timer_list.c |
@@ -194,7 +194,8 @@ static void tick_setup_device(struct tick_device *td, | |||
194 | * When global broadcasting is active, check if the current | 194 | * When global broadcasting is active, check if the current |
195 | * device is registered as a placeholder for broadcast mode. | 195 | * device is registered as a placeholder for broadcast mode. |
196 | * This allows us to handle this x86 misfeature in a generic | 196 | * This allows us to handle this x86 misfeature in a generic |
197 | * way. | 197 | * way. This function also returns !=0 when we keep the |
198 | * current active broadcast state for this CPU. | ||
198 | */ | 199 | */ |
199 | if (tick_device_uses_broadcast(newdev, cpu)) | 200 | if (tick_device_uses_broadcast(newdev, cpu)) |
200 | return; | 201 | return; |
@@ -205,17 +206,75 @@ static void tick_setup_device(struct tick_device *td, | |||
205 | tick_setup_oneshot(newdev, handler, next_event); | 206 | tick_setup_oneshot(newdev, handler, next_event); |
206 | } | 207 | } |
207 | 208 | ||
209 | void tick_install_replacement(struct clock_event_device *newdev) | ||
210 | { | ||
211 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); | ||
212 | int cpu = smp_processor_id(); | ||
213 | |||
214 | clockevents_exchange_device(td->evtdev, newdev); | ||
215 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); | ||
216 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) | ||
217 | tick_oneshot_notify(); | ||
218 | } | ||
219 | |||
220 | static bool tick_check_percpu(struct clock_event_device *curdev, | ||
221 | struct clock_event_device *newdev, int cpu) | ||
222 | { | ||
223 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) | ||
224 | return false; | ||
225 | if (cpumask_equal(newdev->cpumask, cpumask_of(cpu))) | ||
226 | return true; | ||
227 | /* Check if irq affinity can be set */ | ||
228 | if (newdev->irq >= 0 && !irq_can_set_affinity(newdev->irq)) | ||
229 | return false; | ||
230 | /* Prefer an existing cpu local device */ | ||
231 | if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) | ||
232 | return false; | ||
233 | return true; | ||
234 | } | ||
235 | |||
236 | static bool tick_check_preferred(struct clock_event_device *curdev, | ||
237 | struct clock_event_device *newdev) | ||
238 | { | ||
239 | /* Prefer oneshot capable device */ | ||
240 | if (!(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) { | ||
241 | if (curdev && (curdev->features & CLOCK_EVT_FEAT_ONESHOT)) | ||
242 | return false; | ||
243 | if (tick_oneshot_mode_active()) | ||
244 | return false; | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Use the higher rated one, but prefer a CPU local device with a lower | ||
249 | * rating than a non-CPU local device | ||
250 | */ | ||
251 | return !curdev || | ||
252 | newdev->rating > curdev->rating || | ||
253 | !cpumask_equal(curdev->cpumask, newdev->cpumask); | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Check whether the new device is a better fit than curdev. curdev | ||
258 | * can be NULL ! | ||
259 | */ | ||
260 | bool tick_check_replacement(struct clock_event_device *curdev, | ||
261 | struct clock_event_device *newdev) | ||
262 | { | ||
263 | if (tick_check_percpu(curdev, newdev, smp_processor_id())) | ||
264 | return false; | ||
265 | |||
266 | return tick_check_preferred(curdev, newdev); | ||
267 | } | ||
268 | |||
208 | /* | 269 | /* |
209 | * Check, if the new registered device should be used. | 270 | * Check, if the new registered device should be used. Called with |
271 | * clockevents_lock held and interrupts disabled. | ||
210 | */ | 272 | */ |
211 | static int tick_check_new_device(struct clock_event_device *newdev) | 273 | void tick_check_new_device(struct clock_event_device *newdev) |
212 | { | 274 | { |
213 | struct clock_event_device *curdev; | 275 | struct clock_event_device *curdev; |
214 | struct tick_device *td; | 276 | struct tick_device *td; |
215 | int cpu, ret = NOTIFY_OK; | 277 | int cpu; |
216 | unsigned long flags; | ||
217 | |||
218 | raw_spin_lock_irqsave(&tick_device_lock, flags); | ||
219 | 278 | ||
220 | cpu = smp_processor_id(); | 279 | cpu = smp_processor_id(); |
221 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) | 280 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) |
@@ -225,40 +284,15 @@ static int tick_check_new_device(struct clock_event_device *newdev) | |||
225 | curdev = td->evtdev; | 284 | curdev = td->evtdev; |
226 | 285 | ||
227 | /* cpu local device ? */ | 286 | /* cpu local device ? */ |
228 | if (!cpumask_equal(newdev->cpumask, cpumask_of(cpu))) { | 287 | if (!tick_check_percpu(curdev, newdev, cpu)) |
229 | 288 | goto out_bc; | |
230 | /* | ||
231 | * If the cpu affinity of the device interrupt can not | ||
232 | * be set, ignore it. | ||
233 | */ | ||
234 | if (!irq_can_set_affinity(newdev->irq)) | ||
235 | goto out_bc; | ||
236 | 289 | ||
237 | /* | 290 | /* Preference decision */ |
238 | * If we have a cpu local device already, do not replace it | 291 | if (!tick_check_preferred(curdev, newdev)) |
239 | * by a non cpu local device | 292 | goto out_bc; |
240 | */ | ||
241 | if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) | ||
242 | goto out_bc; | ||
243 | } | ||
244 | 293 | ||
245 | /* | 294 | if (!try_module_get(newdev->owner)) |
246 | * If we have an active device, then check the rating and the oneshot | 295 | return; |
247 | * feature. | ||
248 | */ | ||
249 | if (curdev) { | ||
250 | /* | ||
251 | * Prefer one shot capable devices ! | ||
252 | */ | ||
253 | if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) && | ||
254 | !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) | ||
255 | goto out_bc; | ||
256 | /* | ||
257 | * Check the rating | ||
258 | */ | ||
259 | if (curdev->rating >= newdev->rating) | ||
260 | goto out_bc; | ||
261 | } | ||
262 | 296 | ||
263 | /* | 297 | /* |
264 | * Replace the eventually existing device by the new | 298 | * Replace the eventually existing device by the new |
@@ -273,20 +307,13 @@ static int tick_check_new_device(struct clock_event_device *newdev) | |||
273 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); | 307 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); |
274 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) | 308 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) |
275 | tick_oneshot_notify(); | 309 | tick_oneshot_notify(); |
276 | 310 | return; | |
277 | raw_spin_unlock_irqrestore(&tick_device_lock, flags); | ||
278 | return NOTIFY_STOP; | ||
279 | 311 | ||
280 | out_bc: | 312 | out_bc: |
281 | /* | 313 | /* |
282 | * Can the new device be used as a broadcast device ? | 314 | * Can the new device be used as a broadcast device ? |
283 | */ | 315 | */ |
284 | if (tick_check_broadcast_device(newdev)) | 316 | tick_install_broadcast_device(newdev); |
285 | ret = NOTIFY_STOP; | ||
286 | |||
287 | raw_spin_unlock_irqrestore(&tick_device_lock, flags); | ||
288 | |||
289 | return ret; | ||
290 | } | 317 | } |
291 | 318 | ||
292 | /* | 319 | /* |
@@ -294,7 +321,7 @@ out_bc: | |||
294 | * | 321 | * |
295 | * Called with interrupts disabled. | 322 | * Called with interrupts disabled. |
296 | */ | 323 | */ |
297 | static void tick_handover_do_timer(int *cpup) | 324 | void tick_handover_do_timer(int *cpup) |
298 | { | 325 | { |
299 | if (*cpup == tick_do_timer_cpu) { | 326 | if (*cpup == tick_do_timer_cpu) { |
300 | int cpu = cpumask_first(cpu_online_mask); | 327 | int cpu = cpumask_first(cpu_online_mask); |
@@ -311,13 +338,11 @@ static void tick_handover_do_timer(int *cpup) | |||
311 | * access the hardware device itself. | 338 | * access the hardware device itself. |
312 | * We just set the mode and remove it from the lists. | 339 | * We just set the mode and remove it from the lists. |
313 | */ | 340 | */ |
314 | static void tick_shutdown(unsigned int *cpup) | 341 | void tick_shutdown(unsigned int *cpup) |
315 | { | 342 | { |
316 | struct tick_device *td = &per_cpu(tick_cpu_device, *cpup); | 343 | struct tick_device *td = &per_cpu(tick_cpu_device, *cpup); |
317 | struct clock_event_device *dev = td->evtdev; | 344 | struct clock_event_device *dev = td->evtdev; |
318 | unsigned long flags; | ||
319 | 345 | ||
320 | raw_spin_lock_irqsave(&tick_device_lock, flags); | ||
321 | td->mode = TICKDEV_MODE_PERIODIC; | 346 | td->mode = TICKDEV_MODE_PERIODIC; |
322 | if (dev) { | 347 | if (dev) { |
323 | /* | 348 | /* |
@@ -329,26 +354,20 @@ static void tick_shutdown(unsigned int *cpup) | |||
329 | dev->event_handler = clockevents_handle_noop; | 354 | dev->event_handler = clockevents_handle_noop; |
330 | td->evtdev = NULL; | 355 | td->evtdev = NULL; |
331 | } | 356 | } |
332 | raw_spin_unlock_irqrestore(&tick_device_lock, flags); | ||
333 | } | 357 | } |
334 | 358 | ||
335 | static void tick_suspend(void) | 359 | void tick_suspend(void) |
336 | { | 360 | { |
337 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); | 361 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); |
338 | unsigned long flags; | ||
339 | 362 | ||
340 | raw_spin_lock_irqsave(&tick_device_lock, flags); | ||
341 | clockevents_shutdown(td->evtdev); | 363 | clockevents_shutdown(td->evtdev); |
342 | raw_spin_unlock_irqrestore(&tick_device_lock, flags); | ||
343 | } | 364 | } |
344 | 365 | ||
345 | static void tick_resume(void) | 366 | void tick_resume(void) |
346 | { | 367 | { |
347 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); | 368 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); |
348 | unsigned long flags; | ||
349 | int broadcast = tick_resume_broadcast(); | 369 | int broadcast = tick_resume_broadcast(); |
350 | 370 | ||
351 | raw_spin_lock_irqsave(&tick_device_lock, flags); | ||
352 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME); | 371 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME); |
353 | 372 | ||
354 | if (!broadcast) { | 373 | if (!broadcast) { |
@@ -357,68 +376,12 @@ static void tick_resume(void) | |||
357 | else | 376 | else |
358 | tick_resume_oneshot(); | 377 | tick_resume_oneshot(); |
359 | } | 378 | } |
360 | raw_spin_unlock_irqrestore(&tick_device_lock, flags); | ||
361 | } | 379 | } |
362 | 380 | ||
363 | /* | ||
364 | * Notification about clock event devices | ||
365 | */ | ||
366 | static int tick_notify(struct notifier_block *nb, unsigned long reason, | ||
367 | void *dev) | ||
368 | { | ||
369 | switch (reason) { | ||
370 | |||
371 | case CLOCK_EVT_NOTIFY_ADD: | ||
372 | return tick_check_new_device(dev); | ||
373 | |||
374 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | ||
375 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | ||
376 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | ||
377 | tick_broadcast_on_off(reason, dev); | ||
378 | break; | ||
379 | |||
380 | case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: | ||
381 | case CLOCK_EVT_NOTIFY_BROADCAST_EXIT: | ||
382 | tick_broadcast_oneshot_control(reason); | ||
383 | break; | ||
384 | |||
385 | case CLOCK_EVT_NOTIFY_CPU_DYING: | ||
386 | tick_handover_do_timer(dev); | ||
387 | break; | ||
388 | |||
389 | case CLOCK_EVT_NOTIFY_CPU_DEAD: | ||
390 | tick_shutdown_broadcast_oneshot(dev); | ||
391 | tick_shutdown_broadcast(dev); | ||
392 | tick_shutdown(dev); | ||
393 | break; | ||
394 | |||
395 | case CLOCK_EVT_NOTIFY_SUSPEND: | ||
396 | tick_suspend(); | ||
397 | tick_suspend_broadcast(); | ||
398 | break; | ||
399 | |||
400 | case CLOCK_EVT_NOTIFY_RESUME: | ||
401 | tick_resume(); | ||
402 | break; | ||
403 | |||
404 | default: | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | return NOTIFY_OK; | ||
409 | } | ||
410 | |||
411 | static struct notifier_block tick_notifier = { | ||
412 | .notifier_call = tick_notify, | ||
413 | }; | ||
414 | |||
415 | /** | 381 | /** |
416 | * tick_init - initialize the tick control | 382 | * tick_init - initialize the tick control |
417 | * | ||
418 | * Register the notifier with the clockevents framework | ||
419 | */ | 383 | */ |
420 | void __init tick_init(void) | 384 | void __init tick_init(void) |
421 | { | 385 | { |
422 | clockevents_register_notifier(&tick_notifier); | ||
423 | tick_broadcast_init(); | 386 | tick_broadcast_init(); |
424 | } | 387 | } |
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index f0299eae4602..bc906cad709b 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | extern seqlock_t jiffies_lock; | 7 | extern seqlock_t jiffies_lock; |
8 | 8 | ||
9 | #define CS_NAME_LEN 32 | ||
10 | |||
9 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD | 11 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD |
10 | 12 | ||
11 | #define TICK_DO_TIMER_NONE -1 | 13 | #define TICK_DO_TIMER_NONE -1 |
@@ -18,9 +20,19 @@ extern int tick_do_timer_cpu __read_mostly; | |||
18 | 20 | ||
19 | extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); | 21 | extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); |
20 | extern void tick_handle_periodic(struct clock_event_device *dev); | 22 | extern void tick_handle_periodic(struct clock_event_device *dev); |
23 | extern void tick_check_new_device(struct clock_event_device *dev); | ||
24 | extern void tick_handover_do_timer(int *cpup); | ||
25 | extern void tick_shutdown(unsigned int *cpup); | ||
26 | extern void tick_suspend(void); | ||
27 | extern void tick_resume(void); | ||
28 | extern bool tick_check_replacement(struct clock_event_device *curdev, | ||
29 | struct clock_event_device *newdev); | ||
30 | extern void tick_install_replacement(struct clock_event_device *dev); | ||
21 | 31 | ||
22 | extern void clockevents_shutdown(struct clock_event_device *dev); | 32 | extern void clockevents_shutdown(struct clock_event_device *dev); |
23 | 33 | ||
34 | extern size_t sysfs_get_uname(const char *buf, char *dst, size_t cnt); | ||
35 | |||
24 | /* | 36 | /* |
25 | * NO_HZ / high resolution timer shared code | 37 | * NO_HZ / high resolution timer shared code |
26 | */ | 38 | */ |
@@ -90,7 +102,7 @@ static inline bool tick_broadcast_oneshot_available(void) { return false; } | |||
90 | */ | 102 | */ |
91 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 103 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
92 | extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu); | 104 | extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu); |
93 | extern int tick_check_broadcast_device(struct clock_event_device *dev); | 105 | extern void tick_install_broadcast_device(struct clock_event_device *dev); |
94 | extern int tick_is_broadcast_device(struct clock_event_device *dev); | 106 | extern int tick_is_broadcast_device(struct clock_event_device *dev); |
95 | extern void tick_broadcast_on_off(unsigned long reason, int *oncpu); | 107 | extern void tick_broadcast_on_off(unsigned long reason, int *oncpu); |
96 | extern void tick_shutdown_broadcast(unsigned int *cpup); | 108 | extern void tick_shutdown_broadcast(unsigned int *cpup); |
@@ -102,9 +114,8 @@ tick_set_periodic_handler(struct clock_event_device *dev, int broadcast); | |||
102 | 114 | ||
103 | #else /* !BROADCAST */ | 115 | #else /* !BROADCAST */ |
104 | 116 | ||
105 | static inline int tick_check_broadcast_device(struct clock_event_device *dev) | 117 | static inline void tick_install_broadcast_device(struct clock_event_device *dev) |
106 | { | 118 | { |
107 | return 0; | ||
108 | } | 119 | } |
109 | 120 | ||
110 | static inline int tick_is_broadcast_device(struct clock_event_device *dev) | 121 | static inline int tick_is_broadcast_device(struct clock_event_device *dev) |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index baeeb5c87cf1..48b9fffabdc2 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -25,6 +25,11 @@ | |||
25 | 25 | ||
26 | #include "tick-internal.h" | 26 | #include "tick-internal.h" |
27 | #include "ntp_internal.h" | 27 | #include "ntp_internal.h" |
28 | #include "timekeeping_internal.h" | ||
29 | |||
30 | #define TK_CLEAR_NTP (1 << 0) | ||
31 | #define TK_MIRROR (1 << 1) | ||
32 | #define TK_CLOCK_WAS_SET (1 << 2) | ||
28 | 33 | ||
29 | static struct timekeeper timekeeper; | 34 | static struct timekeeper timekeeper; |
30 | static DEFINE_RAW_SPINLOCK(timekeeper_lock); | 35 | static DEFINE_RAW_SPINLOCK(timekeeper_lock); |
@@ -200,9 +205,9 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | |||
200 | 205 | ||
201 | static RAW_NOTIFIER_HEAD(pvclock_gtod_chain); | 206 | static RAW_NOTIFIER_HEAD(pvclock_gtod_chain); |
202 | 207 | ||
203 | static void update_pvclock_gtod(struct timekeeper *tk) | 208 | static void update_pvclock_gtod(struct timekeeper *tk, bool was_set) |
204 | { | 209 | { |
205 | raw_notifier_call_chain(&pvclock_gtod_chain, 0, tk); | 210 | raw_notifier_call_chain(&pvclock_gtod_chain, was_set, tk); |
206 | } | 211 | } |
207 | 212 | ||
208 | /** | 213 | /** |
@@ -216,7 +221,7 @@ int pvclock_gtod_register_notifier(struct notifier_block *nb) | |||
216 | 221 | ||
217 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 222 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
218 | ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb); | 223 | ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb); |
219 | update_pvclock_gtod(tk); | 224 | update_pvclock_gtod(tk, true); |
220 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 225 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
221 | 226 | ||
222 | return ret; | 227 | return ret; |
@@ -241,16 +246,16 @@ int pvclock_gtod_unregister_notifier(struct notifier_block *nb) | |||
241 | EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier); | 246 | EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier); |
242 | 247 | ||
243 | /* must hold timekeeper_lock */ | 248 | /* must hold timekeeper_lock */ |
244 | static void timekeeping_update(struct timekeeper *tk, bool clearntp, bool mirror) | 249 | static void timekeeping_update(struct timekeeper *tk, unsigned int action) |
245 | { | 250 | { |
246 | if (clearntp) { | 251 | if (action & TK_CLEAR_NTP) { |
247 | tk->ntp_error = 0; | 252 | tk->ntp_error = 0; |
248 | ntp_clear(); | 253 | ntp_clear(); |
249 | } | 254 | } |
250 | update_vsyscall(tk); | 255 | update_vsyscall(tk); |
251 | update_pvclock_gtod(tk); | 256 | update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET); |
252 | 257 | ||
253 | if (mirror) | 258 | if (action & TK_MIRROR) |
254 | memcpy(&shadow_timekeeper, &timekeeper, sizeof(timekeeper)); | 259 | memcpy(&shadow_timekeeper, &timekeeper, sizeof(timekeeper)); |
255 | } | 260 | } |
256 | 261 | ||
@@ -508,7 +513,7 @@ int do_settimeofday(const struct timespec *tv) | |||
508 | 513 | ||
509 | tk_set_xtime(tk, tv); | 514 | tk_set_xtime(tk, tv); |
510 | 515 | ||
511 | timekeeping_update(tk, true, true); | 516 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); |
512 | 517 | ||
513 | write_seqcount_end(&timekeeper_seq); | 518 | write_seqcount_end(&timekeeper_seq); |
514 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 519 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
@@ -552,7 +557,7 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
552 | tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); | 557 | tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); |
553 | 558 | ||
554 | error: /* even if we error out, we forwarded the time, so call update */ | 559 | error: /* even if we error out, we forwarded the time, so call update */ |
555 | timekeeping_update(tk, true, true); | 560 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); |
556 | 561 | ||
557 | write_seqcount_end(&timekeeper_seq); | 562 | write_seqcount_end(&timekeeper_seq); |
558 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 563 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
@@ -627,13 +632,22 @@ static int change_clocksource(void *data) | |||
627 | write_seqcount_begin(&timekeeper_seq); | 632 | write_seqcount_begin(&timekeeper_seq); |
628 | 633 | ||
629 | timekeeping_forward_now(tk); | 634 | timekeeping_forward_now(tk); |
630 | if (!new->enable || new->enable(new) == 0) { | 635 | /* |
631 | old = tk->clock; | 636 | * If the cs is in module, get a module reference. Succeeds |
632 | tk_setup_internals(tk, new); | 637 | * for built-in code (owner == NULL) as well. |
633 | if (old->disable) | 638 | */ |
634 | old->disable(old); | 639 | if (try_module_get(new->owner)) { |
640 | if (!new->enable || new->enable(new) == 0) { | ||
641 | old = tk->clock; | ||
642 | tk_setup_internals(tk, new); | ||
643 | if (old->disable) | ||
644 | old->disable(old); | ||
645 | module_put(old->owner); | ||
646 | } else { | ||
647 | module_put(new->owner); | ||
648 | } | ||
635 | } | 649 | } |
636 | timekeeping_update(tk, true, true); | 650 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); |
637 | 651 | ||
638 | write_seqcount_end(&timekeeper_seq); | 652 | write_seqcount_end(&timekeeper_seq); |
639 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 653 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
@@ -648,14 +662,15 @@ static int change_clocksource(void *data) | |||
648 | * This function is called from clocksource.c after a new, better clock | 662 | * This function is called from clocksource.c after a new, better clock |
649 | * source has been registered. The caller holds the clocksource_mutex. | 663 | * source has been registered. The caller holds the clocksource_mutex. |
650 | */ | 664 | */ |
651 | void timekeeping_notify(struct clocksource *clock) | 665 | int timekeeping_notify(struct clocksource *clock) |
652 | { | 666 | { |
653 | struct timekeeper *tk = &timekeeper; | 667 | struct timekeeper *tk = &timekeeper; |
654 | 668 | ||
655 | if (tk->clock == clock) | 669 | if (tk->clock == clock) |
656 | return; | 670 | return 0; |
657 | stop_machine(change_clocksource, clock, NULL); | 671 | stop_machine(change_clocksource, clock, NULL); |
658 | tick_clock_notify(); | 672 | tick_clock_notify(); |
673 | return tk->clock == clock ? 0 : -1; | ||
659 | } | 674 | } |
660 | 675 | ||
661 | /** | 676 | /** |
@@ -841,6 +856,7 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, | |||
841 | tk_xtime_add(tk, delta); | 856 | tk_xtime_add(tk, delta); |
842 | tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *delta)); | 857 | tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *delta)); |
843 | tk_set_sleep_time(tk, timespec_add(tk->total_sleep_time, *delta)); | 858 | tk_set_sleep_time(tk, timespec_add(tk->total_sleep_time, *delta)); |
859 | tk_debug_account_sleep_time(delta); | ||
844 | } | 860 | } |
845 | 861 | ||
846 | /** | 862 | /** |
@@ -872,7 +888,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta) | |||
872 | 888 | ||
873 | __timekeeping_inject_sleeptime(tk, delta); | 889 | __timekeeping_inject_sleeptime(tk, delta); |
874 | 890 | ||
875 | timekeeping_update(tk, true, true); | 891 | timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); |
876 | 892 | ||
877 | write_seqcount_end(&timekeeper_seq); | 893 | write_seqcount_end(&timekeeper_seq); |
878 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 894 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
@@ -954,7 +970,7 @@ static void timekeeping_resume(void) | |||
954 | tk->cycle_last = clock->cycle_last = cycle_now; | 970 | tk->cycle_last = clock->cycle_last = cycle_now; |
955 | tk->ntp_error = 0; | 971 | tk->ntp_error = 0; |
956 | timekeeping_suspended = 0; | 972 | timekeeping_suspended = 0; |
957 | timekeeping_update(tk, false, true); | 973 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); |
958 | write_seqcount_end(&timekeeper_seq); | 974 | write_seqcount_end(&timekeeper_seq); |
959 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 975 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
960 | 976 | ||
@@ -1236,9 +1252,10 @@ out_adjust: | |||
1236 | * It also calls into the NTP code to handle leapsecond processing. | 1252 | * It also calls into the NTP code to handle leapsecond processing. |
1237 | * | 1253 | * |
1238 | */ | 1254 | */ |
1239 | static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) | 1255 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) |
1240 | { | 1256 | { |
1241 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; | 1257 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; |
1258 | unsigned int action = 0; | ||
1242 | 1259 | ||
1243 | while (tk->xtime_nsec >= nsecps) { | 1260 | while (tk->xtime_nsec >= nsecps) { |
1244 | int leap; | 1261 | int leap; |
@@ -1261,8 +1278,10 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
1261 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); | 1278 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); |
1262 | 1279 | ||
1263 | clock_was_set_delayed(); | 1280 | clock_was_set_delayed(); |
1281 | action = TK_CLOCK_WAS_SET; | ||
1264 | } | 1282 | } |
1265 | } | 1283 | } |
1284 | return action; | ||
1266 | } | 1285 | } |
1267 | 1286 | ||
1268 | /** | 1287 | /** |
@@ -1347,6 +1366,7 @@ static void update_wall_time(void) | |||
1347 | struct timekeeper *tk = &shadow_timekeeper; | 1366 | struct timekeeper *tk = &shadow_timekeeper; |
1348 | cycle_t offset; | 1367 | cycle_t offset; |
1349 | int shift = 0, maxshift; | 1368 | int shift = 0, maxshift; |
1369 | unsigned int action; | ||
1350 | unsigned long flags; | 1370 | unsigned long flags; |
1351 | 1371 | ||
1352 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 1372 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
@@ -1399,7 +1419,7 @@ static void update_wall_time(void) | |||
1399 | * Finally, make sure that after the rounding | 1419 | * Finally, make sure that after the rounding |
1400 | * xtime_nsec isn't larger than NSEC_PER_SEC | 1420 | * xtime_nsec isn't larger than NSEC_PER_SEC |
1401 | */ | 1421 | */ |
1402 | accumulate_nsecs_to_secs(tk); | 1422 | action = accumulate_nsecs_to_secs(tk); |
1403 | 1423 | ||
1404 | write_seqcount_begin(&timekeeper_seq); | 1424 | write_seqcount_begin(&timekeeper_seq); |
1405 | /* Update clock->cycle_last with the new value */ | 1425 | /* Update clock->cycle_last with the new value */ |
@@ -1415,7 +1435,7 @@ static void update_wall_time(void) | |||
1415 | * updating. | 1435 | * updating. |
1416 | */ | 1436 | */ |
1417 | memcpy(real_tk, tk, sizeof(*tk)); | 1437 | memcpy(real_tk, tk, sizeof(*tk)); |
1418 | timekeeping_update(real_tk, false, false); | 1438 | timekeeping_update(real_tk, action); |
1419 | write_seqcount_end(&timekeeper_seq); | 1439 | write_seqcount_end(&timekeeper_seq); |
1420 | out: | 1440 | out: |
1421 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1441 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
@@ -1677,6 +1697,7 @@ int do_adjtimex(struct timex *txc) | |||
1677 | 1697 | ||
1678 | if (tai != orig_tai) { | 1698 | if (tai != orig_tai) { |
1679 | __timekeeping_set_tai_offset(tk, tai); | 1699 | __timekeeping_set_tai_offset(tk, tai); |
1700 | update_pvclock_gtod(tk, true); | ||
1680 | clock_was_set_delayed(); | 1701 | clock_was_set_delayed(); |
1681 | } | 1702 | } |
1682 | write_seqcount_end(&timekeeper_seq); | 1703 | write_seqcount_end(&timekeeper_seq); |
diff --git a/kernel/time/timekeeping_debug.c b/kernel/time/timekeeping_debug.c new file mode 100644 index 000000000000..802433a4f5eb --- /dev/null +++ b/kernel/time/timekeeping_debug.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * debugfs file to track time spent in suspend | ||
3 | * | ||
4 | * Copyright (c) 2011, Google, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/debugfs.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/time.h> | ||
23 | |||
24 | static unsigned int sleep_time_bin[32] = {0}; | ||
25 | |||
26 | static int tk_debug_show_sleep_time(struct seq_file *s, void *data) | ||
27 | { | ||
28 | unsigned int bin; | ||
29 | seq_puts(s, " time (secs) count\n"); | ||
30 | seq_puts(s, "------------------------------\n"); | ||
31 | for (bin = 0; bin < 32; bin++) { | ||
32 | if (sleep_time_bin[bin] == 0) | ||
33 | continue; | ||
34 | seq_printf(s, "%10u - %-10u %4u\n", | ||
35 | bin ? 1 << (bin - 1) : 0, 1 << bin, | ||
36 | sleep_time_bin[bin]); | ||
37 | } | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static int tk_debug_sleep_time_open(struct inode *inode, struct file *file) | ||
42 | { | ||
43 | return single_open(file, tk_debug_show_sleep_time, NULL); | ||
44 | } | ||
45 | |||
46 | static const struct file_operations tk_debug_sleep_time_fops = { | ||
47 | .open = tk_debug_sleep_time_open, | ||
48 | .read = seq_read, | ||
49 | .llseek = seq_lseek, | ||
50 | .release = single_release, | ||
51 | }; | ||
52 | |||
53 | static int __init tk_debug_sleep_time_init(void) | ||
54 | { | ||
55 | struct dentry *d; | ||
56 | |||
57 | d = debugfs_create_file("sleep_time", 0444, NULL, NULL, | ||
58 | &tk_debug_sleep_time_fops); | ||
59 | if (!d) { | ||
60 | pr_err("Failed to create sleep_time debug file\n"); | ||
61 | return -ENOMEM; | ||
62 | } | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | late_initcall(tk_debug_sleep_time_init); | ||
67 | |||
68 | void tk_debug_account_sleep_time(struct timespec *t) | ||
69 | { | ||
70 | sleep_time_bin[fls(t->tv_sec)]++; | ||
71 | } | ||
72 | |||
diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h new file mode 100644 index 000000000000..13323ea08ffa --- /dev/null +++ b/kernel/time/timekeeping_internal.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _TIMEKEEPING_INTERNAL_H | ||
2 | #define _TIMEKEEPING_INTERNAL_H | ||
3 | /* | ||
4 | * timekeeping debug functions | ||
5 | */ | ||
6 | #include <linux/time.h> | ||
7 | |||
8 | #ifdef CONFIG_DEBUG_FS | ||
9 | extern void tk_debug_account_sleep_time(struct timespec *t); | ||
10 | #else | ||
11 | #define tk_debug_account_sleep_time(x) | ||
12 | #endif | ||
13 | |||
14 | #endif /* _TIMEKEEPING_INTERNAL_H */ | ||
diff --git a/kernel/timer.c b/kernel/timer.c index 15ffdb3f1948..15bc1b41021d 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -149,9 +149,11 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu, | |||
149 | /* now that we have rounded, subtract the extra skew again */ | 149 | /* now that we have rounded, subtract the extra skew again */ |
150 | j -= cpu * 3; | 150 | j -= cpu * 3; |
151 | 151 | ||
152 | if (j <= jiffies) /* rounding ate our timeout entirely; */ | 152 | /* |
153 | return original; | 153 | * Make sure j is still in the future. Otherwise return the |
154 | return j; | 154 | * unmodified value. |
155 | */ | ||
156 | return time_is_after_jiffies(j) ? j : original; | ||
155 | } | 157 | } |
156 | 158 | ||
157 | /** | 159 | /** |
diff --git a/lib/Kconfig b/lib/Kconfig index 5a5203ded0dd..f1ed53c3aa44 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -66,6 +66,8 @@ config CRC16 | |||
66 | 66 | ||
67 | config CRC_T10DIF | 67 | config CRC_T10DIF |
68 | tristate "CRC calculation for the T10 Data Integrity Field" | 68 | tristate "CRC calculation for the T10 Data Integrity Field" |
69 | select CRYPTO | ||
70 | select CRYPTO_CRCT10DIF | ||
69 | help | 71 | help |
70 | This option is only needed if a module that's not in the | 72 | This option is only needed if a module that's not in the |
71 | kernel tree needs to calculate CRC checks for use with the | 73 | kernel tree needs to calculate CRC checks for use with the |
diff --git a/lib/crc-t10dif.c b/lib/crc-t10dif.c index fbbd66ed86cd..fe3428c07b47 100644 --- a/lib/crc-t10dif.c +++ b/lib/crc-t10dif.c | |||
@@ -11,57 +11,44 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/crc-t10dif.h> | 13 | #include <linux/crc-t10dif.h> |
14 | #include <linux/err.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <crypto/hash.h> | ||
14 | 17 | ||
15 | /* Table generated using the following polynomium: | 18 | static struct crypto_shash *crct10dif_tfm; |
16 | * x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 | ||
17 | * gt: 0x8bb7 | ||
18 | */ | ||
19 | static const __u16 t10_dif_crc_table[256] = { | ||
20 | 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, | ||
21 | 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, | ||
22 | 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, | ||
23 | 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, | ||
24 | 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, | ||
25 | 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, | ||
26 | 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, | ||
27 | 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, | ||
28 | 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, | ||
29 | 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, | ||
30 | 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, | ||
31 | 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, | ||
32 | 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, | ||
33 | 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, | ||
34 | 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, | ||
35 | 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, | ||
36 | 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, | ||
37 | 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, | ||
38 | 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, | ||
39 | 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, | ||
40 | 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, | ||
41 | 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, | ||
42 | 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, | ||
43 | 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, | ||
44 | 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, | ||
45 | 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, | ||
46 | 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, | ||
47 | 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, | ||
48 | 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, | ||
49 | 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, | ||
50 | 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, | ||
51 | 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 | ||
52 | }; | ||
53 | 19 | ||
54 | __u16 crc_t10dif(const unsigned char *buffer, size_t len) | 20 | __u16 crc_t10dif(const unsigned char *buffer, size_t len) |
55 | { | 21 | { |
56 | __u16 crc = 0; | 22 | struct { |
57 | unsigned int i; | 23 | struct shash_desc shash; |
24 | char ctx[2]; | ||
25 | } desc; | ||
26 | int err; | ||
27 | |||
28 | desc.shash.tfm = crct10dif_tfm; | ||
29 | desc.shash.flags = 0; | ||
30 | *(__u16 *)desc.ctx = 0; | ||
58 | 31 | ||
59 | for (i = 0 ; i < len ; i++) | 32 | err = crypto_shash_update(&desc.shash, buffer, len); |
60 | crc = (crc << 8) ^ t10_dif_crc_table[((crc >> 8) ^ buffer[i]) & 0xff]; | 33 | BUG_ON(err); |
61 | 34 | ||
62 | return crc; | 35 | return *(__u16 *)desc.ctx; |
63 | } | 36 | } |
64 | EXPORT_SYMBOL(crc_t10dif); | 37 | EXPORT_SYMBOL(crc_t10dif); |
65 | 38 | ||
39 | static int __init crc_t10dif_mod_init(void) | ||
40 | { | ||
41 | crct10dif_tfm = crypto_alloc_shash("crct10dif", 0, 0); | ||
42 | return PTR_RET(crct10dif_tfm); | ||
43 | } | ||
44 | |||
45 | static void __exit crc_t10dif_mod_fini(void) | ||
46 | { | ||
47 | crypto_free_shash(crct10dif_tfm); | ||
48 | } | ||
49 | |||
50 | module_init(crc_t10dif_mod_init); | ||
51 | module_exit(crc_t10dif_mod_fini); | ||
52 | |||
66 | MODULE_DESCRIPTION("T10 DIF CRC calculation"); | 53 | MODULE_DESCRIPTION("T10 DIF CRC calculation"); |
67 | MODULE_LICENSE("GPL"); | 54 | MODULE_LICENSE("GPL"); |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3d155dd27eb6..62164348ecf7 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -861,24 +861,23 @@ static void check_section(const char *modname, struct elf_info *elf, | |||
861 | 861 | ||
862 | 862 | ||
863 | #define ALL_INIT_DATA_SECTIONS \ | 863 | #define ALL_INIT_DATA_SECTIONS \ |
864 | ".init.setup$", ".init.rodata$", \ | 864 | ".init.setup$", ".init.rodata$", ".meminit.rodata$", \ |
865 | ".cpuinit.rodata$", ".meminit.rodata$", \ | 865 | ".init.data$", ".meminit.data$" |
866 | ".init.data$", ".cpuinit.data$", ".meminit.data$" | ||
867 | #define ALL_EXIT_DATA_SECTIONS \ | 866 | #define ALL_EXIT_DATA_SECTIONS \ |
868 | ".exit.data$", ".cpuexit.data$", ".memexit.data$" | 867 | ".exit.data$", ".memexit.data$" |
869 | 868 | ||
870 | #define ALL_INIT_TEXT_SECTIONS \ | 869 | #define ALL_INIT_TEXT_SECTIONS \ |
871 | ".init.text$", ".cpuinit.text$", ".meminit.text$" | 870 | ".init.text$", ".meminit.text$" |
872 | #define ALL_EXIT_TEXT_SECTIONS \ | 871 | #define ALL_EXIT_TEXT_SECTIONS \ |
873 | ".exit.text$", ".cpuexit.text$", ".memexit.text$" | 872 | ".exit.text$", ".memexit.text$" |
874 | 873 | ||
875 | #define ALL_PCI_INIT_SECTIONS \ | 874 | #define ALL_PCI_INIT_SECTIONS \ |
876 | ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ | 875 | ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ |
877 | ".pci_fixup_enable$", ".pci_fixup_resume$", \ | 876 | ".pci_fixup_enable$", ".pci_fixup_resume$", \ |
878 | ".pci_fixup_resume_early$", ".pci_fixup_suspend$" | 877 | ".pci_fixup_resume_early$", ".pci_fixup_suspend$" |
879 | 878 | ||
880 | #define ALL_XXXINIT_SECTIONS CPU_INIT_SECTIONS, MEM_INIT_SECTIONS | 879 | #define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS |
881 | #define ALL_XXXEXIT_SECTIONS CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS | 880 | #define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS |
882 | 881 | ||
883 | #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS | 882 | #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS |
884 | #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS | 883 | #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS |
@@ -887,11 +886,9 @@ static void check_section(const char *modname, struct elf_info *elf, | |||
887 | #define TEXT_SECTIONS ".text$", ".text.unlikely$" | 886 | #define TEXT_SECTIONS ".text$", ".text.unlikely$" |
888 | 887 | ||
889 | #define INIT_SECTIONS ".init.*" | 888 | #define INIT_SECTIONS ".init.*" |
890 | #define CPU_INIT_SECTIONS ".cpuinit.*" | ||
891 | #define MEM_INIT_SECTIONS ".meminit.*" | 889 | #define MEM_INIT_SECTIONS ".meminit.*" |
892 | 890 | ||
893 | #define EXIT_SECTIONS ".exit.*" | 891 | #define EXIT_SECTIONS ".exit.*" |
894 | #define CPU_EXIT_SECTIONS ".cpuexit.*" | ||
895 | #define MEM_EXIT_SECTIONS ".memexit.*" | 892 | #define MEM_EXIT_SECTIONS ".memexit.*" |
896 | 893 | ||
897 | /* init data sections */ | 894 | /* init data sections */ |
@@ -979,48 +976,20 @@ const struct sectioncheck sectioncheck[] = { | |||
979 | .mismatch = DATA_TO_ANY_EXIT, | 976 | .mismatch = DATA_TO_ANY_EXIT, |
980 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | 977 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
981 | }, | 978 | }, |
982 | /* Do not reference init code/data from cpuinit/meminit code/data */ | 979 | /* Do not reference init code/data from meminit code/data */ |
983 | { | 980 | { |
984 | .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, | 981 | .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, |
985 | .tosec = { INIT_SECTIONS, NULL }, | 982 | .tosec = { INIT_SECTIONS, NULL }, |
986 | .mismatch = XXXINIT_TO_SOME_INIT, | 983 | .mismatch = XXXINIT_TO_SOME_INIT, |
987 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | 984 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
988 | }, | 985 | }, |
989 | /* Do not reference cpuinit code/data from meminit code/data */ | 986 | /* Do not reference exit code/data from memexit code/data */ |
990 | { | ||
991 | .fromsec = { MEM_INIT_SECTIONS, NULL }, | ||
992 | .tosec = { CPU_INIT_SECTIONS, NULL }, | ||
993 | .mismatch = XXXINIT_TO_SOME_INIT, | ||
994 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | ||
995 | }, | ||
996 | /* Do not reference meminit code/data from cpuinit code/data */ | ||
997 | { | ||
998 | .fromsec = { CPU_INIT_SECTIONS, NULL }, | ||
999 | .tosec = { MEM_INIT_SECTIONS, NULL }, | ||
1000 | .mismatch = XXXINIT_TO_SOME_INIT, | ||
1001 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | ||
1002 | }, | ||
1003 | /* Do not reference exit code/data from cpuexit/memexit code/data */ | ||
1004 | { | 987 | { |
1005 | .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, | 988 | .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, |
1006 | .tosec = { EXIT_SECTIONS, NULL }, | 989 | .tosec = { EXIT_SECTIONS, NULL }, |
1007 | .mismatch = XXXEXIT_TO_SOME_EXIT, | 990 | .mismatch = XXXEXIT_TO_SOME_EXIT, |
1008 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | 991 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
1009 | }, | 992 | }, |
1010 | /* Do not reference cpuexit code/data from memexit code/data */ | ||
1011 | { | ||
1012 | .fromsec = { MEM_EXIT_SECTIONS, NULL }, | ||
1013 | .tosec = { CPU_EXIT_SECTIONS, NULL }, | ||
1014 | .mismatch = XXXEXIT_TO_SOME_EXIT, | ||
1015 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | ||
1016 | }, | ||
1017 | /* Do not reference memexit code/data from cpuexit code/data */ | ||
1018 | { | ||
1019 | .fromsec = { CPU_EXIT_SECTIONS, NULL }, | ||
1020 | .tosec = { MEM_EXIT_SECTIONS, NULL }, | ||
1021 | .mismatch = XXXEXIT_TO_SOME_EXIT, | ||
1022 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | ||
1023 | }, | ||
1024 | /* Do not use exit code/data from init code */ | 993 | /* Do not use exit code/data from init code */ |
1025 | { | 994 | { |
1026 | .fromsec = { ALL_INIT_SECTIONS, NULL }, | 995 | .fromsec = { ALL_INIT_SECTIONS, NULL }, |
@@ -1089,8 +1058,6 @@ static const struct sectioncheck *section_mismatch( | |||
1089 | * Pattern 2: | 1058 | * Pattern 2: |
1090 | * Many drivers utilise a *driver container with references to | 1059 | * Many drivers utilise a *driver container with references to |
1091 | * add, remove, probe functions etc. | 1060 | * add, remove, probe functions etc. |
1092 | * These functions may often be marked __cpuinit and we do not want to | ||
1093 | * warn here. | ||
1094 | * the pattern is identified by: | 1061 | * the pattern is identified by: |
1095 | * tosec = init or exit section | 1062 | * tosec = init or exit section |
1096 | * fromsec = data section | 1063 | * fromsec = data section |
@@ -1249,7 +1216,6 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, | |||
1249 | /* | 1216 | /* |
1250 | * Convert a section name to the function/data attribute | 1217 | * Convert a section name to the function/data attribute |
1251 | * .init.text => __init | 1218 | * .init.text => __init |
1252 | * .cpuinit.data => __cpudata | ||
1253 | * .memexitconst => __memconst | 1219 | * .memexitconst => __memconst |
1254 | * etc. | 1220 | * etc. |
1255 | * | 1221 | * |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 0a63658065f0..4cb14cae3791 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -6,6 +6,7 @@ TARGETS += memory-hotplug | |||
6 | TARGETS += mqueue | 6 | TARGETS += mqueue |
7 | TARGETS += net | 7 | TARGETS += net |
8 | TARGETS += ptrace | 8 | TARGETS += ptrace |
9 | TARGETS += timers | ||
9 | TARGETS += vm | 10 | TARGETS += vm |
10 | 11 | ||
11 | all: | 12 | all: |
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile new file mode 100644 index 000000000000..eb2859f4ad21 --- /dev/null +++ b/tools/testing/selftests/timers/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | all: | ||
2 | gcc posix_timers.c -o posix_timers -lrt | ||
3 | |||
4 | run_tests: all | ||
5 | ./posix_timers | ||
6 | |||
7 | clean: | ||
8 | rm -f ./posix_timers | ||
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c new file mode 100644 index 000000000000..4fa655d68a81 --- /dev/null +++ b/tools/testing/selftests/timers/posix_timers.c | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com> | ||
3 | * | ||
4 | * Licensed under the terms of the GNU GPL License version 2 | ||
5 | * | ||
6 | * Selftests for a few posix timers interface. | ||
7 | * | ||
8 | * Kernel loop code stolen from Steven Rostedt <srostedt@redhat.com> | ||
9 | */ | ||
10 | |||
11 | #include <sys/time.h> | ||
12 | #include <stdio.h> | ||
13 | #include <signal.h> | ||
14 | #include <unistd.h> | ||
15 | #include <time.h> | ||
16 | #include <pthread.h> | ||
17 | |||
18 | #define DELAY 2 | ||
19 | #define USECS_PER_SEC 1000000 | ||
20 | |||
21 | static volatile int done; | ||
22 | |||
23 | /* Busy loop in userspace to elapse ITIMER_VIRTUAL */ | ||
24 | static void user_loop(void) | ||
25 | { | ||
26 | while (!done); | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Try to spend as much time as possible in kernelspace | ||
31 | * to elapse ITIMER_PROF. | ||
32 | */ | ||
33 | static void kernel_loop(void) | ||
34 | { | ||
35 | void *addr = sbrk(0); | ||
36 | |||
37 | while (!done) { | ||
38 | brk(addr + 4096); | ||
39 | brk(addr); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Sleep until ITIMER_REAL expiration. | ||
45 | */ | ||
46 | static void idle_loop(void) | ||
47 | { | ||
48 | pause(); | ||
49 | } | ||
50 | |||
51 | static void sig_handler(int nr) | ||
52 | { | ||
53 | done = 1; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Check the expected timer expiration matches the GTOD elapsed delta since | ||
58 | * we armed the timer. Keep a 0.5 sec error margin due to various jitter. | ||
59 | */ | ||
60 | static int check_diff(struct timeval start, struct timeval end) | ||
61 | { | ||
62 | long long diff; | ||
63 | |||
64 | diff = end.tv_usec - start.tv_usec; | ||
65 | diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC; | ||
66 | |||
67 | if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { | ||
68 | printf("Diff too high: %lld..", diff); | ||
69 | return -1; | ||
70 | } | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int check_itimer(int which) | ||
76 | { | ||
77 | int err; | ||
78 | struct timeval start, end; | ||
79 | struct itimerval val = { | ||
80 | .it_value.tv_sec = DELAY, | ||
81 | }; | ||
82 | |||
83 | printf("Check itimer "); | ||
84 | |||
85 | if (which == ITIMER_VIRTUAL) | ||
86 | printf("virtual... "); | ||
87 | else if (which == ITIMER_PROF) | ||
88 | printf("prof... "); | ||
89 | else if (which == ITIMER_REAL) | ||
90 | printf("real... "); | ||
91 | |||
92 | fflush(stdout); | ||
93 | |||
94 | done = 0; | ||
95 | |||
96 | if (which == ITIMER_VIRTUAL) | ||
97 | signal(SIGVTALRM, sig_handler); | ||
98 | else if (which == ITIMER_PROF) | ||
99 | signal(SIGPROF, sig_handler); | ||
100 | else if (which == ITIMER_REAL) | ||
101 | signal(SIGALRM, sig_handler); | ||
102 | |||
103 | err = gettimeofday(&start, NULL); | ||
104 | if (err < 0) { | ||
105 | perror("Can't call gettimeofday()\n"); | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | err = setitimer(which, &val, NULL); | ||
110 | if (err < 0) { | ||
111 | perror("Can't set timer\n"); | ||
112 | return -1; | ||
113 | } | ||
114 | |||
115 | if (which == ITIMER_VIRTUAL) | ||
116 | user_loop(); | ||
117 | else if (which == ITIMER_PROF) | ||
118 | kernel_loop(); | ||
119 | else if (which == ITIMER_REAL) | ||
120 | idle_loop(); | ||
121 | |||
122 | gettimeofday(&end, NULL); | ||
123 | if (err < 0) { | ||
124 | perror("Can't call gettimeofday()\n"); | ||
125 | return -1; | ||
126 | } | ||
127 | |||
128 | if (!check_diff(start, end)) | ||
129 | printf("[OK]\n"); | ||
130 | else | ||
131 | printf("[FAIL]\n"); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int check_timer_create(int which) | ||
137 | { | ||
138 | int err; | ||
139 | timer_t id; | ||
140 | struct timeval start, end; | ||
141 | struct itimerspec val = { | ||
142 | .it_value.tv_sec = DELAY, | ||
143 | }; | ||
144 | |||
145 | printf("Check timer_create() "); | ||
146 | if (which == CLOCK_THREAD_CPUTIME_ID) { | ||
147 | printf("per thread... "); | ||
148 | } else if (which == CLOCK_PROCESS_CPUTIME_ID) { | ||
149 | printf("per process... "); | ||
150 | } | ||
151 | fflush(stdout); | ||
152 | |||
153 | done = 0; | ||
154 | timer_create(which, NULL, &id); | ||
155 | if (err < 0) { | ||
156 | perror("Can't create timer\n"); | ||
157 | return -1; | ||
158 | } | ||
159 | signal(SIGALRM, sig_handler); | ||
160 | |||
161 | err = gettimeofday(&start, NULL); | ||
162 | if (err < 0) { | ||
163 | perror("Can't call gettimeofday()\n"); | ||
164 | return -1; | ||
165 | } | ||
166 | |||
167 | err = timer_settime(id, 0, &val, NULL); | ||
168 | if (err < 0) { | ||
169 | perror("Can't set timer\n"); | ||
170 | return -1; | ||
171 | } | ||
172 | |||
173 | user_loop(); | ||
174 | |||
175 | gettimeofday(&end, NULL); | ||
176 | if (err < 0) { | ||
177 | perror("Can't call gettimeofday()\n"); | ||
178 | return -1; | ||
179 | } | ||
180 | |||
181 | if (!check_diff(start, end)) | ||
182 | printf("[OK]\n"); | ||
183 | else | ||
184 | printf("[FAIL]\n"); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | int main(int argc, char **argv) | ||
190 | { | ||
191 | int err; | ||
192 | |||
193 | printf("Testing posix timers. False negative may happen on CPU execution \n"); | ||
194 | printf("based timers if other threads run on the CPU...\n"); | ||
195 | |||
196 | if (check_itimer(ITIMER_VIRTUAL) < 0) | ||
197 | return -1; | ||
198 | |||
199 | if (check_itimer(ITIMER_PROF) < 0) | ||
200 | return -1; | ||
201 | |||
202 | if (check_itimer(ITIMER_REAL) < 0) | ||
203 | return -1; | ||
204 | |||
205 | if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) | ||
206 | return -1; | ||
207 | |||
208 | /* | ||
209 | * It's unfortunately hard to reliably test a timer expiration | ||
210 | * on parallel multithread cputime. We could arm it to expire | ||
211 | * on DELAY * nr_threads, with nr_threads busy looping, then wait | ||
212 | * the normal DELAY since the time is elapsing nr_threads faster. | ||
213 | * But for that we need to ensure we have real physical free CPUs | ||
214 | * to ensure true parallelism. So test only one thread until we | ||
215 | * find a better solution. | ||
216 | */ | ||
217 | if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) | ||
218 | return -1; | ||
219 | |||
220 | return 0; | ||
221 | } | ||