if (inode) {
pdata = container_of(inode->i_cdev,
struct nvhost_device_data, cdev);
- ret = nvhost_channel_map(pdata, &ch);
+ ret = nvhost_channel_map(pdata, &ch, NULL);
if (ret) {
pr_err("%s: failed to map channel, error: %d\n",
__func__, ret);
priv->timeout = pdata->nvhost_timeout_default;
priv->timeout_debug_dump = true;
mutex_init(&priv->ioctl_lock);
+ priv->pdev = pdata->pdev;
if (!tegra_platform_is_silicon())
priv->timeout = 0;
mutex_unlock(&channel_lock);
#include <trace/events/nvhost.h>
#include <linux/nvhost_ioctl.h>
+#include <linux/delay.h>
#include <linux/nvhost.h>
#include <linux/slab.h>
ch->dev = NULL;
ch->aperture = NULL;
ch->refcount = 0;
+ ch->identifier = NULL;
pdata->channels[ch->dev_chid] = NULL;
return 0;
/* Maps free channel with device */
int nvhost_channel_map(struct nvhost_device_data *pdata,
- struct nvhost_channel **channel)
+ struct nvhost_channel **channel,
+ void *identifier)
{
struct nvhost_master *host = NULL;
struct nvhost_channel *ch = NULL;
mutex_lock(&host->chlist_mutex);
max_channels = host->info.nb_channels;
- /* Check if already channel(s) assigned for device */
- if (pdata->num_channels == pdata->num_mapped_chs) {
+ if (host->info.channel_policy == MAP_CHANNEL_ON_SUBMIT) {
+ /* check if the channel is still in use */
+ ch = *channel;
+ if (ch && ch->refcount && ch->identifier == identifier) {
+ /* yes, client can continue using it */
+ ch->refcount++;
+ mutex_unlock(&host->chlist_mutex);
+ return 0;
+ }
+ } else if (pdata->num_channels == pdata->num_mapped_chs) {
if (pdata->exclusive) {
mutex_unlock(&host->chlist_mutex);
return -EBUSY;
return 0;
}
- index = find_next_zero_bit(&host->allocated_channels,
+ do {
+ index = find_next_zero_bit(&host->allocated_channels,
max_channels, host->next_free_ch);
- if (index >= max_channels) {
- /* Reset next pointer and try */
- host->next_free_ch = 0;
- index = find_next_zero_bit(&host->allocated_channels,
+ if (index >= max_channels) {
+ /* Reset next pointer and try */
+ host->next_free_ch = 0;
+ index = find_next_zero_bit(&host->allocated_channels,
max_channels, host->next_free_ch);
+ }
if (index >= max_channels) {
- pr_err("All host1x channels are mapped, BITMAP: %lu\n",
- host->allocated_channels);
mutex_unlock(&host->chlist_mutex);
- return -ENOMEM;
+ if (host->info.channel_policy != MAP_CHANNEL_ON_SUBMIT)
+ return -ENOMEM;
+ mdelay(1);
+ mutex_lock(&host->chlist_mutex);
}
- }
+ } while (index >= max_channels);
/* Get channel from list and map to device */
ch = host->chlist[index];
ch->dev = pdata->pdev;
ch->chid = index;
- nvhost_channel_assign(pdata, ch);
+ ch->identifier = identifier;
+ if (host->info.channel_policy == MAP_CHANNEL_ON_OPEN)
+ nvhost_channel_assign(pdata, ch);
nvhost_set_chanops(ch);
set_bit(ch->chid, &host->allocated_channels);
mutex_init(&ch->syncpts_lock);
/* channel syncpoints */
struct mutex syncpts_lock;
u32 syncpts[NVHOST_MODULE_MAX_SYNCPTS];
+
+ /* owner identifier */
+ void *identifier;
};
#define channel_op(ch) (ch->ops)
int nvhost_alloc_channels(struct nvhost_master *host);
int nvhost_channel_map(struct nvhost_device_data *pdata,
- struct nvhost_channel **ch);
+ struct nvhost_channel **ch,
+ void *identifier);
int nvhost_channel_unmap(struct nvhost_channel *ch);
int nvhost_channel_release(struct nvhost_device_data *pdata);
int nvhost_channel_list_free(struct nvhost_master *host);