gpu: ipu-v3: allocate ipuv3_channels as needed
authorPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 8 May 2017 10:45:52 +0000 (12:45 +0200)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 8 Jun 2017 06:57:19 +0000 (08:57 +0200)
Most of the 64 IPUv3 DMA channels are never used, some of them (channels
16, 30, 32, 34-39, and 53-63) are even marked as reserved.
Allocate the channel control structure only when a channel is actually
requested, replace the fixed size array with a list, and remove the
unused enabled and busy fields from the ipuv3_channel structure.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
drivers/gpu/ipu-v3/ipu-common.c
drivers/gpu/ipu-v3/ipu-prv.h

index 16d556816b5fcaa62758549d9bceaa88bd4bc839..61310f8be3099ccfac444816c82815332c4a59c7 100644 (file)
@@ -274,15 +274,22 @@ struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
 
        mutex_lock(&ipu->channel_lock);
 
-       channel = &ipu->channel[num];
+       list_for_each_entry(channel, &ipu->channels, list) {
+               if (channel->num == num) {
+                       channel = ERR_PTR(-EBUSY);
+                       goto out;
+               }
+       }
 
-       if (channel->busy) {
-               channel = ERR_PTR(-EBUSY);
+       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+       if (!channel) {
+               channel = ERR_PTR(-ENOMEM);
                goto out;
        }
 
-       channel->busy = true;
        channel->num = num;
+       channel->ipu = ipu;
+       list_add(&channel->list, &ipu->channels);
 
 out:
        mutex_unlock(&ipu->channel_lock);
@@ -299,7 +306,8 @@ void ipu_idmac_put(struct ipuv3_channel *channel)
 
        mutex_lock(&ipu->channel_lock);
 
-       channel->busy = false;
+       list_del(&channel->list);
+       kfree(channel);
 
        mutex_unlock(&ipu->channel_lock);
 }
@@ -1376,7 +1384,7 @@ static int ipu_probe(struct platform_device *pdev)
        struct ipu_soc *ipu;
        struct resource *res;
        unsigned long ipu_base;
-       int i, ret, irq_sync, irq_err;
+       int ret, irq_sync, irq_err;
        const struct ipu_devtype *devtype;
 
        devtype = of_device_get_match_data(&pdev->dev);
@@ -1409,13 +1417,12 @@ static int ipu_probe(struct platform_device *pdev)
                        return -EPROBE_DEFER;
        }
 
-       for (i = 0; i < 64; i++)
-               ipu->channel[i].ipu = ipu;
        ipu->devtype = devtype;
        ipu->ipu_type = devtype->type;
 
        spin_lock_init(&ipu->lock);
        mutex_init(&ipu->channel_lock);
+       INIT_LIST_HEAD(&ipu->channels);
 
        dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
                        ipu_base + devtype->cm_ofs);
index ca2a223a0d1e0318924e39bc15df47bb0e259def..b6e22d64159fa7a85fcf4838eb8f0ba95cb17756 100644 (file)
@@ -157,11 +157,8 @@ enum ipu_modules {
 
 struct ipuv3_channel {
        unsigned int num;
-
-       bool enabled;
-       bool busy;
-
        struct ipu_soc *ipu;
+       struct list_head list;
 };
 
 struct ipu_cpmem;
@@ -184,6 +181,7 @@ struct ipu_soc {
        enum ipuv3_type         ipu_type;
        spinlock_t              lock;
        struct mutex            channel_lock;
+       struct list_head        channels;
 
        void __iomem            *cm_reg;
        void __iomem            *idmac_reg;
@@ -193,8 +191,6 @@ struct ipu_soc {
 
        struct clk              *clk;
 
-       struct ipuv3_channel    channel[64];
-
        int                     irq_sync;
        int                     irq_err;
        struct irq_domain       *domain;