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