Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);