]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00292607 PXP: define a static dma_chan array to record channel status
authorFancy Fang <B47543@freescale.com>
Wed, 18 Dec 2013 08:34:05 +0000 (16:34 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Mon, 16 Jun 2014 16:09:14 +0000 (18:09 +0200)
Since the number of dma channels is constant, it is more efficient
to use an array to record all the channels alloc/free status.

Signed-off-by: Fancy Fang <B47543@freescale.com>
drivers/dma/pxp/pxp_device.c

index 12f8890469ce095a3f88e2536f8f08af196e97f0..7d0ac4006f714de861456fc02ed57fee31296ef7 100644 (file)
@@ -34,9 +34,7 @@
 static atomic_t open_count = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(pxp_mem_lock);
-static DEFINE_SPINLOCK(pxp_chan_lock);
 static LIST_HEAD(head);
-static LIST_HEAD(list);
 
 /* To track the allocated memory buffer */
 struct memalloc_record {
@@ -44,17 +42,14 @@ struct memalloc_record {
        struct pxp_mem_desc mem;
 };
 
-struct pxp_chan_info {
-       struct dma_chan *dma_chan;
-       struct list_head list;
-};
-
 struct pxp_irq_info {
        wait_queue_head_t waitq;
        int irq_pending;
        int hist_status;
        spinlock_t lock;
 };
+
+static struct dma_chan *dma_chans[NR_PXP_VIRT_CHANNEL];
 static struct pxp_irq_info irq_info[NR_PXP_VIRT_CHANNEL];
 
 static int pxp_alloc_dma_buffer(struct pxp_mem_desc *mem)
@@ -122,12 +117,12 @@ static int pxp_ioc_config_chan(unsigned long arg)
        struct scatterlist sg[3];
        struct pxp_tx_desc *desc;
        struct dma_async_tx_descriptor *txd;
-       struct pxp_chan_info *info;
        struct pxp_config_data pxp_conf;
        dma_cookie_t cookie;
        int chan_id;
        int i, length, ret;
        unsigned long flags;
+       struct dma_chan *chan;
 
        ret = copy_from_user(&pxp_conf,
                             (struct pxp_config_data *)arg,
@@ -138,23 +133,15 @@ static int pxp_ioc_config_chan(unsigned long arg)
        chan_id = pxp_conf.chan_id;
        if (chan_id < 0 || chan_id >= NR_PXP_VIRT_CHANNEL)
                return -ENODEV;
-
-       /* find the channel */
-       spin_lock(&pxp_chan_lock);
-       list_for_each_entry(info, &list, list) {
-               if (info->dma_chan->chan_id == chan_id)
-                       break;
-       }
-       spin_unlock(&pxp_chan_lock);
+       chan = dma_chans[chan_id];
 
        sg_init_table(sg, 3);
 
-       txd =
-           info->dma_chan->device->device_prep_slave_sg(info->dma_chan,
-                                                        sg, 3,
-                                                        DMA_TO_DEVICE,
-                                                        DMA_PREP_INTERRUPT,
-                                                        NULL);
+       txd = chan->device->device_prep_slave_sg(chan,
+                                                sg, 3,
+                                                DMA_TO_DEVICE,
+                                                DMA_PREP_INTERRUPT,
+                                                NULL);
        if (!txd) {
                pr_err("Error preparing a DMA transaction descriptor.\n");
                return -EIO;
@@ -263,36 +250,27 @@ static long pxp_device_ioctl(struct file *filp,
        switch (cmd) {
        case PXP_IOC_GET_CHAN:
                {
-                       struct pxp_chan_info *info;
+                       struct dma_chan *chan = NULL;
                        dma_cap_mask_t mask;
 
                        pr_debug("drv: PXP_IOC_GET_CHAN Line %d\n", __LINE__);
-                       info = kzalloc(sizeof(*info), GFP_KERNEL);
-                       if (!info) {
-                               pr_err("%d: alloc err\n", __LINE__);
-                               return -ENOMEM;
-                       }
 
                        dma_cap_zero(mask);
                        dma_cap_set(DMA_SLAVE, mask);
                        dma_cap_set(DMA_PRIVATE, mask);
-                       info->dma_chan =
-                               dma_request_channel(mask, chan_filter, NULL);
-                       if (!info->dma_chan) {
+                       chan = dma_request_channel(mask, chan_filter, NULL);
+                       if (!chan) {
                                pr_err("Unsccessfully received channel!\n");
-                               kfree(info);
                                return -EBUSY;
                        }
-                       pr_debug("Successfully received channel."
-                                "chan_id %d\n", info->dma_chan->chan_id);
+                       BUG_ON(dma_chans[chan->chan_id] != NULL);
 
-                       spin_lock(&pxp_chan_lock);
-                       list_add_tail(&info->list, &list);
-                       spin_unlock(&pxp_chan_lock);
+                       pr_debug("Successfully received channel."
+                                "chan_id %d\n", chan->chan_id);
 
-                       init_waitqueue_head(&(irq_info[info->dma_chan->chan_id].waitq));
-                       if (put_user
-                           (info->dma_chan->chan_id, (u32 __user *) arg))
+                       dma_chans[chan->chan_id] = chan;
+                       init_waitqueue_head(&(irq_info[chan->chan_id].waitq));
+                       if (put_user(chan->chan_id, (u32 __user *) arg))
                                return -EFAULT;
 
                        break;
@@ -300,7 +278,7 @@ static long pxp_device_ioctl(struct file *filp,
        case PXP_IOC_PUT_CHAN:
                {
                        int chan_id;
-                       struct pxp_chan_info *info;
+                       struct dma_chan *chan;
 
                        if (get_user(chan_id, (u32 __user *) arg))
                                return -EFAULT;
@@ -308,21 +286,14 @@ static long pxp_device_ioctl(struct file *filp,
                        if (chan_id < 0 || chan_id >= NR_PXP_VIRT_CHANNEL)
                                return -ENODEV;
 
-                       spin_lock(&pxp_chan_lock);
-                       list_for_each_entry(info, &list, list) {
-                               if (info->dma_chan->chan_id == chan_id)
-                                       break;
-                       }
-                       spin_unlock(&pxp_chan_lock);
+                       if (!dma_chans[chan_id])
+                               return -ENODEV;
 
-                       pr_debug("%d release chan_id %d\n", __LINE__,
-                                info->dma_chan->chan_id);
+                       pr_debug("%d release chan_id %d\n", __LINE__, chan_id);
                        /* REVISIT */
-                       dma_release_channel(info->dma_chan);
-                       spin_lock(&pxp_chan_lock);
-                       list_del_init(&info->list);
-                       spin_unlock(&pxp_chan_lock);
-                       kfree(info);
+                       chan = dma_chans[chan_id];
+                       dma_chans[chan_id] = NULL;
+                       dma_release_channel(chan);
 
                        break;
                }
@@ -338,21 +309,15 @@ static long pxp_device_ioctl(struct file *filp,
                }
        case PXP_IOC_START_CHAN:
                {
-                       struct pxp_chan_info *info;
                        int chan_id;
 
                        if (get_user(chan_id, (u32 __user *) arg))
                                return -EFAULT;
 
-                       /* find the channel */
-                       spin_lock(&pxp_chan_lock);
-                       list_for_each_entry(info, &list, list) {
-                               if (info->dma_chan->chan_id == chan_id)
-                                       break;
-                       }
-                       spin_unlock(&pxp_chan_lock);
+                       if (chan_id < 0 || chan_id >= NR_PXP_VIRT_CHANNEL)
+                               return -ENODEV;
 
-                       dma_async_issue_pending(info->dma_chan);
+                       dma_async_issue_pending(dma_chans[chan_id]);
 
                        break;
                }