root/drivers/gpu/host1x/channel.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. host1x_channel_list_init
  2. host1x_channel_list_free
  3. host1x_job_submit
  4. host1x_channel_get
  5. host1x_channel_get_index
  6. release_channel
  7. host1x_channel_put
  8. acquire_unused_channel
  9. host1x_channel_request

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Tegra host1x Channel
   4  *
   5  * Copyright (c) 2010-2013, NVIDIA Corporation.
   6  */
   7 
   8 #include <linux/slab.h>
   9 #include <linux/module.h>
  10 
  11 #include "channel.h"
  12 #include "dev.h"
  13 #include "job.h"
  14 
  15 /* Constructor for the host1x device list */
  16 int host1x_channel_list_init(struct host1x_channel_list *chlist,
  17                              unsigned int num_channels)
  18 {
  19         chlist->channels = kcalloc(num_channels, sizeof(struct host1x_channel),
  20                                    GFP_KERNEL);
  21         if (!chlist->channels)
  22                 return -ENOMEM;
  23 
  24         chlist->allocated_channels =
  25                 kcalloc(BITS_TO_LONGS(num_channels), sizeof(unsigned long),
  26                         GFP_KERNEL);
  27         if (!chlist->allocated_channels) {
  28                 kfree(chlist->channels);
  29                 return -ENOMEM;
  30         }
  31 
  32         bitmap_zero(chlist->allocated_channels, num_channels);
  33 
  34         return 0;
  35 }
  36 
  37 void host1x_channel_list_free(struct host1x_channel_list *chlist)
  38 {
  39         kfree(chlist->allocated_channels);
  40         kfree(chlist->channels);
  41 }
  42 
  43 int host1x_job_submit(struct host1x_job *job)
  44 {
  45         struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
  46 
  47         return host1x_hw_channel_submit(host, job);
  48 }
  49 EXPORT_SYMBOL(host1x_job_submit);
  50 
  51 struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
  52 {
  53         kref_get(&channel->refcount);
  54 
  55         return channel;
  56 }
  57 EXPORT_SYMBOL(host1x_channel_get);
  58 
  59 /**
  60  * host1x_channel_get_index() - Attempt to get channel reference by index
  61  * @host: Host1x device object
  62  * @index: Index of channel
  63  *
  64  * If channel number @index is currently allocated, increase its refcount
  65  * and return a pointer to it. Otherwise, return NULL.
  66  */
  67 struct host1x_channel *host1x_channel_get_index(struct host1x *host,
  68                                                 unsigned int index)
  69 {
  70         struct host1x_channel *ch = &host->channel_list.channels[index];
  71 
  72         if (!kref_get_unless_zero(&ch->refcount))
  73                 return NULL;
  74 
  75         return ch;
  76 }
  77 
  78 static void release_channel(struct kref *kref)
  79 {
  80         struct host1x_channel *channel =
  81                 container_of(kref, struct host1x_channel, refcount);
  82         struct host1x *host = dev_get_drvdata(channel->dev->parent);
  83         struct host1x_channel_list *chlist = &host->channel_list;
  84 
  85         host1x_hw_cdma_stop(host, &channel->cdma);
  86         host1x_cdma_deinit(&channel->cdma);
  87 
  88         clear_bit(channel->id, chlist->allocated_channels);
  89 }
  90 
  91 void host1x_channel_put(struct host1x_channel *channel)
  92 {
  93         kref_put(&channel->refcount, release_channel);
  94 }
  95 EXPORT_SYMBOL(host1x_channel_put);
  96 
  97 static struct host1x_channel *acquire_unused_channel(struct host1x *host)
  98 {
  99         struct host1x_channel_list *chlist = &host->channel_list;
 100         unsigned int max_channels = host->info->nb_channels;
 101         unsigned int index;
 102 
 103         index = find_first_zero_bit(chlist->allocated_channels, max_channels);
 104         if (index >= max_channels) {
 105                 dev_err(host->dev, "failed to find free channel\n");
 106                 return NULL;
 107         }
 108 
 109         chlist->channels[index].id = index;
 110 
 111         set_bit(index, chlist->allocated_channels);
 112 
 113         return &chlist->channels[index];
 114 }
 115 
 116 /**
 117  * host1x_channel_request() - Allocate a channel
 118  * @device: Host1x unit this channel will be used to send commands to
 119  *
 120  * Allocates a new host1x channel for @device. May return NULL if CDMA
 121  * initialization fails.
 122  */
 123 struct host1x_channel *host1x_channel_request(struct device *dev)
 124 {
 125         struct host1x *host = dev_get_drvdata(dev->parent);
 126         struct host1x_channel_list *chlist = &host->channel_list;
 127         struct host1x_channel *channel;
 128         int err;
 129 
 130         channel = acquire_unused_channel(host);
 131         if (!channel)
 132                 return NULL;
 133 
 134         kref_init(&channel->refcount);
 135         mutex_init(&channel->submitlock);
 136         channel->dev = dev;
 137 
 138         err = host1x_hw_channel_init(host, channel, channel->id);
 139         if (err < 0)
 140                 goto fail;
 141 
 142         err = host1x_cdma_init(&channel->cdma);
 143         if (err < 0)
 144                 goto fail;
 145 
 146         return channel;
 147 
 148 fail:
 149         clear_bit(channel->id, chlist->allocated_channels);
 150 
 151         dev_err(dev, "failed to initialize channel\n");
 152 
 153         return NULL;
 154 }
 155 EXPORT_SYMBOL(host1x_channel_request);

/* [<][>][^][v][top][bottom][index][help] */