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 | |
| 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>
| -rw-r--r-- | drivers/dma/dmaengine.c | 27 | ||||
| -rw-r--r-- | include/linux/dmaengine.h | 4 |
2 files changed, 29 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 | } |
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index d6b6bff355f4..64dea2ab326c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h | |||
| @@ -140,10 +140,14 @@ struct dma_chan { | |||
| 140 | * struct dma_chan_dev - relate sysfs device node to backing channel device | 140 | * struct dma_chan_dev - relate sysfs device node to backing channel device |
| 141 | * @chan - driver channel device | 141 | * @chan - driver channel device |
| 142 | * @device - sysfs device | 142 | * @device - sysfs device |
| 143 | * @dev_id - parent dma_device dev_id | ||
| 144 | * @idr_ref - reference count to gate release of dma_device dev_id | ||
| 143 | */ | 145 | */ |
| 144 | struct dma_chan_dev { | 146 | struct dma_chan_dev { |
| 145 | struct dma_chan *chan; | 147 | struct dma_chan *chan; |
| 146 | struct device device; | 148 | struct device device; |
| 149 | int dev_id; | ||
| 150 | atomic_t *idr_ref; | ||
| 147 | }; | 151 | }; |
| 148 | 152 | ||
| 149 | static inline const char *dma_chan_name(struct dma_chan *chan) | 153 | static inline const char *dma_chan_name(struct dma_chan *chan) |
