diff options
author | Dan Williams <dan.j.williams@intel.com> | 2007-01-02 15:52:26 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2007-07-13 11:06:18 -0400 |
commit | c211092313b90f898dec61f35207fc282d1eadc3 (patch) | |
tree | 30df0c81f207d0babb3fe56a17419f37e71e973a /include/asm-arm/hardware | |
parent | f6dff381af01006ffae3c23cd2e07e30584de0ec (diff) |
dmaengine: driver for the iop32x, iop33x, and iop13xx raid engines
The Intel(R) IOP series of i/o processors integrate an Xscale core with
raid acceleration engines. The capabilities per platform are:
iop219:
(2) copy engines
iop321:
(2) copy engines
(1) xor and block fill engine
iop33x:
(2) copy and crc32c engines
(1) xor, xor zero sum, pq, pq zero sum, and block fill engine
iop34x (iop13xx):
(2) copy, crc32c, xor, xor zero sum, and block fill engines
(1) copy, crc32c, xor, xor zero sum, pq, pq zero sum, and block fill engine
The driver supports the features of the async_tx api:
* asynchronous notification of operation completion
* implicit (interupt triggered) handling of inter-channel transaction
dependencies
The driver adapts to the platform it is running by two methods.
1/ #include <asm/arch/adma.h> which defines the hardware specific
iop_chan_* and iop_desc_* routines as a series of static inline
functions
2/ The private platform data attached to the platform_device defines the
capabilities of the channels
20070626: Callbacks are run in a tasklet. Given the recent discussion on
LKML about killing tasklets in favor of workqueues I did a quick conversion
of the driver. Raid5 resync performance dropped from 50MB/s to 30MB/s, so
the tasklet implementation remains until a generic softirq interface is
available.
Changelog:
* fixed a slot allocation bug in do_iop13xx_adma_xor that caused too few
slots to be requested eventually leading to data corruption
* enabled the slot allocation routine to attempt to free slots before
returning -ENOMEM
* switched the cleanup routine to solely use the software chain and the
status register to determine if a descriptor is complete. This is
necessary to support other IOP engines that do not have status writeback
capability
* make the driver iop generic
* modified the allocation routines to understand allocating a group of
slots for a single operation
* added a null xor initialization operation for the xor only channel on
iop3xx
* support xor operations on buffers larger than the hardware maximum
* split the do_* routines into separate prep, src/dest set, submit stages
* added async_tx support (dependent operations initiation at cleanup time)
* simplified group handling
* added interrupt support (callbacks via tasklets)
* brought the pending depth inline with ioat (i.e. 4 descriptors)
* drop dma mapping methods, suggested by Chris Leech
* don't use inline in C files, Adrian Bunk
* remove static tasklet declarations
* make iop_adma_alloc_slots easier to read and remove chances for a
corrupted descriptor chain
* fix locking bug in iop_adma_alloc_chan_resources, Benjamin Herrenschmidt
* convert capabilities over to dma_cap_mask_t
* fixup sparse warnings
* add descriptor flush before iop_chan_enable
* checkpatch.pl fixes
* gpl v2 only correction
* move set_src, set_dest, submit to async_tx methods
* move group_list and phys to async_tx
Cc: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'include/asm-arm/hardware')
-rw-r--r-- | include/asm-arm/hardware/iop_adma.h | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h new file mode 100644 index 000000000000..ca8e71f44346 --- /dev/null +++ b/include/asm-arm/hardware/iop_adma.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Copyright © 2006, Intel Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
16 | * | ||
17 | */ | ||
18 | #ifndef IOP_ADMA_H | ||
19 | #define IOP_ADMA_H | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/dmaengine.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | |||
24 | #define IOP_ADMA_SLOT_SIZE 32 | ||
25 | #define IOP_ADMA_THRESHOLD 4 | ||
26 | |||
27 | /** | ||
28 | * struct iop_adma_device - internal representation of an ADMA device | ||
29 | * @pdev: Platform device | ||
30 | * @id: HW ADMA Device selector | ||
31 | * @dma_desc_pool: base of DMA descriptor region (DMA address) | ||
32 | * @dma_desc_pool_virt: base of DMA descriptor region (CPU address) | ||
33 | * @common: embedded struct dma_device | ||
34 | */ | ||
35 | struct iop_adma_device { | ||
36 | struct platform_device *pdev; | ||
37 | int id; | ||
38 | dma_addr_t dma_desc_pool; | ||
39 | void *dma_desc_pool_virt; | ||
40 | struct dma_device common; | ||
41 | }; | ||
42 | |||
43 | /** | ||
44 | * struct iop_adma_chan - internal representation of an ADMA device | ||
45 | * @pending: allows batching of hardware operations | ||
46 | * @completed_cookie: identifier for the most recently completed operation | ||
47 | * @lock: serializes enqueue/dequeue operations to the slot pool | ||
48 | * @mmr_base: memory mapped register base | ||
49 | * @chain: device chain view of the descriptors | ||
50 | * @device: parent device | ||
51 | * @common: common dmaengine channel object members | ||
52 | * @last_used: place holder for allocation to continue from where it left off | ||
53 | * @all_slots: complete domain of slots usable by the channel | ||
54 | * @cleanup_watchdog: workaround missed interrupts on iop3xx | ||
55 | * @slots_allocated: records the actual size of the descriptor slot pool | ||
56 | * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs | ||
57 | */ | ||
58 | struct iop_adma_chan { | ||
59 | int pending; | ||
60 | dma_cookie_t completed_cookie; | ||
61 | spinlock_t lock; /* protects the descriptor slot pool */ | ||
62 | void __iomem *mmr_base; | ||
63 | struct list_head chain; | ||
64 | struct iop_adma_device *device; | ||
65 | struct dma_chan common; | ||
66 | struct iop_adma_desc_slot *last_used; | ||
67 | struct list_head all_slots; | ||
68 | struct timer_list cleanup_watchdog; | ||
69 | int slots_allocated; | ||
70 | struct tasklet_struct irq_tasklet; | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * struct iop_adma_desc_slot - IOP-ADMA software descriptor | ||
75 | * @slot_node: node on the iop_adma_chan.all_slots list | ||
76 | * @chain_node: node on the op_adma_chan.chain list | ||
77 | * @hw_desc: virtual address of the hardware descriptor chain | ||
78 | * @phys: hardware address of the hardware descriptor chain | ||
79 | * @group_head: first operation in a transaction | ||
80 | * @slot_cnt: total slots used in an transaction (group of operations) | ||
81 | * @slots_per_op: number of slots per operation | ||
82 | * @idx: pool index | ||
83 | * @unmap_src_cnt: number of xor sources | ||
84 | * @unmap_len: transaction bytecount | ||
85 | * @async_tx: support for the async_tx api | ||
86 | * @group_list: list of slots that make up a multi-descriptor transaction | ||
87 | * for example transfer lengths larger than the supported hw max | ||
88 | * @xor_check_result: result of zero sum | ||
89 | * @crc32_result: result crc calculation | ||
90 | */ | ||
91 | struct iop_adma_desc_slot { | ||
92 | struct list_head slot_node; | ||
93 | struct list_head chain_node; | ||
94 | void *hw_desc; | ||
95 | struct iop_adma_desc_slot *group_head; | ||
96 | u16 slot_cnt; | ||
97 | u16 slots_per_op; | ||
98 | u16 idx; | ||
99 | u16 unmap_src_cnt; | ||
100 | size_t unmap_len; | ||
101 | struct dma_async_tx_descriptor async_tx; | ||
102 | union { | ||
103 | u32 *xor_check_result; | ||
104 | u32 *crc32_result; | ||
105 | }; | ||
106 | }; | ||
107 | |||
108 | struct iop_adma_platform_data { | ||
109 | int hw_id; | ||
110 | dma_cap_mask_t cap_mask; | ||
111 | size_t pool_size; | ||
112 | }; | ||
113 | |||
114 | #define to_iop_sw_desc(addr_hw_desc) \ | ||
115 | container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc) | ||
116 | #define iop_hw_desc_slot_idx(hw_desc, idx) \ | ||
117 | ( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) ) | ||
118 | #endif | ||