video: tegra: host: remove nvhost_channel from nvhost_master
Mayuresh Kulkarni [Mon, 14 May 2012 09:08:22 +0000 (14:08 +0530)]
- nvhost_master holds a reference to all the channels for
a chip architecture
- however, nvhost_master is a private data of host1x hardware
device. so it should contain only members needed by host1x
hardware device
- add chip specific apis to allocate and free channels
- this will also help to remove the static binding between
nvhost_device and a channel per SoC in future

Bug 871237

Change-Id: I2148db57b995b4cb60954ebb6e670f588552eca4
Signed-off-by: Mayuresh Kulkarni <mkulkarni@nvidia.com>
Reviewed-on: http://git-master/r/91687
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>

drivers/video/tegra/host/bus_client.c
drivers/video/tegra/host/chip_support.h
drivers/video/tegra/host/dev.c
drivers/video/tegra/host/dev.h
drivers/video/tegra/host/nvhost_channel.c
drivers/video/tegra/host/nvhost_channel.h
drivers/video/tegra/host/t20/t20.c
drivers/video/tegra/host/t30/t30.c

index 660e795..9a32e53 100644 (file)
@@ -532,7 +532,11 @@ int nvhost_client_device_init(struct nvhost_device *dev)
 {
        int err;
        struct nvhost_master *nvhost_master = nvhost_get_host(dev);
-       struct nvhost_channel *ch = &nvhost_master->channels[dev->index];
+       struct nvhost_channel *ch;
+
+       ch = nvhost_alloc_channel(dev->index);
+       if (ch == NULL)
+               return -ENODEV;
 
        /* store the pointer to this device for channel */
        ch->dev = dev;
@@ -555,6 +559,7 @@ int nvhost_client_device_init(struct nvhost_device *dev)
 
 fail:
        /* Add clean-up */
+       nvhost_free_channel(ch);
        return err;
 }
 
index 9f56a90..c0d567d 100644 (file)
@@ -138,8 +138,9 @@ struct nvhost_chip_support {
        } intr;
 
        struct {
-               struct nvhost_device *(*get_nvhost_device)(struct nvhost_master *host,
-                       char *name);
+               struct nvhost_device *(*get_nvhost_device)(char *name);
+               struct nvhost_channel *(*alloc_nvhost_channel)(int chid);
+               void (*free_nvhost_channel)(struct nvhost_channel *ch);
        } nvhost_dev;
 };
 
index 9142b52..f215b53 100644 (file)
@@ -353,14 +353,23 @@ fail:
 struct nvhost_device *nvhost_get_device(char *name)
 {
        BUG_ON(!host_device_op().get_nvhost_device);
-       return host_device_op().get_nvhost_device(nvhost, name);
+       return host_device_op().get_nvhost_device(name);
 }
 
-static void nvhost_free_resources(struct nvhost_master *host)
+struct nvhost_channel *nvhost_alloc_channel(int index)
+{
+       BUG_ON(!host_device_op().alloc_nvhost_channel);
+       return host_device_op().alloc_nvhost_channel(index);
+}
+
+void nvhost_free_channel(struct nvhost_channel *ch)
 {
-       kfree(host->channels);
-       host->channels = 0;
+       BUG_ON(!host_device_op().free_nvhost_channel);
+       host_device_op().free_nvhost_channel(ch);
+}
 
+static void nvhost_free_resources(struct nvhost_master *host)
+{
        kfree(host->intr.syncpt);
        host->intr.syncpt = 0;
 }
@@ -373,14 +382,10 @@ static int __devinit nvhost_alloc_resources(struct nvhost_master *host)
        if (err)
                return err;
 
-       /* allocate items sized in chip specific support init */
-       host->channels = kzalloc(sizeof(struct nvhost_channel) *
-                                host->nb_channels, GFP_KERNEL);
-
        host->intr.syncpt = kzalloc(sizeof(struct nvhost_intr_syncpt) *
                                    host->syncpt.nb_pts, GFP_KERNEL);
 
-       if (!(host->channels && host->intr.syncpt)) {
+       if (!host->intr.syncpt) {
                /* frees happen in the support removal phase */
                return -ENOMEM;
        }
index 8360725..41c4fb5 100644 (file)
@@ -43,8 +43,6 @@ struct nvhost_master {
        struct nvmap_client *nvmap;
        struct nvhost_intr intr;
        struct nvhost_device *dev;
-       struct nvhost_channel *channels;
-       u32 nb_channels;
        atomic_t clientid;
 };
 
@@ -54,6 +52,8 @@ void nvhost_debug_init(struct nvhost_master *master);
 void nvhost_debug_dump(struct nvhost_master *master);
 
 struct nvhost_device *nvhost_get_device(char *name);
+struct nvhost_channel *nvhost_alloc_channel(int index);
+void nvhost_free_channel(struct nvhost_channel *ch);
 
 extern pid_t nvhost_debug_null_kickoff_pid;
 
index e09f50a..8b79479 100644 (file)
@@ -125,3 +125,29 @@ int nvhost_channel_suspend(struct nvhost_channel *ch)
 
        return ret;
 }
+
+struct nvhost_channel *nvhost_alloc_channel_internal(int chindex,
+       int max_channels, int *current_channel_count)
+{
+       struct nvhost_channel *ch = NULL;
+
+       if ( (chindex > max_channels) ||
+            ( (*current_channel_count + 1) > max_channels) )
+               return NULL;
+       else {
+               ch = kzalloc(sizeof(*ch), GFP_KERNEL);
+               if (ch == NULL)
+                       return NULL;
+               else {
+                       (*current_channel_count)++;
+                       return ch;
+               }
+       }
+}
+
+void nvhost_free_channel_internal(struct nvhost_channel *ch,
+       int *current_channel_count)
+{
+       kfree(ch);
+       (*current_channel_count)--;
+}
index fd3dcbb..eac5173 100644 (file)
@@ -70,10 +70,14 @@ int nvhost_channel_suspend(struct nvhost_channel *ch);
 int nvhost_channel_drain_read_fifo(void __iomem *chan_regs,
                        u32 *ptr, unsigned int count, unsigned int *pending);
 
-int nvhost_channel_read_3d_reg(
-       struct nvhost_channel *channel,
+int nvhost_channel_read_3d_reg(struct nvhost_channel *channel,
        struct nvhost_hwctx *hwctx,
-       u32 offset,
-       u32 *value);
+       u32 offset, u32 *value);
+
+struct nvhost_channel *nvhost_alloc_channel_internal(int chindex,
+       int max_channels, int *current_channel_count);
+
+void nvhost_free_channel_internal(struct nvhost_channel *ch,
+       int *current_channel_count);
 
 #endif
index 02382cb..673a81c 100644 (file)
@@ -43,7 +43,9 @@
 #define NVMODMUTEX_VI          (8)
 #define NVMODMUTEX_DSI         (9)
 
-#define NVHOST_NUMCHANNELS     (NV_HOST1X_CHANNELS - 1)
+#define T20_NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1)
+
+static int t20_num_alloc_channels = 0;
 
 struct nvhost_device t20_devices[] = {
 {
@@ -189,8 +191,6 @@ static int t20_channel_init(struct nvhost_channel *ch,
 int nvhost_init_t20_channel_support(struct nvhost_master *host,
        struct nvhost_chip_support *op)
 {
-       host->nb_channels =  NVHOST_NUMCHANNELS;
-
        op->channel.init = t20_channel_init;
        op->channel.submit = host1x_channel_submit;
        op->channel.read3dreg = host1x_channel_read_3d_reg;
@@ -198,8 +198,18 @@ int nvhost_init_t20_channel_support(struct nvhost_master *host,
        return 0;
 }
 
-struct nvhost_device *t20_get_nvhost_device(struct nvhost_master *host,
-       char *name)
+static void t20_free_nvhost_channel(struct nvhost_channel *ch)
+{
+       nvhost_free_channel_internal(ch, &t20_num_alloc_channels);
+}
+
+static struct nvhost_channel *t20_alloc_nvhost_channel(int chindex)
+{
+       return nvhost_alloc_channel_internal(chindex,
+               T20_NVHOST_NUMCHANNELS, &t20_num_alloc_channels);
+}
+
+struct nvhost_device *t20_get_nvhost_device(char *name)
 {
        int i;
 
@@ -232,6 +242,10 @@ int nvhost_init_t20_support(struct nvhost_master *host,
        err = nvhost_init_t20_intr_support(op);
        if (err)
                return err;
+
        op->nvhost_dev.get_nvhost_device = t20_get_nvhost_device;
+       op->nvhost_dev.alloc_nvhost_channel = t20_alloc_nvhost_channel;
+       op->nvhost_dev.free_nvhost_channel = t20_free_nvhost_channel;
+
        return 0;
 }
index 6e9b0af..d4113a8 100644 (file)
 
 #define NVHOST_CHANNEL_BASE    0
 
+#define T30_NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1)
+
+static int t30_num_alloc_channels = 0;
+
 struct nvhost_device t30_devices[] = {
 {
        /* channel 0 */
@@ -209,6 +213,7 @@ int nvhost_init_t30_channel_support(struct nvhost_master *host,
 
        return result;
 }
+
 int nvhost_init_t30_debug_support(struct nvhost_chip_support *op)
 {
        nvhost_init_t20_debug_support(op);
@@ -217,8 +222,18 @@ int nvhost_init_t30_debug_support(struct nvhost_chip_support *op)
        return 0;
 }
 
-struct nvhost_device *t30_get_nvhost_device(struct nvhost_master *host,
-       char *name)
+static void t30_free_nvhost_channel(struct nvhost_channel *ch)
+{
+       nvhost_free_channel_internal(ch, &t30_num_alloc_channels);
+}
+
+static struct nvhost_channel *t30_alloc_nvhost_channel(int chindex)
+{
+       return nvhost_alloc_channel_internal(chindex,
+               T30_NVHOST_NUMCHANNELS, &t30_num_alloc_channels);
+}
+
+struct nvhost_device *t30_get_nvhost_device(char *name)
 {
        int i;
 
@@ -251,6 +266,10 @@ int nvhost_init_t30_support(struct nvhost_master *host,
        err = nvhost_init_t20_intr_support(op);
        if (err)
                return err;
+
        op->nvhost_dev.get_nvhost_device = t30_get_nvhost_device;
+       op->nvhost_dev.alloc_nvhost_channel = t30_alloc_nvhost_channel;
+       op->nvhost_dev.free_nvhost_channel = t30_free_nvhost_channel;
+
        return 0;
 }