diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2007-07-09 14:56:42 -0400 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2007-07-13 11:06:13 -0400 |
| commit | d379b01e9087a582d58f4b678208a4f8d8376fe7 (patch) | |
| tree | 155920bca93c18afba66b9d5acfecd359d5bec65 /include/linux | |
| parent | 7405f74badf46b5d023c5d2b670b4471525f6c91 (diff) | |
dmaengine: make clients responsible for managing channels
The current implementation assumes that a channel will only be used by one
client at a time. In order to enable channel sharing the dmaengine core is
changed to a model where clients subscribe to channel-available-events.
Instead of tracking how many channels a client wants and how many it has
received the core just broadcasts the available channels and lets the
clients optionally take a reference. The core learns about the clients'
needs at dma_event_callback time.
In support of multiple operation types, clients can specify a capability
mask to only be notified of channels that satisfy a certain set of
capabilities.
Changelog:
* removed DMA_TX_ARRAY_INIT, no longer needed
* dma_client_chan_free -> dma_chan_release: switch to global reference
counting only at device unregistration time, before it was also happening
at client unregistration time
* clients now return dma_state_client to dmaengine (ack, dup, nak)
* checkpatch.pl fixes
* fixup merge with git-ioat
Cc: Chris Leech <christopher.leech@intel.com>
Signed-off-by: Shannon Nelson <shannon.nelson@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/dmaengine.h | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 3de1cf71031a..a3b6035b6c86 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h | |||
| @@ -29,20 +29,32 @@ | |||
| 29 | #include <linux/dma-mapping.h> | 29 | #include <linux/dma-mapping.h> |
| 30 | 30 | ||
| 31 | /** | 31 | /** |
| 32 | * enum dma_event - resource PNP/power managment events | 32 | * enum dma_state - resource PNP/power managment state |
| 33 | * @DMA_RESOURCE_SUSPEND: DMA device going into low power state | 33 | * @DMA_RESOURCE_SUSPEND: DMA device going into low power state |
| 34 | * @DMA_RESOURCE_RESUME: DMA device returning to full power | 34 | * @DMA_RESOURCE_RESUME: DMA device returning to full power |
| 35 | * @DMA_RESOURCE_ADDED: DMA device added to the system | 35 | * @DMA_RESOURCE_AVAILABLE: DMA device available to the system |
| 36 | * @DMA_RESOURCE_REMOVED: DMA device removed from the system | 36 | * @DMA_RESOURCE_REMOVED: DMA device removed from the system |
| 37 | */ | 37 | */ |
| 38 | enum dma_event { | 38 | enum dma_state { |
| 39 | DMA_RESOURCE_SUSPEND, | 39 | DMA_RESOURCE_SUSPEND, |
| 40 | DMA_RESOURCE_RESUME, | 40 | DMA_RESOURCE_RESUME, |
| 41 | DMA_RESOURCE_ADDED, | 41 | DMA_RESOURCE_AVAILABLE, |
| 42 | DMA_RESOURCE_REMOVED, | 42 | DMA_RESOURCE_REMOVED, |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | /** | 45 | /** |
| 46 | * enum dma_state_client - state of the channel in the client | ||
| 47 | * @DMA_ACK: client would like to use, or was using this channel | ||
| 48 | * @DMA_DUP: client has already seen this channel, or is not using this channel | ||
| 49 | * @DMA_NAK: client does not want to see any more channels | ||
| 50 | */ | ||
| 51 | enum dma_state_client { | ||
| 52 | DMA_ACK, | ||
| 53 | DMA_DUP, | ||
| 54 | DMA_NAK, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /** | ||
| 46 | * typedef dma_cookie_t - an opaque DMA cookie | 58 | * typedef dma_cookie_t - an opaque DMA cookie |
| 47 | * | 59 | * |
| 48 | * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code | 60 | * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code |
| @@ -104,7 +116,6 @@ struct dma_chan_percpu { | |||
| 104 | 116 | ||
| 105 | /** | 117 | /** |
| 106 | * struct dma_chan - devices supply DMA channels, clients use them | 118 | * struct dma_chan - devices supply DMA channels, clients use them |
| 107 | * @client: ptr to the client user of this chan, will be %NULL when unused | ||
| 108 | * @device: ptr to the dma device who supplies this channel, always !%NULL | 119 | * @device: ptr to the dma device who supplies this channel, always !%NULL |
| 109 | * @cookie: last cookie value returned to client | 120 | * @cookie: last cookie value returned to client |
| 110 | * @chan_id: channel ID for sysfs | 121 | * @chan_id: channel ID for sysfs |
| @@ -112,12 +123,10 @@ struct dma_chan_percpu { | |||
| 112 | * @refcount: kref, used in "bigref" slow-mode | 123 | * @refcount: kref, used in "bigref" slow-mode |
| 113 | * @slow_ref: indicates that the DMA channel is free | 124 | * @slow_ref: indicates that the DMA channel is free |
| 114 | * @rcu: the DMA channel's RCU head | 125 | * @rcu: the DMA channel's RCU head |
| 115 | * @client_node: used to add this to the client chan list | ||
| 116 | * @device_node: used to add this to the device chan list | 126 | * @device_node: used to add this to the device chan list |
| 117 | * @local: per-cpu pointer to a struct dma_chan_percpu | 127 | * @local: per-cpu pointer to a struct dma_chan_percpu |
| 118 | */ | 128 | */ |
| 119 | struct dma_chan { | 129 | struct dma_chan { |
| 120 | struct dma_client *client; | ||
| 121 | struct dma_device *device; | 130 | struct dma_device *device; |
| 122 | dma_cookie_t cookie; | 131 | dma_cookie_t cookie; |
| 123 | 132 | ||
| @@ -129,11 +138,11 @@ struct dma_chan { | |||
| 129 | int slow_ref; | 138 | int slow_ref; |
| 130 | struct rcu_head rcu; | 139 | struct rcu_head rcu; |
| 131 | 140 | ||
| 132 | struct list_head client_node; | ||
| 133 | struct list_head device_node; | 141 | struct list_head device_node; |
| 134 | struct dma_chan_percpu *local; | 142 | struct dma_chan_percpu *local; |
| 135 | }; | 143 | }; |
| 136 | 144 | ||
| 145 | |||
| 137 | void dma_chan_cleanup(struct kref *kref); | 146 | void dma_chan_cleanup(struct kref *kref); |
| 138 | 147 | ||
| 139 | static inline void dma_chan_get(struct dma_chan *chan) | 148 | static inline void dma_chan_get(struct dma_chan *chan) |
| @@ -158,26 +167,31 @@ static inline void dma_chan_put(struct dma_chan *chan) | |||
| 158 | 167 | ||
| 159 | /* | 168 | /* |
| 160 | * typedef dma_event_callback - function pointer to a DMA event callback | 169 | * typedef dma_event_callback - function pointer to a DMA event callback |
| 170 | * For each channel added to the system this routine is called for each client. | ||
| 171 | * If the client would like to use the channel it returns '1' to signal (ack) | ||
| 172 | * the dmaengine core to take out a reference on the channel and its | ||
| 173 | * corresponding device. A client must not 'ack' an available channel more | ||
| 174 | * than once. When a channel is removed all clients are notified. If a client | ||
| 175 | * is using the channel it must 'ack' the removal. A client must not 'ack' a | ||
| 176 | * removed channel more than once. | ||
| 177 | * @client - 'this' pointer for the client context | ||
| 178 | * @chan - channel to be acted upon | ||
| 179 | * @state - available or removed | ||
| 161 | */ | 180 | */ |
| 162 | typedef void (*dma_event_callback) (struct dma_client *client, | 181 | struct dma_client; |
| 163 | struct dma_chan *chan, enum dma_event event); | 182 | typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client, |
| 183 | struct dma_chan *chan, enum dma_state state); | ||
| 164 | 184 | ||
| 165 | /** | 185 | /** |
| 166 | * struct dma_client - info on the entity making use of DMA services | 186 | * struct dma_client - info on the entity making use of DMA services |
| 167 | * @event_callback: func ptr to call when something happens | 187 | * @event_callback: func ptr to call when something happens |
| 168 | * @chan_count: number of chans allocated | 188 | * @cap_mask: only return channels that satisfy the requested capabilities |
| 169 | * @chans_desired: number of chans requested. Can be +/- chan_count | 189 | * a value of zero corresponds to any capability |
| 170 | * @lock: protects access to the channels list | ||
| 171 | * @channels: the list of DMA channels allocated | ||
| 172 | * @global_node: list_head for global dma_client_list | 190 | * @global_node: list_head for global dma_client_list |
| 173 | */ | 191 | */ |
| 174 | struct dma_client { | 192 | struct dma_client { |
| 175 | dma_event_callback event_callback; | 193 | dma_event_callback event_callback; |
| 176 | unsigned int chan_count; | 194 | dma_cap_mask_t cap_mask; |
| 177 | unsigned int chans_desired; | ||
| 178 | |||
| 179 | spinlock_t lock; | ||
| 180 | struct list_head channels; | ||
| 181 | struct list_head global_node; | 195 | struct list_head global_node; |
| 182 | }; | 196 | }; |
| 183 | 197 | ||
| @@ -285,10 +299,9 @@ struct dma_device { | |||
| 285 | 299 | ||
| 286 | /* --- public DMA engine API --- */ | 300 | /* --- public DMA engine API --- */ |
| 287 | 301 | ||
| 288 | struct dma_client *dma_async_client_register(dma_event_callback event_callback); | 302 | void dma_async_client_register(struct dma_client *client); |
| 289 | void dma_async_client_unregister(struct dma_client *client); | 303 | void dma_async_client_unregister(struct dma_client *client); |
| 290 | void dma_async_client_chan_request(struct dma_client *client, | 304 | void dma_async_client_chan_request(struct dma_client *client); |
| 291 | unsigned int number); | ||
| 292 | dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, | 305 | dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, |
| 293 | void *dest, void *src, size_t len); | 306 | void *dest, void *src, size_t len); |
| 294 | dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, | 307 | dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, |
| @@ -299,7 +312,6 @@ dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan, | |||
| 299 | void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, | 312 | void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, |
| 300 | struct dma_chan *chan); | 313 | struct dma_chan *chan); |
| 301 | 314 | ||
| 302 | |||
| 303 | static inline void | 315 | static inline void |
| 304 | async_tx_ack(struct dma_async_tx_descriptor *tx) | 316 | async_tx_ack(struct dma_async_tx_descriptor *tx) |
| 305 | { | 317 | { |
