if (inode) {
pdata = container_of(inode->i_cdev,
struct nvhost_device_data, cdev);
- ch = nvhost_channel_map(pdata);
- if (!ch || !ch->dev) {
+ ret = nvhost_channel_map(pdata, &ch);
+ if (ret) {
pr_err("%s: failed to map channel\n", __func__);
- return -ENOMEM;
+ return ret;
}
} else {
if (!ch || !ch->dev) {
pr_err("%s: NULL channel request to get\n", __func__);
return -EINVAL;
}
- nvhost_getchannel(ch);
+ pdata = platform_get_drvdata(ch->dev);
+ if (!pdata->exclusive)
+ nvhost_getchannel(ch);
+ else
+ return -EBUSY;
}
mutex_lock(&channel_lock);
}
/* Maps free channel with device */
-struct nvhost_channel *nvhost_channel_map(struct nvhost_device_data *pdata)
+int nvhost_channel_map(struct nvhost_device_data *pdata,
+ struct nvhost_channel **channel)
{
struct nvhost_master *host = NULL;
struct nvhost_channel *ch = NULL;
if (!pdata) {
pr_err("%s: NULL device data\n", __func__);
- return NULL;
+ return -EINVAL;
}
host = nvhost_get_host(pdata->pdev);
/* Check if already channel(s) assigned for device */
if (pdata->num_channels == pdata->num_mapped_chs) {
+ if (pdata->exclusive) {
+ mutex_unlock(&host->chlist_mutex);
+ return -EBUSY;
+ }
ch = nvhost_check_channel(pdata);
if (ch)
nvhost_getchannel(ch);
mutex_unlock(&host->chlist_mutex);
- return ch;
+ *channel = ch;
+ return 0;
}
index = find_next_zero_bit(&host->allocated_channels,
pr_err("All host1x channels are mapped, BITMAP: %lu\n",
host->allocated_channels);
mutex_unlock(&host->chlist_mutex);
- return NULL;
+ return -ENOMEM;
}
}
if (!ch) {
dev_err(&host->dev->dev, "%s: No channel is free\n", __func__);
mutex_unlock(&host->chlist_mutex);
- return NULL;
+ return -EBUSY;
}
if (ch->chid == NVHOST_INVALID_CHANNEL) {
ch->dev = pdata->pdev;
} else {
dev_err(&host->dev->dev, "%s: wrong channel map\n", __func__);
mutex_unlock(&host->chlist_mutex);
- return NULL;
+ return -EINVAL;
}
/* Initialize channel */
dev_err(&ch->dev->dev, "%s: channel init failed\n", __func__);
mutex_unlock(&host->chlist_mutex);
nvhost_channel_unmap(ch);
- return NULL;
+ return err;
}
nvhost_getchannel(ch);
set_bit(ch->chid, &host->allocated_channels);
dev_err(&ch->dev->dev, "device init failed\n");
mutex_unlock(&host->chlist_mutex);
nvhost_channel_unmap(ch);
- return NULL;
+ return err;
}
}
dev_dbg(&ch->dev->dev, "channel %d mapped\n", ch->chid);
mutex_unlock(&host->chlist_mutex);
- return ch;
+ *channel = ch;
+ return 0;
}
/* Free channel memory and list */
#define channel_op(ch) (ch->ops)
int nvhost_alloc_channels(struct nvhost_master *host);
-struct nvhost_channel *nvhost_channel_map(struct nvhost_device_data *pdata);
+int nvhost_channel_map(struct nvhost_device_data *pdata,
+ struct nvhost_channel **ch);
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);