Skip to content

Commit

Permalink
dmaengine: track the number of clients using a channel
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dan Williams committed Jul 8, 2008
1 parent 9c402f4 commit 7cc5bf9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
14 changes: 10 additions & 4 deletions drivers/dma/dmaengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,10 @@ static void dma_client_chan_alloc(struct dma_client *client)
/* we are done once this client rejects
* an available resource
*/
if (ack == DMA_ACK)
if (ack == DMA_ACK) {
dma_chan_get(chan);
else if (ack == DMA_NAK)
chan->client_count++;
} else if (ack == DMA_NAK)
return;
}
}
Expand Down Expand Up @@ -272,8 +273,10 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
/* client was holding resources for this channel so
* free it
*/
if (ack == DMA_ACK)
if (ack == DMA_ACK) {
dma_chan_put(chan);
chan->client_count--;
}
}

mutex_unlock(&dma_list_mutex);
Expand Down Expand Up @@ -313,8 +316,10 @@ void dma_async_client_unregister(struct dma_client *client)
ack = client->event_callback(client, chan,
DMA_RESOURCE_REMOVED);

if (ack == DMA_ACK)
if (ack == DMA_ACK) {
dma_chan_put(chan);
chan->client_count--;
}
}

list_del(&client->global_node);
Expand Down Expand Up @@ -394,6 +399,7 @@ int dma_async_device_register(struct dma_device *device)
kref_get(&device->refcount);
kref_get(&device->refcount);
kref_init(&chan->refcount);
chan->client_count = 0;
chan->slow_ref = 0;
INIT_RCU_HEAD(&chan->rcu);
}
Expand Down
2 changes: 2 additions & 0 deletions include/linux/dmaengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct dma_chan_percpu {
* @rcu: the DMA channel's RCU head
* @device_node: used to add this to the device chan list
* @local: per-cpu pointer to a struct dma_chan_percpu
* @client-count: how many clients are using this channel
*/
struct dma_chan {
struct dma_device *device;
Expand All @@ -154,6 +155,7 @@ struct dma_chan {

struct list_head device_node;
struct dma_chan_percpu *local;
int client_count;
};

#define to_dma_chan(p) container_of(p, struct dma_chan, dev)
Expand Down

0 comments on commit 7cc5bf9

Please sign in to comment.