0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/slab.h>
0009 #include <linux/module.h>
0010
0011 #include "channel.h"
0012 #include "dev.h"
0013 #include "job.h"
0014
0015
0016 int host1x_channel_list_init(struct host1x_channel_list *chlist,
0017 unsigned int num_channels)
0018 {
0019 chlist->channels = kcalloc(num_channels, sizeof(struct host1x_channel),
0020 GFP_KERNEL);
0021 if (!chlist->channels)
0022 return -ENOMEM;
0023
0024 chlist->allocated_channels = bitmap_zalloc(num_channels, GFP_KERNEL);
0025 if (!chlist->allocated_channels) {
0026 kfree(chlist->channels);
0027 return -ENOMEM;
0028 }
0029
0030 return 0;
0031 }
0032
0033 void host1x_channel_list_free(struct host1x_channel_list *chlist)
0034 {
0035 bitmap_free(chlist->allocated_channels);
0036 kfree(chlist->channels);
0037 }
0038
0039 int host1x_job_submit(struct host1x_job *job)
0040 {
0041 struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
0042
0043 return host1x_hw_channel_submit(host, job);
0044 }
0045 EXPORT_SYMBOL(host1x_job_submit);
0046
0047 struct host1x_channel *host1x_channel_get(struct host1x_channel *channel)
0048 {
0049 kref_get(&channel->refcount);
0050
0051 return channel;
0052 }
0053 EXPORT_SYMBOL(host1x_channel_get);
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 struct host1x_channel *host1x_channel_get_index(struct host1x *host,
0064 unsigned int index)
0065 {
0066 struct host1x_channel *ch = &host->channel_list.channels[index];
0067
0068 if (!kref_get_unless_zero(&ch->refcount))
0069 return NULL;
0070
0071 return ch;
0072 }
0073
0074 void host1x_channel_stop(struct host1x_channel *channel)
0075 {
0076 struct host1x *host = dev_get_drvdata(channel->dev->parent);
0077
0078 host1x_hw_cdma_stop(host, &channel->cdma);
0079 }
0080 EXPORT_SYMBOL(host1x_channel_stop);
0081
0082 static void release_channel(struct kref *kref)
0083 {
0084 struct host1x_channel *channel =
0085 container_of(kref, struct host1x_channel, refcount);
0086 struct host1x *host = dev_get_drvdata(channel->dev->parent);
0087 struct host1x_channel_list *chlist = &host->channel_list;
0088
0089 host1x_hw_cdma_stop(host, &channel->cdma);
0090 host1x_cdma_deinit(&channel->cdma);
0091
0092 clear_bit(channel->id, chlist->allocated_channels);
0093 }
0094
0095 void host1x_channel_put(struct host1x_channel *channel)
0096 {
0097 kref_put(&channel->refcount, release_channel);
0098 }
0099 EXPORT_SYMBOL(host1x_channel_put);
0100
0101 static struct host1x_channel *acquire_unused_channel(struct host1x *host)
0102 {
0103 struct host1x_channel_list *chlist = &host->channel_list;
0104 unsigned int max_channels = host->info->nb_channels;
0105 unsigned int index;
0106
0107 index = find_first_zero_bit(chlist->allocated_channels, max_channels);
0108 if (index >= max_channels) {
0109 dev_err(host->dev, "failed to find free channel\n");
0110 return NULL;
0111 }
0112
0113 chlist->channels[index].id = index;
0114
0115 set_bit(index, chlist->allocated_channels);
0116
0117 return &chlist->channels[index];
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127 struct host1x_channel *host1x_channel_request(struct host1x_client *client)
0128 {
0129 struct host1x *host = dev_get_drvdata(client->dev->parent);
0130 struct host1x_channel_list *chlist = &host->channel_list;
0131 struct host1x_channel *channel;
0132 int err;
0133
0134 channel = acquire_unused_channel(host);
0135 if (!channel)
0136 return NULL;
0137
0138 kref_init(&channel->refcount);
0139 mutex_init(&channel->submitlock);
0140 channel->client = client;
0141 channel->dev = client->dev;
0142
0143 err = host1x_hw_channel_init(host, channel, channel->id);
0144 if (err < 0)
0145 goto fail;
0146
0147 err = host1x_cdma_init(&channel->cdma);
0148 if (err < 0)
0149 goto fail;
0150
0151 return channel;
0152
0153 fail:
0154 clear_bit(channel->id, chlist->allocated_channels);
0155
0156 dev_err(client->dev, "failed to initialize channel\n");
0157
0158 return NULL;
0159 }
0160 EXPORT_SYMBOL(host1x_channel_request);