Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 127986
b: refs/heads/master
c: f27c580
h: refs/heads/master
v: v3
  • Loading branch information
Dan Williams committed Jan 6, 2009
1 parent 4d28b1e commit 9924e1c
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 88 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aa1e6f1a385eb2b04171ec841f3b760091e4a8ee
refs/heads/master: f27c580c3628d79b17f38976d842a6d7f3616e2e
87 changes: 9 additions & 78 deletions trunk/drivers/dma/dmaengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,15 @@
* The subsystem keeps a global list of dma_device structs it is protected by a
* mutex, dma_list_mutex.
*
* A subsystem can get access to a channel by calling dmaengine_get() followed
* by dma_find_channel(), or if it has need for an exclusive channel it can call
* dma_request_channel(). Once a channel is allocated a reference is taken
* against its corresponding driver to disable removal.
*
* Each device has a channels list, which runs unlocked but is never modified
* once the device is registered, it's just setup by the driver.
*
* Each device has a kref, which is initialized to 1 when the device is
* registered. A kref_get is done for each device registered. When the
* device is released, the corresponding kref_put is done in the release
* method. Every time one of the device's channels is allocated to a client,
* a kref_get occurs. When the channel is freed, the corresponding kref_put
* happens. The device's release function does a completion, so
* unregister_device does a remove event, device_unregister, a kref_put
* for the first reference, then waits on the completion for all other
* references to finish.
*
* Each channel has an open-coded implementation of Rusty Russell's "bigref,"
* with a kref and a per_cpu local_t. A dma_chan_get is called when a client
* signals that it wants to use a channel, and dma_chan_put is called when
* a channel is removed or a client using it is unregistered. A client can
* take extra references per outstanding transaction, as is the case with
* the NET DMA client. The release function does a kref_put on the device.
* -ChrisL, DanW
* See Documentation/dmaengine.txt for more details
*/

#include <linux/init.h>
Expand Down Expand Up @@ -114,18 +103,9 @@ static struct device_attribute dma_attrs[] = {
__ATTR_NULL
};

static void dma_async_device_cleanup(struct kref *kref);

static void dma_dev_release(struct device *dev)
{
struct dma_chan *chan = to_dma_chan(dev);
kref_put(&chan->device->refcount, dma_async_device_cleanup);
}

static struct class dma_devclass = {
.name = "dma",
.dev_attrs = dma_attrs,
.dev_release = dma_dev_release,
};

/* --- client and device registration --- */
Expand Down Expand Up @@ -232,29 +212,6 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
}
EXPORT_SYMBOL(dma_sync_wait);

/**
* dma_chan_cleanup - release a DMA channel's resources
* @kref: kernel reference structure that contains the DMA channel device
*/
void dma_chan_cleanup(struct kref *kref)
{
struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
kref_put(&chan->device->refcount, dma_async_device_cleanup);
}
EXPORT_SYMBOL(dma_chan_cleanup);

static void dma_chan_free_rcu(struct rcu_head *rcu)
{
struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu);

kref_put(&chan->refcount, dma_chan_cleanup);
}

static void dma_chan_release(struct dma_chan *chan)
{
call_rcu(&chan->rcu, dma_chan_free_rcu);
}

/**
* dma_cap_mask_all - enable iteration over all operation types
*/
Expand Down Expand Up @@ -641,9 +598,6 @@ int dma_async_device_register(struct dma_device *device)
BUG_ON(!device->device_issue_pending);
BUG_ON(!device->dev);

init_completion(&device->done);
kref_init(&device->refcount);

mutex_lock(&dma_list_mutex);
device->dev_id = id++;
mutex_unlock(&dma_list_mutex);
Expand All @@ -662,19 +616,11 @@ int dma_async_device_register(struct dma_device *device)

rc = device_register(&chan->dev);
if (rc) {
chancnt--;
free_percpu(chan->local);
chan->local = NULL;
goto err_out;
}

/* One for the channel, one of the class 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);
}
device->chancnt = chancnt;

Expand Down Expand Up @@ -705,30 +651,19 @@ int dma_async_device_register(struct dma_device *device)
list_for_each_entry(chan, &device->channels, device_node) {
if (chan->local == NULL)
continue;
kref_put(&device->refcount, dma_async_device_cleanup);
device_unregister(&chan->dev);
chancnt--;
free_percpu(chan->local);
}
return rc;
}
EXPORT_SYMBOL(dma_async_device_register);

/**
* dma_async_device_cleanup - function called when all references are released
* @kref: kernel reference object
*/
static void dma_async_device_cleanup(struct kref *kref)
{
struct dma_device *device;

device = container_of(kref, struct dma_device, refcount);
complete(&device->done);
}

/**
* dma_async_device_unregister - unregister a DMA device
* @device: &dma_device
*
* This routine is called by dma driver exit routines, dmaengine holds module
* references to prevent it being called while channels are in use.
*/
void dma_async_device_unregister(struct dma_device *device)
{
Expand All @@ -744,11 +679,7 @@ void dma_async_device_unregister(struct dma_device *device)
"%s called while %d clients hold a reference\n",
__func__, chan->client_count);
device_unregister(&chan->dev);
dma_chan_release(chan);
}

kref_put(&device->refcount, dma_async_device_cleanup);
wait_for_completion(&device->done);
}
EXPORT_SYMBOL(dma_async_device_unregister);

Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/dma/iop-adma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,7 +1253,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
spin_lock_init(&iop_chan->lock);
INIT_LIST_HEAD(&iop_chan->chain);
INIT_LIST_HEAD(&iop_chan->all_slots);
INIT_RCU_HEAD(&iop_chan->common.rcu);
iop_chan->common.device = dma_dev;
list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);

Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/dma/mv_xor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1219,7 +1219,6 @@ static int __devinit mv_xor_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mv_chan->chain);
INIT_LIST_HEAD(&mv_chan->completed_slots);
INIT_LIST_HEAD(&mv_chan->all_slots);
INIT_RCU_HEAD(&mv_chan->common.rcu);
mv_chan->common.device = dma_dev;

list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
Expand Down
7 changes: 0 additions & 7 deletions trunk/include/linux/dmaengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ struct dma_chan {
int chan_id;
struct device dev;

struct kref refcount;
int slow_ref;
struct rcu_head rcu;

struct list_head device_node;
struct dma_chan_percpu *local;
int client_count;
Expand Down Expand Up @@ -233,9 +229,6 @@ struct dma_device {
dma_cap_mask_t cap_mask;
int max_xor;

struct kref refcount;
struct completion done;

int dev_id;
struct device *dev;

Expand Down

0 comments on commit 9924e1c

Please sign in to comment.