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