diff options
author | Dan Williams <dan.j.williams@intel.com> | 2009-01-06 13:38:21 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2009-01-06 13:38:21 -0500 |
commit | 864498aaa9fef69ee166da023d12413a7776342d (patch) | |
tree | 023d6bfc15ba192c1a92caab3ff7525a84e409fc /drivers/dma/dmaengine.c | |
parent | 41d5e59c1299f27983977bcfe3b360600996051c (diff) |
dmaengine: use idr for registering dma device numbers
This brings some predictability to dma device numbers, i.e. an rmmod/insmod
cycle may now result in /sys/class/dma/dma0chan0 being restored rather than
/sys/class/dma/dma1chan0 appearing.
Cc: Maciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma/dmaengine.c')
-rw-r--r-- | drivers/dma/dmaengine.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 93c4c9ac8997..dd43410c1019 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -57,10 +57,12 @@ | |||
57 | #include <linux/mutex.h> | 57 | #include <linux/mutex.h> |
58 | #include <linux/jiffies.h> | 58 | #include <linux/jiffies.h> |
59 | #include <linux/rculist.h> | 59 | #include <linux/rculist.h> |
60 | #include <linux/idr.h> | ||
60 | 61 | ||
61 | static DEFINE_MUTEX(dma_list_mutex); | 62 | static DEFINE_MUTEX(dma_list_mutex); |
62 | static LIST_HEAD(dma_device_list); | 63 | static LIST_HEAD(dma_device_list); |
63 | static long dmaengine_ref_count; | 64 | static long dmaengine_ref_count; |
65 | static struct idr dma_idr; | ||
64 | 66 | ||
65 | /* --- sysfs implementation --- */ | 67 | /* --- sysfs implementation --- */ |
66 | 68 | ||
@@ -147,6 +149,12 @@ static void chan_dev_release(struct device *dev) | |||
147 | struct dma_chan_dev *chan_dev; | 149 | struct dma_chan_dev *chan_dev; |
148 | 150 | ||
149 | chan_dev = container_of(dev, typeof(*chan_dev), device); | 151 | chan_dev = container_of(dev, typeof(*chan_dev), device); |
152 | if (atomic_dec_and_test(chan_dev->idr_ref)) { | ||
153 | mutex_lock(&dma_list_mutex); | ||
154 | idr_remove(&dma_idr, chan_dev->dev_id); | ||
155 | mutex_unlock(&dma_list_mutex); | ||
156 | kfree(chan_dev->idr_ref); | ||
157 | } | ||
150 | kfree(chan_dev); | 158 | kfree(chan_dev); |
151 | } | 159 | } |
152 | 160 | ||
@@ -611,9 +619,9 @@ EXPORT_SYMBOL(dmaengine_put); | |||
611 | */ | 619 | */ |
612 | int dma_async_device_register(struct dma_device *device) | 620 | int dma_async_device_register(struct dma_device *device) |
613 | { | 621 | { |
614 | static int id; | ||
615 | int chancnt = 0, rc; | 622 | int chancnt = 0, rc; |
616 | struct dma_chan* chan; | 623 | struct dma_chan* chan; |
624 | atomic_t *idr_ref; | ||
617 | 625 | ||
618 | if (!device) | 626 | if (!device) |
619 | return -ENODEV; | 627 | return -ENODEV; |
@@ -640,9 +648,20 @@ int dma_async_device_register(struct dma_device *device) | |||
640 | BUG_ON(!device->device_issue_pending); | 648 | BUG_ON(!device->device_issue_pending); |
641 | BUG_ON(!device->dev); | 649 | BUG_ON(!device->dev); |
642 | 650 | ||
651 | idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL); | ||
652 | if (!idr_ref) | ||
653 | return -ENOMEM; | ||
654 | atomic_set(idr_ref, 0); | ||
655 | idr_retry: | ||
656 | if (!idr_pre_get(&dma_idr, GFP_KERNEL)) | ||
657 | return -ENOMEM; | ||
643 | mutex_lock(&dma_list_mutex); | 658 | mutex_lock(&dma_list_mutex); |
644 | device->dev_id = id++; | 659 | rc = idr_get_new(&dma_idr, NULL, &device->dev_id); |
645 | mutex_unlock(&dma_list_mutex); | 660 | mutex_unlock(&dma_list_mutex); |
661 | if (rc == -EAGAIN) | ||
662 | goto idr_retry; | ||
663 | else if (rc != 0) | ||
664 | return rc; | ||
646 | 665 | ||
647 | /* represent channels in sysfs. Probably want devs too */ | 666 | /* represent channels in sysfs. Probably want devs too */ |
648 | list_for_each_entry(chan, &device->channels, device_node) { | 667 | list_for_each_entry(chan, &device->channels, device_node) { |
@@ -659,6 +678,9 @@ int dma_async_device_register(struct dma_device *device) | |||
659 | chan->dev->device.class = &dma_devclass; | 678 | chan->dev->device.class = &dma_devclass; |
660 | chan->dev->device.parent = device->dev; | 679 | chan->dev->device.parent = device->dev; |
661 | chan->dev->chan = chan; | 680 | chan->dev->chan = chan; |
681 | chan->dev->idr_ref = idr_ref; | ||
682 | chan->dev->dev_id = device->dev_id; | ||
683 | atomic_inc(idr_ref); | ||
662 | dev_set_name(&chan->dev->device, "dma%dchan%d", | 684 | dev_set_name(&chan->dev->device, "dma%dchan%d", |
663 | device->dev_id, chan->chan_id); | 685 | device->dev_id, chan->chan_id); |
664 | 686 | ||
@@ -971,6 +993,7 @@ EXPORT_SYMBOL_GPL(dma_run_dependencies); | |||
971 | 993 | ||
972 | static int __init dma_bus_init(void) | 994 | static int __init dma_bus_init(void) |
973 | { | 995 | { |
996 | idr_init(&dma_idr); | ||
974 | mutex_init(&dma_list_mutex); | 997 | mutex_init(&dma_list_mutex); |
975 | return class_register(&dma_devclass); | 998 | return class_register(&dma_devclass); |
976 | } | 999 | } |