1c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
2c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
3c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
4c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * This program is free software; you can redistribute it and/or modify it
5c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * under the terms of the GNU General Public License as published by the Free
6c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Software Foundation; either version 2 of the License, or (at your option)
7c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * any later version.
8c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
9c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * This program is distributed in the hope that it will be useful, but WITHOUT
10c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * more details.
13c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
14c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * You should have received a copy of the GNU General Public License along with
15c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * this program; if not, write to the Free Software Foundation, Inc., 59
16c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
18c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * The full GNU General Public License is included in this distribution in the
19c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * file called COPYING.
20c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
21c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifndef DMAENGINE_H
22c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define DMAENGINE_H
23c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
24c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifdef CONFIG_DMA_ENGINE
25c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
26c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/device.h>
27c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/uio.h>
28c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/kref.h>
29c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/completion.h>
30c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/rcupdate.h>
31c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
32c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
33c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * enum dma_event - resource PNP/power managment events
34c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
35c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_RESOURCE_RESUME: DMA device returning to full power
36c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_RESOURCE_ADDED: DMA device added to the system
37c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_RESOURCE_REMOVED: DMA device removed from the system
38c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
39c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruenum dma_event {
40c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_RESOURCE_SUSPEND,
41c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_RESOURCE_RESUME,
42c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_RESOURCE_ADDED,
43c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_RESOURCE_REMOVED,
44c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
45c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
46c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
47c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * typedef dma_cookie_t - an opaque DMA cookie
48c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
49c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
50c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
51c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querutypedef s32 dma_cookie_t;
52c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
53c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0)
54c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
55c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
56c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * enum dma_status - DMA transaction status
57c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_SUCCESS: transaction completed successfully
58c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_IN_PROGRESS: transaction not yet processed
59c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @DMA_ERROR: transaction failed
60c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
61c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruenum dma_status {
62c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_SUCCESS,
63c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_IN_PROGRESS,
64c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	DMA_ERROR,
65c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
66c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
67c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
68c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * struct dma_chan_percpu - the per-CPU part of struct dma_chan
69c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @refcount: local_t used for open-coded "bigref" counting
70c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @memcpy_count: transaction counter
71c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @bytes_transferred: byte counter
72c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
73c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
74c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_chan_percpu {
75c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	local_t refcount;
76c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* stats */
77c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long memcpy_count;
78c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long bytes_transferred;
79c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
80c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
81c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
82c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * struct dma_chan - devices supply DMA channels, clients use them
83c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @client: ptr to the client user of this chan, will be %NULL when unused
84c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device: ptr to the dma device who supplies this channel, always !%NULL
85c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @cookie: last cookie value returned to client
86c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan_id: channel ID for sysfs
87c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @class_dev: class device for sysfs
88c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @refcount: kref, used in "bigref" slow-mode
89c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @slow_ref: indicates that the DMA channel is free
90c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @rcu: the DMA channel's RCU head
91c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @client_node: used to add this to the client chan list
92c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_node: used to add this to the device chan list
93c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @local: per-cpu pointer to a struct dma_chan_percpu
94c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
95c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_chan {
96c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dma_client *client;
97c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dma_device *device;
98c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	dma_cookie_t cookie;
99c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
100c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/* sysfs */
101c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int chan_id;
102c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct class_device class_dev;
103c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
104c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct kref refcount;
105c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int slow_ref;
106c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rcu_head rcu;
107c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
108c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct list_head client_node;
109c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct list_head device_node;
110c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dma_chan_percpu *local;
111c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
112c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
113c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid dma_chan_cleanup(struct kref *kref);
114c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
115c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void dma_chan_get(struct dma_chan *chan)
116c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
117c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (unlikely(chan->slow_ref))
118c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		kref_get(&chan->refcount);
119c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	else {
120c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		local_inc(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
121c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		put_cpu();
122c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
123c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
124c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
125c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void dma_chan_put(struct dma_chan *chan)
126c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
127c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (unlikely(chan->slow_ref))
128c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		kref_put(&chan->refcount, dma_chan_cleanup);
129c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	else {
130c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		local_dec(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
131c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		put_cpu();
132c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
133c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
134c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
135c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
136c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * typedef dma_event_callback - function pointer to a DMA event callback
137c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
138c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querutypedef void (*dma_event_callback) (struct dma_client *client,
139c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		struct dma_chan *chan, enum dma_event event);
140c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
141c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
142c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * struct dma_client - info on the entity making use of DMA services
143c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @event_callback: func ptr to call when something happens
144c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan_count: number of chans allocated
145c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chans_desired: number of chans requested. Can be +/- chan_count
146c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @lock: protects access to the channels list
147c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @channels: the list of DMA channels allocated
148c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @global_node: list_head for global dma_client_list
149c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
150c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_client {
151c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	dma_event_callback	event_callback;
152c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int		chan_count;
153c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int		chans_desired;
154c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
155c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	spinlock_t		lock;
156c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct list_head	channels;
157c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct list_head	global_node;
158c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
159c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
160c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
161c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * struct dma_device - info on the entity supplying DMA services
162c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chancnt: how many DMA channels are supported
163c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @channels: the list of struct dma_chan
164c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @global_node: list_head for global dma_device_list
165c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @refcount: reference count
166c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @done: IO completion struct
167c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @dev_id: unique device ID
168c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_alloc_chan_resources: allocate resources and return the
169c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	number of allocated descriptors
170c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_free_chan_resources: release DMA channel's resources
171c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
172c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
173c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
174c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_memcpy_complete: poll the status of an IOAT DMA transaction
175c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @device_memcpy_issue_pending: push appended descriptors to hardware
176c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
177c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_device {
178c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
179c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int chancnt;
180c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct list_head channels;
181c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct list_head global_node;
182c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
183c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct kref refcount;
184c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct completion done;
185c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
186c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int dev_id;
187c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
188c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int (*device_alloc_chan_resources)(struct dma_chan *chan);
189c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void (*device_free_chan_resources)(struct dma_chan *chan);
190c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
191c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			void *dest, void *src, size_t len);
192c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
193c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			struct page *page, unsigned int offset, void *kdata,
194c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			size_t len);
195c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
196c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			struct page *dest_pg, unsigned int dest_off,
197c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			struct page *src_pg, unsigned int src_off, size_t len);
198c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
199c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			dma_cookie_t cookie, dma_cookie_t *last,
200c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			dma_cookie_t *used);
201c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void (*device_memcpy_issue_pending)(struct dma_chan *chan);
202c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
203c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
204c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* --- public DMA engine API --- */
205c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
206c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_client *dma_async_client_register(dma_event_callback event_callback);
207c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid dma_async_client_unregister(struct dma_client *client);
208c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid dma_async_client_chan_request(struct dma_client *client,
209c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		unsigned int number);
210c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
211c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
212c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
213c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan: DMA channel to offload copy to
214c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @dest: destination address (virtual)
215c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @src: source address (virtual)
216c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @len: length
217c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
218c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Both @dest and @src must be mappable to a bus address according to the
219c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * DMA mapping API rules for streaming mappings.
220c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Both @dest and @src must stay memory resident (kernel memory or locked
221c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * user space pages).
222c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
223c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
224c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void *dest, void *src, size_t len)
225c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
226c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int cpu = get_cpu();
227c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
228c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
229c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	put_cpu();
230c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
231c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
232c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
233c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
234c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
235c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
236c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan: DMA channel to offload copy to
237c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @page: destination page
238c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @offset: offset in page to copy to
239c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @kdata: source address (virtual)
240c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @len: length
241c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
242c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Both @page/@offset and @kdata must be mappable to a bus address according
243c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * to the DMA mapping API rules for streaming mappings.
244c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Both @page/@offset and @kdata must stay memory resident (kernel memory or
245c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * locked user space pages)
246c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
247c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
248c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct page *page, unsigned int offset, void *kdata, size_t len)
249c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
250c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int cpu = get_cpu();
251c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
252c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
253c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	put_cpu();
254c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
255c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
256c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	                                             kdata, len);
257c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
258c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
259c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
260c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
261c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan: DMA channel to offload copy to
262c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @dest_pg: destination page
263c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @dest_off: offset in page to copy to
264c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @src_pg: source page
265c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @src_off: offset in page to copy from
266c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @len: length
267c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
268c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
269c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * address according to the DMA mapping API rules for streaming mappings.
270c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
271c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * (kernel memory or locked user space pages).
272c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
273c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
274c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
275c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int src_off, size_t len)
276c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
277c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int cpu = get_cpu();
278c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
279c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
280c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	put_cpu();
281c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
282c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
283c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	                                            src_pg, src_off, len);
284c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
285c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
286c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
287c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_memcpy_issue_pending - flush pending copies to HW
288c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan: target DMA channel
289c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
290c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * This allows drivers to push copies to HW in batches,
291c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * reducing MMIO writes where possible.
292c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
293c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
294c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
295c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return chan->device->device_memcpy_issue_pending(chan);
296c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
297c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
298c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
299c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_memcpy_complete - poll for transaction completion
300c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @chan: DMA channel
301c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @cookie: transaction identifier to check status of
302c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @last: returns last completed cookie, can be NULL
303c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @used: returns last issued cookie, can be NULL
304c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
305c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * If @last and @used are passed in, upon return they reflect the driver
306c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * internal state and can be used with dma_async_is_complete() to check
307c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * the status of multiple cookies without re-checking hardware state.
308c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
309c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
310c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
311c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
312c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return chan->device->device_memcpy_complete(chan, cookie, last, used);
313c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
314c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
315c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
316c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_is_complete - test a cookie against chan state
317c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @cookie: transaction identifier to test status of
318c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @last_complete: last know completed transaction
319c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * @last_used: last cookie value handed out
320c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
321c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * dma_async_is_complete() is used in dma_async_memcpy_complete()
322c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * the test logic is seperated for lightweight testing of multiple cookies
323c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
324c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
325c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			dma_cookie_t last_complete, dma_cookie_t last_used)
326c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
327c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (last_complete <= last_used) {
328c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		if ((cookie <= last_complete) || (cookie > last_used))
329c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			return DMA_SUCCESS;
330c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	} else {
331c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		if ((cookie <= last_complete) && (cookie > last_used))
332c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			return DMA_SUCCESS;
333c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
334c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return DMA_IN_PROGRESS;
335c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
336c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
337c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
338c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* --- DMA device --- */
339c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
340c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruint dma_async_device_register(struct dma_device *device);
341c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid dma_async_device_unregister(struct dma_device *device);
342c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
343c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* --- Helper iov-locking functions --- */
344c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
345c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_page_list {
346c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	char *base_address;
347c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int nr_pages;
348c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct page **pages;
349c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
350c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
351c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_pinned_list {
352c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int nr_iovecs;
353c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dma_page_list page_list[0];
354c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
355c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
356c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len);
357c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruvoid dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list);
358c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
359c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querudma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
360c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len);
361c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querudma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
362c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dma_pinned_list *pinned_list, struct page *page,
363c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int offset, size_t len);
364c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
365c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif /* CONFIG_DMA_ENGINE */
366c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif /* DMAENGINE_H */
367