aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/dmaengine.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-07-08 14:58:21 -0400
committerDan Williams <dan.j.williams@intel.com>2008-07-08 14:58:21 -0400
commit7cc5bf9a3a84e5a02e23e5739fb894790b37c101 (patch)
treeb526b348ed1b64884bf672924540bb5dc29cb211 /drivers/dma/dmaengine.c
parent9c402f4e196290692d998b188f9094deb1619e57 (diff)
dmaengine: track the number of clients using a channel
Haavard's dma-slave interface would like to test for exclusive access to a channel. The standard channel refcounting is not sufficient in that it tracks more than just client references, it is also inaccurate as reference counts are percpu until the channel is removed. This change also enables a future fix to deallocate resources when a client declines to use a capable channel. Acked-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma/dmaengine.c')
-rw-r--r--drivers/dma/dmaengine.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 99c22b42bada..10de69eb1a3e 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -183,9 +183,10 @@ static void dma_client_chan_alloc(struct dma_client *client)
183 /* we are done once this client rejects 183 /* we are done once this client rejects
184 * an available resource 184 * an available resource
185 */ 185 */
186 if (ack == DMA_ACK) 186 if (ack == DMA_ACK) {
187 dma_chan_get(chan); 187 dma_chan_get(chan);
188 else if (ack == DMA_NAK) 188 chan->client_count++;
189 } else if (ack == DMA_NAK)
189 return; 190 return;
190 } 191 }
191 } 192 }
@@ -272,8 +273,10 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
272 /* client was holding resources for this channel so 273 /* client was holding resources for this channel so
273 * free it 274 * free it
274 */ 275 */
275 if (ack == DMA_ACK) 276 if (ack == DMA_ACK) {
276 dma_chan_put(chan); 277 dma_chan_put(chan);
278 chan->client_count--;
279 }
277 } 280 }
278 281
279 mutex_unlock(&dma_list_mutex); 282 mutex_unlock(&dma_list_mutex);
@@ -313,8 +316,10 @@ void dma_async_client_unregister(struct dma_client *client)
313 ack = client->event_callback(client, chan, 316 ack = client->event_callback(client, chan,
314 DMA_RESOURCE_REMOVED); 317 DMA_RESOURCE_REMOVED);
315 318
316 if (ack == DMA_ACK) 319 if (ack == DMA_ACK) {
317 dma_chan_put(chan); 320 dma_chan_put(chan);
321 chan->client_count--;
322 }
318 } 323 }
319 324
320 list_del(&client->global_node); 325 list_del(&client->global_node);
@@ -394,6 +399,7 @@ int dma_async_device_register(struct dma_device *device)
394 kref_get(&device->refcount); 399 kref_get(&device->refcount);
395 kref_get(&device->refcount); 400 kref_get(&device->refcount);
396 kref_init(&chan->refcount); 401 kref_init(&chan->refcount);
402 chan->client_count = 0;
397 chan->slow_ref = 0; 403 chan->slow_ref = 0;
398 INIT_RCU_HEAD(&chan->rcu); 404 INIT_RCU_HEAD(&chan->rcu);
399 } 405 }