summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2010-10-12 18:47:05 -0700
committerColin Cross <ccross@android.com>2010-10-12 18:47:05 -0700
commit3d533ce331337e58f16b25e5de9a57f1665c4a73 (patch)
tree4022cf35ba4ff433311c3bbc24d6e1a628387ce7 /drivers
parent5c7c63142d2298d383e6e9daa733da78370b8aa1 (diff)
parent4beaf8cc13b10367d1bbb63bacbfe8d12b667c3c (diff)
Merge branch 'linux-tegra-2.6.36' into android-tegra-2.6.36
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi_tegra.c1
-rw-r--r--drivers/video/tegra/dc/dc.c18
-rw-r--r--drivers/video/tegra/fb.c233
-rw-r--r--drivers/video/tegra/host/debug.c82
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.c21
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.h2
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c15
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c8
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c2
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c5
10 files changed, 222 insertions, 165 deletions
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
index 6023da9a103a..3709d5dccd76 100644
--- a/drivers/spi/spi_tegra.c
+++ b/drivers/spi/spi_tegra.c
@@ -274,6 +274,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
val |= SLINK_TXEN;
val |= SLINK_SS_EN_CS(spi->chip_select);
val |= SLINK_SPIE;
+ val |= SLINK_SS_SETUP(3);
spi_tegra_writel(tspi, val, SLINK_COMMAND2);
val = spi_tegra_readl(tspi, SLINK_COMMAND);
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 16e6a454336d..65a36ddd2514 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -328,20 +328,6 @@ struct tegra_dc *tegra_dc_get_dc(unsigned idx)
}
EXPORT_SYMBOL(tegra_dc_get_dc);
-ssize_t tegra_dc_compute_stride(int xres, int bpp, enum tegra_win_layout layout)
-{
- unsigned int raw_stride = (xres * bpp) / 8;
- unsigned int k, n = 0;
-
- if (layout == TEGRA_WIN_LAYOUT_PITCH)
- return ALIGN(raw_stride, TEGRA_DC_PITCH_ATOM);
- else if (layout == TEGRA_WIN_LAYOUT_TILED)
- return ALIGN(raw_stride, TEGRA_DC_TILED_ATOM);
- else
- return -EINVAL;
-}
-EXPORT_SYMBOL(tegra_dc_compute_stride);
-
struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
{
if (win >= dc->n_windows)
@@ -1066,8 +1052,10 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state)
dev_info(&ndev->dev, "suspend\n");
+ mutex_lock(&dc->lock);
if (dc->enabled)
_tegra_dc_disable(dc);
+ mutex_unlock(&dc->lock);
return 0;
}
@@ -1078,8 +1066,10 @@ static int tegra_dc_resume(struct nvhost_device *ndev)
dev_info(&ndev->dev, "resume\n");
+ mutex_lock(&dc->lock);
if (dc->enabled)
_tegra_dc_enable(dc);
+ mutex_unlock(&dc->lock);
return 0;
}
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index 1656a6e49279..87ba58b06cd1 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -59,17 +59,16 @@ struct tegra_fb_info {
};
struct tegra_fb_flip_win {
- struct tegra_dc_win win_data;
- struct tegra_dc_win *dc_win;
- s32 pre_syncpt_id;
- u32 pre_syncpt_val;
+ struct tegra_fb_windowattr attr;
+ struct nvmap_handle_ref *handle;
+ dma_addr_t phys_addr;
};
struct tegra_fb_flip_data {
- struct work_struct work;
- struct tegra_fb_info *fb;
- struct tegra_fb_flip_win windows[TEGRA_FB_FLIP_N_WINDOWS];
- u32 syncpt_max;
+ struct work_struct work;
+ struct tegra_fb_info *fb;
+ struct tegra_fb_flip_win win[TEGRA_FB_FLIP_N_WINDOWS];
+ u32 syncpt_max;
};
/* palette array used by the fbcon */
@@ -149,10 +148,7 @@ static int tegra_fb_set_par(struct fb_info *info)
default:
return -EINVAL;
}
-
- info->fix.line_length = tegra_dc_compute_stride(var->xres,
- var->bits_per_pixel, TEGRA_WIN_LAYOUT_PITCH);
- tegra_fb->win->stride = info->fix.line_length;
+ info->fix.line_length = var->xres * var->bits_per_pixel / 8;
if (var->pixclock) {
struct tegra_dc_mode mode;
@@ -251,10 +247,10 @@ static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
tegra_dc_update_windows(&tegra_fb->win, 1);
tegra_dc_sync_windows(&tegra_fb->win, 1);
- if (WARN_ON(tegra_fb->win->surface)) {
- nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->surface);
- nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->surface);
- tegra_fb->win->surface = NULL;
+ if (WARN_ON(tegra_fb->win->cur_handle)) {
+ nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
+ nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
+ tegra_fb->win->cur_handle = NULL;
}
return 0;
@@ -299,131 +295,140 @@ static int tegra_fb_set_nvmap_fd(struct tegra_fb_info *tegra_fb, int fd)
return 0;
}
-static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
- struct tegra_dc_win *win,
- const struct tegra_fb_windowattr *attr)
+static int tegra_fb_pin_window(struct tegra_fb_info *tegra_fb,
+ struct tegra_fb_flip_win *flip_win)
{
- struct nvmap_handle_ref *r_dupe;
- struct nvmap_handle *h_win;
+ struct nvmap_handle_ref *win_dupe;
+ struct nvmap_handle *win_handle;
+ unsigned long buff_id = flip_win->attr.buff_id;
- if (!attr->buff_id) {
- win->flags = 0;
- win->surface = NULL;
+ if (!buff_id)
return 0;
- }
- h_win = nvmap_get_handle_id(tegra_fb->user_nvmap, attr->buff_id);
- if (h_win == NULL) {
+ win_handle = nvmap_get_handle_id(tegra_fb->user_nvmap, buff_id);
+ if (win_handle == NULL) {
dev_err(&tegra_fb->ndev->dev, "%s: flip invalid "
- "handle %08x\n", current->comm, attr->buff_id);
+ "handle %08lx\n", current->comm, buff_id);
return -EPERM;
}
/* duplicate the new framebuffer's handle into the fb driver's
* nvmap context, to ensure that the handle won't be freed as
* long as it is in-use by the fb driver */
- r_dupe = nvmap_duplicate_handle_id(tegra_fb->fb_nvmap, attr->buff_id);
- nvmap_handle_put(h_win);
+ win_dupe = nvmap_duplicate_handle_id(tegra_fb->fb_nvmap, buff_id);
+ nvmap_handle_put(win_handle);
- if (IS_ERR(r_dupe)) {
+ if (IS_ERR(win_dupe)) {
dev_err(&tegra_fb->ndev->dev, "couldn't duplicate handle\n");
- return PTR_ERR(r_dupe);
+ return PTR_ERR(win_dupe);
+ }
+
+ flip_win->handle = win_dupe;
+
+ flip_win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, win_dupe);
+ if (IS_ERR((void *)flip_win->phys_addr)) {
+ dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n");
+ nvmap_free(tegra_fb->fb_nvmap, win_dupe);
+ return PTR_ERR((void *)flip_win->phys_addr);
}
- win->surface = r_dupe;
+ return 0;
+}
+
+static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
+ struct tegra_dc_win *win,
+ const struct tegra_fb_flip_win *flip_win)
+{
+ if (flip_win->handle == NULL) {
+ win->flags = 0;
+ return 0;
+ }
win->flags = TEGRA_WIN_FLAG_ENABLED;
- if (attr->blend == TEGRA_FB_WIN_BLEND_PREMULT)
+ if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_PREMULT)
win->flags |= TEGRA_WIN_FLAG_BLEND_PREMULT;
- else if (attr->blend == TEGRA_FB_WIN_BLEND_COVERAGE)
+ else if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_COVERAGE)
win->flags |= TEGRA_WIN_FLAG_BLEND_COVERAGE;
- win->fmt = attr->pixformat;
- win->x = attr->x;
- win->y = attr->y;
- win->w = attr->w;
- win->h = attr->h;
- win->out_x = attr->out_x;
- win->out_y = attr->out_y;
- win->out_w = attr->out_w;
- win->out_h = attr->out_h;
- win->z = attr->z;
-
- win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, r_dupe);
- if (IS_ERR((void *)win->phys_addr)) {
- dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n");
- nvmap_free(tegra_fb->fb_nvmap, r_dupe);
- return (int)win->phys_addr;
- }
+ win->fmt = flip_win->attr.pixformat;
+ win->x = flip_win->attr.x;
+ win->y = flip_win->attr.y;
+ win->w = flip_win->attr.w;
+ win->h = flip_win->attr.h;
+ win->out_x = flip_win->attr.out_x;
+ win->out_y = flip_win->attr.out_y;
+ win->out_w = flip_win->attr.out_w;
+ win->out_h = flip_win->attr.out_h;
+ win->z = flip_win->attr.z;
+ win->cur_handle = flip_win->handle;
+
/* STOPSHIP verify that this won't read outside of the surface */
- win->phys_addr += attr->offset;
- win->stride = attr->stride;
+ win->phys_addr = flip_win->phys_addr + flip_win->attr.offset;
+ win->stride = flip_win->attr.stride;
+
+ if ((s32)flip_win->attr.pre_syncpt_id >= 0) {
+ nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
+ flip_win->attr.pre_syncpt_id,
+ flip_win->attr.pre_syncpt_val,
+ msecs_to_jiffies(500));
+ }
+
return 0;
}
-static void tegra_fb_flip_work(struct work_struct *work)
+static void tegra_fb_flip_worker(struct work_struct *work)
{
- struct tegra_fb_flip_data *data;
+ struct tegra_fb_flip_data *data =
+ container_of(work, struct tegra_fb_flip_data, work);
+ struct tegra_fb_info *tegra_fb = data->fb;
+ struct tegra_dc_win *win;
struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS];
- struct nvmap_handle_ref *surfs[TEGRA_FB_FLIP_N_WINDOWS];
+ struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS];
int i, nr_win = 0, nr_unpin = 0;
data = container_of(work, struct tegra_fb_flip_data, work);
for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
- struct tegra_fb_flip_win *flip_win = &data->windows[i];
+ struct tegra_fb_flip_win *flip_win = &data->win[i];
+ int idx = flip_win->attr.index;
+ win = tegra_dc_get_window(tegra_fb->win->dc, idx);
- if (!flip_win->dc_win)
+ if (!win)
continue;
- if (flip_win->dc_win->flags && flip_win->dc_win->surface)
- surfs[nr_unpin++] = flip_win->dc_win->surface;
+ if (win->flags && win->cur_handle)
+ unpin_handles[nr_unpin++] = win->cur_handle;
- wins[nr_win++] = flip_win->dc_win;
+ tegra_fb_set_windowattr(tegra_fb, win, &data->win[i]);
- flip_win->dc_win->flags = flip_win->win_data.flags;
- if (!flip_win->dc_win->flags)
- continue;
+ wins[nr_win++] = win;
- flip_win->dc_win->surface = flip_win->win_data.surface;
- flip_win->dc_win->fmt = flip_win->win_data.fmt;
- flip_win->dc_win->x = flip_win->win_data.x;
- flip_win->dc_win->y = flip_win->win_data.y;
- flip_win->dc_win->w = flip_win->win_data.w;
- flip_win->dc_win->h = flip_win->win_data.h;
- flip_win->dc_win->out_x = flip_win->win_data.out_x;
- flip_win->dc_win->out_y = flip_win->win_data.out_y;
- flip_win->dc_win->out_w = flip_win->win_data.out_w;
- flip_win->dc_win->out_h = flip_win->win_data.out_h;
- flip_win->dc_win->z = flip_win->win_data.z;
- flip_win->dc_win->phys_addr = flip_win->win_data.phys_addr;
- flip_win->dc_win->stride = flip_win->win_data.stride;
-
- if (flip_win->pre_syncpt_id < 0)
+#if 0
+ if (flip_win->attr.pre_syncpt_id < 0)
continue;
+ printk("%08x %08x\n",
+ flip_win->attr.pre_syncpt_id,
+ flip_win->attr.pre_syncpt_val);
- nvhost_syncpt_wait_timeout(&data->fb->ndev->host->syncpt,
- flip_win->pre_syncpt_id,
- flip_win->pre_syncpt_val,
+ nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
+ flip_win->attr.pre_syncpt_id,
+ flip_win->attr.pre_syncpt_val,
msecs_to_jiffies(500));
+#endif
}
- if (!nr_win)
- goto free_data;
-
tegra_dc_update_windows(wins, nr_win);
/* TODO: implement swapinterval here */
tegra_dc_sync_windows(wins, nr_win);
- tegra_dc_incr_syncpt_min(data->fb->win->dc, data->syncpt_max);
+ tegra_dc_incr_syncpt_min(tegra_fb->win->dc, data->syncpt_max);
/* unpin and deref previous front buffers */
for (i = 0; i < nr_unpin; i++) {
- nvmap_unpin(data->fb->fb_nvmap, surfs[i]);
- nvmap_free(data->fb->fb_nvmap, surfs[i]);
+ nvmap_unpin(tegra_fb->fb_nvmap, unpin_handles[i]);
+ nvmap_free(tegra_fb->fb_nvmap, unpin_handles[i]);
}
-free_data:
kfree(data);
}
@@ -432,7 +437,6 @@ static int tegra_fb_flip(struct tegra_fb_info *tegra_fb,
{
struct tegra_fb_flip_data *data;
struct tegra_fb_flip_win *flip_win;
- struct tegra_dc *dc = tegra_fb->win->dc;
u32 syncpt_max;
int i, err;
@@ -442,51 +446,46 @@ static int tegra_fb_flip(struct tegra_fb_info *tegra_fb,
if (WARN_ON(!tegra_fb->ndev))
return -EFAULT;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&tegra_fb->ndev->dev, "no memory for flip\n");
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL) {
+ dev_err(&tegra_fb->ndev->dev,
+ "can't allocate memory for flip\n");
return -ENOMEM;
}
- INIT_WORK(&data->work, tegra_fb_flip_work);
+ INIT_WORK(&data->work, tegra_fb_flip_worker);
data->fb = tegra_fb;
for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
+ flip_win = &data->win[i];
- flip_win = &data->windows[i];
- flip_win->dc_win = tegra_dc_get_window(dc, args->win[i].index);
- flip_win->pre_syncpt_id = args->win[i].pre_syncpt_id;
- flip_win->pre_syncpt_val = args->win[i].pre_syncpt_val;
-
- if (!flip_win->dc_win)
- continue;
+ memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
- err = tegra_fb_set_windowattr(tegra_fb, &flip_win->win_data,
- &args->win[i]);
- if (err) {
- dev_err(&tegra_fb->ndev->dev, "error setting window "
- "attributes\n");
+ err = tegra_fb_pin_window(tegra_fb, flip_win);
+ if (err < 0) {
+ dev_err(&tegra_fb->ndev->dev,
+ "error setting window attributes\n");
goto surf_err;
}
}
- syncpt_max = tegra_dc_incr_syncpt_max(dc);
+ syncpt_max = tegra_dc_incr_syncpt_max(tegra_fb->win->dc);
data->syncpt_max = syncpt_max;
queue_work(tegra_fb->flip_wq, &data->work);
args->post_syncpt_val = syncpt_max;
- args->post_syncpt_id = tegra_dc_get_syncpt_id(dc);
+ args->post_syncpt_id = tegra_dc_get_syncpt_id(tegra_fb->win->dc);
return 0;
surf_err:
while (i--) {
- if (data->windows[i].win_data.surface) {
+ if (data->win[i].handle) {
nvmap_unpin(tegra_fb->fb_nvmap,
- data->windows[i].win_data.surface);
+ data->win[i].handle);
nvmap_free(tegra_fb->fb_nvmap,
- data->windows[i].win_data.surface);
+ data->win[i].handle);
}
}
kfree(data);
@@ -679,9 +678,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
win->z = 0;
win->phys_addr = fb_phys;
win->virt_addr = fb_base;
- win->layout = TEGRA_WIN_LAYOUT_PITCH;
- win->stride = tegra_dc_compute_stride(fb_data->xres,
- fb_data->bits_per_pixel, win->layout);
+ win->stride = fb_data->xres * fb_data->bits_per_pixel / 8;
win->flags = TEGRA_WIN_FLAG_ENABLED;
if (fb_mem)
@@ -715,9 +712,9 @@ void tegra_fb_unregister(struct tegra_fb_info *fb_info)
{
struct fb_info *info = fb_info->info;
- if (fb_info->win->surface) {
- nvmap_unpin(fb_info->fb_nvmap, fb_info->win->surface);
- nvmap_free(fb_info->fb_nvmap, fb_info->win->surface);
+ if (fb_info->win->cur_handle) {
+ nvmap_unpin(fb_info->fb_nvmap, fb_info->win->cur_handle);
+ nvmap_free(fb_info->fb_nvmap, fb_info->win->cur_handle);
}
if (fb_info->fb_nvmap)
diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c
index c2dfe3156df3..c1cfd6ee229c 100644
--- a/drivers/video/tegra/host/debug.c
+++ b/drivers/video/tegra/host/debug.c
@@ -48,19 +48,19 @@ static int nvhost_debug_handle_cmd(struct seq_file *s, u32 val, int *count)
}
case 0x1:
- seq_printf(s, "INCR(offset=%03x, [", val >> 16 & 0x3ff);
+ seq_printf(s, "INCR(offset=%03x, [", val >> 16 & 0xfff);
*count = val & 0xffff;
return NVHOST_DBG_STATE_DATA;
case 0x2:
- seq_printf(s, "NOMINCR(offset=%03x, [", val >> 16 & 0x3ff);
+ seq_printf(s, "NONINCR(offset=%03x, [", val >> 16 & 0xfff);
*count = val & 0xffff;
return NVHOST_DBG_STATE_DATA;
case 0x3:
mask = val & 0xffff;
seq_printf(s, "MASK(offset=%03x, mask=%03x, [",
- val >> 16 & 0x3ff, mask);
+ val >> 16 & 0xfff, mask);
*count = hweight16(mask);
return NVHOST_DBG_STATE_DATA;
@@ -100,6 +100,33 @@ static int nvhost_debug_handle_cmd(struct seq_file *s, u32 val, int *count)
}
}
+static void nvhost_debug_handle_word(struct seq_file *s, int *state, int *count,
+ unsigned long addr, int channel, u32 val)
+{
+ switch (*state) {
+ case NVHOST_DBG_STATE_CMD:
+ if (addr)
+ seq_printf(s, "%d: %08x: %08x:", channel, addr, val);
+ else
+ seq_printf(s, "%d: %08x:", channel, val);
+
+ *state = nvhost_debug_handle_cmd(s, val, count);
+ if (*state == NVHOST_DBG_STATE_DATA && *count == 0) {
+ *state = NVHOST_DBG_STATE_CMD;
+ seq_printf(s, "])\n");
+ }
+ break;
+
+ case NVHOST_DBG_STATE_DATA:
+ (*count)--;
+ seq_printf(s, "%08x%s", val, *count > 0 ? ", " : "])\n");
+ if (*count == 0)
+ *state = NVHOST_DBG_STATE_CMD;
+ break;
+ }
+}
+
+
static int nvhost_debug_show(struct seq_file *s, void *unused)
{
struct nvhost_master *m = s->private;
@@ -116,7 +143,8 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
unsigned start, end;
unsigned wr_ptr, rd_ptr;
int state;
- int count = 0;
+ int count;
+ u32 phys_addr, size;
dmaput = readl(regs + HOST1X_CHANNEL_DMAPUT);
dmaget = readl(regs + HOST1X_CHANNEL_DMAGET);
@@ -151,9 +179,35 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
break;
}
+ nvhost_cdma_find_gather(&m->channels[i].cdma, dmaget, &phys_addr, &size);
+
+ /* If dmaget is in the pushbuffer (should always be?),
+ * check if we're executing a fetch, and if so dump
+ * it. */
+ if (size) {
+ u32 offset = dmaget - m->channels[i].cdma.push_buffer.phys;
+ u32 map_base = phys_addr & PAGE_MASK;
+ u32 map_size = (size * 4 + PAGE_SIZE - 1) & PAGE_MASK;
+ u32 map_offset = phys_addr - map_base;
+ void *map_addr = ioremap_nocache(map_base, map_size);
+
+ if (map_addr) {
+ u32 ii;
+
+ seq_printf(s, "\n%d: gather (%d words)\n", i, size);
+ state = NVHOST_DBG_STATE_CMD;
+ for (ii = 0; ii < size; ii++) {
+ val = readl(map_addr + map_offset + ii*sizeof(u32));
+ nvhost_debug_handle_word(s, &state, &count, phys_addr + ii, i, val);
+ }
+ iounmap(map_addr);
+ }
+ }
+
fifostat = readl(regs + HOST1X_CHANNEL_FIFOSTAT);
if ((fifostat & 1 << 10) == 0 ) {
+ seq_printf(s, "\n%d: fifo:\n", i);
writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
writel(1 << 31 | i << 16, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
rd_ptr = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS) & 0x1ff;
@@ -169,24 +223,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
writel(1 << 31 | i << 16 | rd_ptr, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
val = readl(m->aperture + HOST1X_SYNC_CFPEEK_READ);
- switch (state) {
- case NVHOST_DBG_STATE_CMD:
- seq_printf(s, "%d: %08x:", i, val);
-
- state = nvhost_debug_handle_cmd(s, val, &count);
- if (state == NVHOST_DBG_STATE_DATA && count == 0) {
- state = NVHOST_DBG_STATE_CMD;
- seq_printf(s, "])\n");
- }
- break;
-
- case NVHOST_DBG_STATE_DATA:
- count--;
- seq_printf(s, "%08x%s", val, count > 0 ? ", " : "])\n");
- if (count == 0)
- state = NVHOST_DBG_STATE_CMD;
- break;
- }
+ nvhost_debug_handle_word(s, &state, &count, 0, i, val);
if (rd_ptr == end)
rd_ptr = start;
@@ -199,6 +236,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
if (state == NVHOST_DBG_STATE_DATA)
seq_printf(s, ", ...])\n");
}
+
seq_printf(s, "\n");
}
diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c
index 4b90456696ad..f27656bac07b 100644
--- a/drivers/video/tegra/host/nvhost_cdma.c
+++ b/drivers/video/tegra/host/nvhost_cdma.c
@@ -627,3 +627,24 @@ void nvhost_cdma_flush(struct nvhost_cdma *cdma)
}
mutex_unlock(&cdma->lock);
}
+
+/**
+ * Find the currently executing gather in the push buffer and return
+ * its physical address and size.
+ */
+void nvhost_cdma_find_gather(struct nvhost_cdma *cdma, u32 dmaget, u32 *addr, u32 *size)
+{
+ u32 offset = dmaget - cdma->push_buffer.phys;
+
+ *addr = *size = 0;
+
+ if (offset >= 8 && offset < cdma->push_buffer.cur) {
+ u32 *p = cdma->push_buffer.mapped + (offset - 8) / 4;
+
+ /* Make sure we have a gather */
+ if ((p[0] >> 28) == 6) {
+ *addr = p[1];
+ *size = p[0] & 0x3fff;
+ }
+ }
+}
diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h
index 77493abe0e27..a7f17d0413d5 100644
--- a/drivers/video/tegra/host/nvhost_cdma.h
+++ b/drivers/video/tegra/host/nvhost_cdma.h
@@ -97,5 +97,7 @@ void nvhost_cdma_end(struct nvmap_client *user_nvmap,
struct nvmap_handle **handles, unsigned int nr_handles);
void nvhost_cdma_update(struct nvhost_cdma *cdma);
void nvhost_cdma_flush(struct nvhost_cdma *cdma);
+void nvhost_cdma_find_gather(struct nvhost_cdma *cdma, u32 dmaget,
+ u32 *addr, u32 *size);
#endif
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index 7419731a7c52..506aef8408a9 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -225,12 +225,17 @@ int nvmap_pin_ids(struct nvmap_client *client,
if (ref) {
atomic_inc(&ref->pin);
nvmap_handle_get(h[i]);
- } else if (!client->super && (h[i]->owner != client) &&
- !h[i]->global) {
- ret = -EPERM;
} else {
- nvmap_warn(client, "%s pinning unreferenced handle "
- "%p\n", current->group_leader->comm, h[i]);
+ struct nvmap_handle *verify;
+ nvmap_ref_unlock(client);
+ verify = nvmap_validate_get(client, ids[i]);
+ if (verify)
+ nvmap_warn(client, "%s pinning unreferenced "
+ "handle %p\n",
+ current->group_leader->comm, h[i]);
+ else
+ ret = -EPERM;
+ nvmap_ref_lock(client);
}
}
nvmap_ref_unlock(client);
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index b84a788dd33b..c6669ed86c24 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -353,6 +353,8 @@ struct nvmap_handle *nvmap_validate_get(struct nvmap_client *client,
if ((unsigned long)h == id) {
if (client->super || h->global || (h->owner == client))
h = nvmap_handle_get(h);
+ else
+ h = NULL;
spin_unlock(&client->dev->handle_lock);
return h;
}
@@ -696,9 +698,9 @@ static int nvmap_probe(struct platform_device *pdev)
dev->dev_user.parent = &pdev->dev;
dev->dev_super.minor = MISC_DYNAMIC_MINOR;
- dev->dev_super.name = "kvmap";
- dev->dev_user.fops = &nvmap_super_fops;
- dev->dev_user.parent = &pdev->dev;
+ dev->dev_super.name = "knvmap";
+ dev->dev_super.fops = &nvmap_super_fops;
+ dev->dev_super.parent = &pdev->dev;
dev->handles = RB_ROOT;
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index eed3403db02d..21cbf9c4d85d 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -38,7 +38,7 @@
#include "nvmap_mru.h"
#define NVMAP_SECURE_HEAPS (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_IOVMM)
-#define GFP_NVMAP (GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN)
+#define GFP_NVMAP (__GFP_HIGHMEM | __GFP_NOWARN)
/* handles may be arbitrarily large (16+MiB), and any handle allocated from
* the kernel (i.e., not a carveout handle) includes its array of pages. to
* preserve kmalloc space, if the array of pages exceeds PAGELIST_VMALLOC_MIN,
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index 9051803aa68d..b943065a44c0 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -459,7 +459,8 @@ static int cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
}
if (h->flags == NVMAP_HANDLE_UNCACHEABLE ||
- h->flags == NVMAP_HANDLE_WRITE_COMBINE)
+ h->flags == NVMAP_HANDLE_WRITE_COMBINE ||
+ start == end)
goto out;
if (WARN_ON_ONCE(op == NVMAP_CACHE_OP_WB_INV))
@@ -607,7 +608,7 @@ static ssize_t rw_handle(struct nvmap_client *client, struct nvmap_handle *h,
return PTR_ERR(pte);
while (count--) {
- if (h_offs + elem_size >= h->size) {
+ if (h_offs + elem_size > h->size) {
nvmap_warn(client, "read/write outside of handle\n");
ret = -EFAULT;
break;