From 2c45b9ceabce36f6873f227c09bedc2be9b3ca00 Mon Sep 17 00:00:00 2001 From: Kirill Artamonov Date: Mon, 30 Jan 2012 23:08:37 +0200 Subject: video: tegra: remove free memory check Used free memory check in allocation policy is not working, because it doesn't calculate available physical memory size in same way as android oom killer. It also breaks kernel build if swapping is enabled. Remove free memory check from allocation policy. Change-Id: I214d1829451f313dbace967e87ed4111e688865d Reviewed-on: http://git-master/r/85227 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/video/tegra/nvmap/nvmap_handle.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index 2f24ba515862..2e2b8b3d46a1 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -38,11 +38,8 @@ #include #include -#include -#include #include #include - #include "nvmap.h" #include "nvmap_mru.h" #include "nvmap_common.h" @@ -751,10 +748,6 @@ static const unsigned int heap_policy_large[] = { 0, }; -/* Do not override single page policy if there is not much space to -avoid invoking system oom killer. */ -#define NVMAP_SMALL_POLICY_SYSMEM_THRESHOLD 50000000 - int nvmap_alloc_handle_id(struct nvmap_client *client, unsigned long id, unsigned int heap_mask, size_t align, unsigned int flags) @@ -792,15 +785,7 @@ int nvmap_alloc_handle_id(struct nvmap_client *client, if (heap_mask & NVMAP_HEAP_IOVMM) heap_mask |= NVMAP_HEAP_SYSMEM; else if (heap_mask & NVMAP_HEAP_CARVEOUT_GENERIC) { - /* Calculate size of free physical pages - * managed by kernel */ - unsigned long freeMem = - (global_page_state(NR_FREE_PAGES) + - global_page_state(NR_FILE_PAGES) - - total_swapcache_pages) << PAGE_SHIFT; - - if (freeMem > NVMAP_SMALL_POLICY_SYSMEM_THRESHOLD) - heap_mask |= NVMAP_HEAP_SYSMEM; + heap_mask |= NVMAP_HEAP_SYSMEM; } } #endif -- cgit v1.2.3 From 5abc30ce92eee652cdadc3f88f1496d6941affe6 Mon Sep 17 00:00:00 2001 From: Preetham Chandru Date: Mon, 16 Apr 2012 13:18:57 +0530 Subject: video: tegra: dsi: enable dsi panel B Enable dsi panel B by setting the first bit in APB_MISC_GP_MIPI_PAD_CTRL_0 register. Bug 935764 Signed-off-by: Preetham Chandru R Change-Id: I9e958e0c9d9e934edf77688fd6a987b5e863392b Reviewed-on: http://git-master/r/96672 Reviewed-by: Shashank Sharma Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Kiran Adduri Reviewed-by: Animesh Kishore Reviewed-by: Laxman Dewangan --- drivers/video/tegra/dc/dsi.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c index 69cc60f70f1c..e402c416b779 100644 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c @@ -1,7 +1,7 @@ /* * drivers/video/tegra/dc/dsi.c * - * Copyright (c) 2011, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA Corporation. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "dc_reg.h" @@ -38,6 +39,9 @@ #include "dsi_regs.h" #include "dsi.h" +#define APB_MISC_GP_MIPI_PAD_CTRL_0 (TEGRA_APB_MISC_BASE + 0x820) +#define DSIB_MODE_ENABLE 0x2 + #define DSI_USE_SYNC_POINTS 1 #define S_TO_MS(x) (1000 * (x)) @@ -1621,6 +1625,15 @@ static void tegra_dsi_pad_calibration(struct tegra_dc_dsi_data *dsi) tegra_vi_csi_writel(val, CSI_CIL_PAD_CONFIG); } +static void tegra_dsi_panelB_enable() +{ + unsigned int val; + + val = readl(IO_ADDRESS(APB_MISC_GP_MIPI_PAD_CTRL_0)); + val |= DSIB_MODE_ENABLE; + writel(val, (IO_ADDRESS(APB_MISC_GP_MIPI_PAD_CTRL_0))); +} + static int tegra_dsi_init_hw(struct tegra_dc *dc, struct tegra_dc_dsi_data *dsi) { @@ -1634,7 +1647,7 @@ static int tegra_dsi_init_hw(struct tegra_dc *dc, tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_lp_clk_khz); if (dsi->info.dsi_instance) { - /* TODO:Set the misc register*/ + tegra_dsi_panelB_enable(); } /* TODO: only need to change the timing for bta */ -- cgit v1.2.3 From 1953361f8e492ea6ec5de23a5321a8eaf000563e Mon Sep 17 00:00:00 2001 From: Jon Mayo Date: Tue, 22 May 2012 17:24:27 -0700 Subject: video: tegra: detect fbmem alignment on probe Detect the stride size used by the bootloader. If DC is not enabled, fallback to a default stride size. Bug 973111 Change-Id: If04647ddf04a44987cd841062ff30e03fa4d6a02 Signed-off-by: Jon Mayo Reviewed-on: http://git-master/r/104031 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/video/tegra/dc/dc.c | 17 +++++++++++++++++ drivers/video/tegra/dc/dc_reg.h | 2 ++ drivers/video/tegra/fb.c | 12 ++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index fb171549f78d..935f18bc8cfd 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -583,6 +583,23 @@ static unsigned int tegra_dc_has_multiple_dc(void) return (cnt > 1); } +/* get the stride size of a window. + * return: stride size in bytes for window win. or 0 if unavailble. */ +int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win) +{ + u32 tmp; + u32 stride; + + if (!dc->enabled) + return 0; + BUG_ON(win > DC_N_WINDOWS); + tegra_dc_writel(dc, WINDOW_A_SELECT << win, + DC_CMD_DISPLAY_WINDOW_HEADER); + tmp = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE); + return GET_LINE_STRIDE(tmp); +} +EXPORT_SYMBOL(tegra_dc_get_stride); + struct tegra_dc *tegra_dc_get_dc(unsigned idx) { if (idx < TEGRA_MAX_DC) diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h index 8b84bff45eb3..5eac27adfbf8 100644 --- a/drivers/video/tegra/dc/dc_reg.h +++ b/drivers/video/tegra/dc/dc_reg.h @@ -430,6 +430,8 @@ #define DC_WIN_LINE_STRIDE 0x70a #define LINE_STRIDE(x) (x) #define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16) +#define GET_LINE_STRIDE(x) ((x) & 0xffff) +#define GET_UV_LINE_STRIDE(x) (((x) >> 16) & 0xffff) #define DC_WIN_BUF_STRIDE 0x70b #define DC_WIN_UV_BUF_STRIDE 0x70c #define DC_WIN_BUFFER_ADDR_MODE 0x70d diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 50aa9b383059..1193a2eb8c52 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -44,7 +44,7 @@ #include "dc/dc_priv.h" /* Pad pitch to 16-byte boundary. */ -#define TEGRA_LINEAR_PITCH_ALIGNMENT 16 +#define TEGRA_LINEAR_PITCH_ALIGNMENT 32 struct tegra_fb_info { struct tegra_dc_win *win; @@ -527,6 +527,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, unsigned long fb_size = 0; unsigned long fb_phys = 0; int ret = 0; + unsigned stride; win = tegra_dc_get_window(dc, fb_data->win); if (!win) { @@ -560,6 +561,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, tegra_fb->valid = true; } + stride = tegra_dc_get_stride(dc, 0); + if (!stride) /* default to pad the stride to 16-byte boundary. */ + stride = round_up(info->fix.line_length, + TEGRA_LINEAR_PITCH_ALIGNMENT); + info->fbops = &tegra_fb_ops; info->pseudo_palette = pseudo_palette; info->screen_base = fb_base; @@ -574,9 +580,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, info->fix.smem_start = fb_phys; info->fix.smem_len = fb_size; info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8; - /* Pad the stride to 16-byte boundary. */ - info->fix.line_length = round_up(info->fix.line_length, - TEGRA_LINEAR_PITCH_ALIGNMENT); + info->fix.line_length = stride; info->var.xres = fb_data->xres; info->var.yres = fb_data->yres; -- cgit v1.2.3 From dfa3030e767dca384f5d159c6993d5ee25b416d7 Mon Sep 17 00:00:00 2001 From: Mayuresh Kulkarni Date: Mon, 9 Apr 2012 12:21:24 +0530 Subject: video: tegra: host: rewrite nvhost_job_pin/unpin APIs - remove usage of custom interface of nvmap to patch the relocs and and pin the gathers/relocs - convert code that references nvmap_handle to nvmap_handle_ref - add logic to pin and map only unique gathers and relocs - rename nvhost_channel_gather to nvhost_job_gather, because it's used in nvhost_job code only Bug 965206 Change-Id: Iaa7fbac9e4a7b08c0a7c1e184b8dd3566e1edfe2 Signed-off-by: Mayuresh Kulkarni Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/95299 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Juha Tukkinen --- drivers/video/tegra/host/bus_client.c | 17 +- drivers/video/tegra/host/chip_support.h | 4 +- drivers/video/tegra/host/gr3d/gr3d_t20.c | 2 +- drivers/video/tegra/host/gr3d/gr3d_t30.c | 2 +- drivers/video/tegra/host/host1x/host1x_cdma.c | 2 +- drivers/video/tegra/host/host1x/host1x_channel.c | 4 +- drivers/video/tegra/host/host1x/host1x_debug.c | 17 +- drivers/video/tegra/host/mpe/mpe.c | 2 +- drivers/video/tegra/host/nvhost_cdma.c | 12 +- drivers/video/tegra/host/nvhost_cdma.h | 4 +- drivers/video/tegra/host/nvhost_channel.h | 7 - drivers/video/tegra/host/nvhost_job.c | 285 +++++++++-------------- drivers/video/tegra/host/nvhost_job.h | 27 +-- 13 files changed, 157 insertions(+), 228 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c index fd632a6ea9c5..822f8f3a456d 100644 --- a/drivers/video/tegra/host/bus_client.c +++ b/drivers/video/tegra/host/bus_client.c @@ -166,7 +166,7 @@ static int set_submit(struct nvhost_channel_userctx *ctx) return -EFAULT; } - ctx->job = nvhost_job_realloc(ctx->job, + ctx->job = nvhost_job_alloc(ctx->ch, ctx->hwctx, &ctx->hdr, ctx->nvmap, @@ -241,13 +241,17 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf, consumed = sizeof(struct nvhost_reloc); if (remaining < consumed) break; - if (copy_from_user(&job->pinarray[job->num_pins], + if (copy_from_user(&job->pinarray[job->num_relocs], buf, consumed)) { err = -EFAULT; break; } - trace_nvhost_channel_write_reloc(chname); - job->num_pins++; + trace_nvhost_channel_write_reloc(chname, + job->pinarray[job->num_relocs].patch_mem, + job->pinarray[job->num_relocs].patch_offset, + job->pinarray[job->num_relocs].pin_mem, + job->pinarray[job->num_relocs].pin_offset); + job->num_relocs++; hdr->num_relocs--; } else if (hdr->num_waitchks) { int numwaitchks = @@ -269,7 +273,7 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf, hdr->num_waitchks -= numwaitchks; } else if (priv->num_relocshifts) { int next_shift = - job->num_pins - priv->num_relocshifts; + job->num_relocs - priv->num_relocshifts; consumed = sizeof(struct nvhost_reloc_shift); if (remaining < consumed) break; @@ -337,6 +341,9 @@ static int nvhost_ioctl_channel_flush( if (err) nvhost_job_unpin(ctx->job); + nvhost_job_put(ctx->job); + ctx->job = NULL; + return err; } diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index edc5f6a51574..173a36065458 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -31,7 +31,7 @@ struct nvhost_syncpt; struct nvhost_waitchk; struct nvhost_userctx_timeout; struct nvhost_channel; -struct nvmap_handle; +struct nvmap_handle_ref; struct nvmap_client; struct nvhost_hwctx; struct nvhost_cdma; @@ -77,7 +77,7 @@ struct nvhost_chip_support { void (*destroy)(struct push_buffer *); void (*push_to)(struct push_buffer *, struct nvmap_client *, - struct nvmap_handle *, + struct nvmap_handle_ref *, u32 op1, u32 op2); void (*pop_from)(struct push_buffer *, unsigned int slots); diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c index c0efac03b882..5645f5b2b0c6 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t20.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c @@ -138,7 +138,7 @@ static void save_push_v0(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) nvhost_cdma_push_gather(cdma, nvhost_get_host(nctx->channel->dev)->nvmap, - p->save_buf->handle, + p->save_buf, 0, nvhost_opcode_gather(p->save_size), p->save_phys); diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c index 93d98dfa645c..57f4c779eff8 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t30.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c @@ -145,7 +145,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) /* gather the save buffer */ nvhost_cdma_push_gather(cdma, nvhost_get_host(nctx->channel->dev)->nvmap, - p->save_buf->handle, + p->save_buf, 0, nvhost_opcode_gather(p->save_size), p->save_phys); diff --git a/drivers/video/tegra/host/host1x/host1x_cdma.c b/drivers/video/tegra/host/host1x/host1x_cdma.c index fcb1f05f0025..4569c3d62494 100644 --- a/drivers/video/tegra/host/host1x/host1x_cdma.c +++ b/drivers/video/tegra/host/host1x/host1x_cdma.c @@ -137,7 +137,7 @@ static void push_buffer_destroy(struct push_buffer *pb) */ static void push_buffer_push_to(struct push_buffer *pb, struct nvmap_client *client, - struct nvmap_handle *handle, u32 op1, u32 op2) + struct nvmap_handle_ref *handle, u32 op1, u32 op2) { u32 cur = pb->cur; u32 *p = (u32 *)((u32)pb->mapped + cur); diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c index 8c4a7a5c74ad..0b4d07cb9e47 100644 --- a/drivers/video/tegra/host/host1x/host1x_channel.c +++ b/drivers/video/tegra/host/host1x/host1x_channel.c @@ -143,7 +143,7 @@ static void submit_ctxrestore(struct nvhost_job *job) /* Send restore buffer to channel */ nvhost_cdma_push_gather(&ch->cdma, host->nvmap, - nvmap_ref_to_handle(ctx->restore), + ctx->restore, 0, nvhost_opcode_gather(ctx->restore_size), ctx->restore_phys); @@ -188,7 +188,7 @@ void submit_gathers(struct nvhost_job *job) u32 op2 = job->gathers[i].mem; nvhost_cdma_push_gather(&job->ch->cdma, job->nvmap, - nvmap_id_to_handle(job->gathers[i].mem_id), + job->gathers[i].ref, job->gathers[i].offset, op1, op2); } diff --git a/drivers/video/tegra/host/host1x/host1x_debug.c b/drivers/video/tegra/host/host1x/host1x_debug.c index 76483d82528b..a5574a0fb60a 100644 --- a/drivers/video/tegra/host/host1x/host1x_debug.c +++ b/drivers/video/tegra/host/host1x/host1x_debug.c @@ -169,32 +169,27 @@ static void show_channel_gather(struct output *o, u32 addr, struct push_buffer *pb = &cdma->push_buffer; u32 cur = addr - pb->phys; struct nvmap_client_handle *nvmap = &pb->nvmap[cur/8]; - struct nvmap_handle_ref ref; u32 *map_addr, offset; phys_addr_t pin_addr; int state, count, i; if (!nvmap->handle || !nvmap->client - || atomic_read(&nvmap->handle->ref) < 1) { + || atomic_read(&nvmap->handle->handle->ref) < 1) { nvhost_debug_output(o, "[already deallocated]\n"); return; } - /* Create a fake nvmap_handle_ref - nvmap requires it - * but accesses only the first field - nvmap_handle */ - ref.handle = nvmap->handle; - - map_addr = nvmap_mmap(&ref); + map_addr = nvmap_mmap(nvmap->handle); if (!map_addr) { nvhost_debug_output(o, "[could not mmap]\n"); return; } /* Get base address from nvmap */ - pin_addr = nvmap_pin(nvmap->client, &ref); + pin_addr = nvmap_pin(nvmap->client, nvmap->handle); if (IS_ERR_VALUE(pin_addr)) { nvhost_debug_output(o, "[couldn't pin]\n"); - nvmap_munmap(&ref, map_addr); + nvmap_munmap(nvmap->handle, map_addr); return; } @@ -215,8 +210,8 @@ static void show_channel_gather(struct output *o, u32 addr, *(map_addr + offset/4 + i), cdma); } - nvmap_unpin(nvmap->client, &ref); - nvmap_munmap(&ref, map_addr); + nvmap_unpin(nvmap->client, nvmap->handle); + nvmap_munmap(nvmap->handle, map_addr); #endif } diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c index d8c9da7e9a76..3fe2fcd8bb50 100644 --- a/drivers/video/tegra/host/mpe/mpe.c +++ b/drivers/video/tegra/host/mpe/mpe.c @@ -502,7 +502,7 @@ static void ctxmpe_save_push(struct nvhost_hwctx *nctx, struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx); nvhost_cdma_push_gather(cdma, nvhost_get_host(nctx->channel->dev)->nvmap, - h->save_buf->handle, + h->save_buf, 0, nvhost_opcode_gather(h->save_size), h->save_phys); diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c index a72e18f16ac7..b1f138317cc1 100644 --- a/drivers/video/tegra/host/nvhost_cdma.c +++ b/drivers/video/tegra/host/nvhost_cdma.c @@ -371,15 +371,13 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job) } static void trace_write_gather(struct nvhost_cdma *cdma, - struct nvmap_handle *handle, + struct nvmap_handle_ref *ref, u32 offset, u32 words) { - struct nvmap_handle_ref ref; void *mem = NULL; if (nvhost_debug_trace_cmdbuf) { - ref.handle = handle; - mem = nvmap_mmap(&ref); + mem = nvmap_mmap(ref); if (IS_ERR_OR_NULL(mem)) mem = NULL; }; @@ -393,12 +391,12 @@ static void trace_write_gather(struct nvhost_cdma *cdma, for (i = 0; i < words; i += TRACE_MAX_LENGTH) { trace_nvhost_cdma_push_gather( cdma_to_channel(cdma)->dev->name, - (u32)handle, + (u32)ref->handle, min(words - i, TRACE_MAX_LENGTH), offset + i * sizeof(u32), mem); } - nvmap_munmap(&ref, mem); + nvmap_munmap(ref, mem); } } @@ -421,7 +419,7 @@ void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2) */ void nvhost_cdma_push_gather(struct nvhost_cdma *cdma, struct nvmap_client *client, - struct nvmap_handle *handle, + struct nvmap_handle_ref *handle, u32 offset, u32 op1, u32 op2) { u32 slots_free = cdma->slots_free; diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h index e6f51179150f..98393f0cc765 100644 --- a/drivers/video/tegra/host/nvhost_cdma.h +++ b/drivers/video/tegra/host/nvhost_cdma.h @@ -48,7 +48,7 @@ struct nvhost_job; struct nvmap_client_handle { struct nvmap_client *client; - struct nvmap_handle *handle; + struct nvmap_handle_ref *handle; }; struct push_buffer { @@ -113,7 +113,7 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job); void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2); void nvhost_cdma_push_gather(struct nvhost_cdma *cdma, struct nvmap_client *client, - struct nvmap_handle *handle, u32 offset, u32 op1, u32 op2); + struct nvmap_handle_ref *handle, u32 offset, u32 op1, u32 op2); void nvhost_cdma_end(struct nvhost_cdma *cdma, struct nvhost_job *job); void nvhost_cdma_update(struct nvhost_cdma *cdma); diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h index eac51731547b..a8f16f0c5abc 100644 --- a/drivers/video/tegra/host/nvhost_channel.h +++ b/drivers/video/tegra/host/nvhost_channel.h @@ -36,13 +36,6 @@ struct nvhost_device; struct nvhost_channel; struct nvhost_hwctx; -struct nvhost_channel_gather { - u32 words; - phys_addr_t mem; - u32 mem_id; - int offset; -}; - struct nvhost_channel { int refcount; int chid; diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c index 71f2ab0e751f..11d65964e2c9 100644 --- a/drivers/video/tegra/host/nvhost_job.c +++ b/drivers/video/tegra/host/nvhost_job.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "nvhost_channel.h" #include "nvhost_job.h" #include "nvhost_hwctx.h" @@ -33,128 +34,41 @@ static int job_size(struct nvhost_submit_hdr_ext *hdr) { - int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0; + int num_relocs = hdr ? hdr->num_relocs : 0; int num_waitchks = hdr ? hdr->num_waitchks : 0; + int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0; + int num_unpins = num_cmdbufs + num_relocs; return sizeof(struct nvhost_job) - + num_pins * sizeof(struct nvmap_pinarray_elem) - + num_pins * sizeof(struct nvmap_handle *) - + num_waitchks * sizeof(struct nvhost_waitchk); -} - -static int gather_size(int num_cmdbufs) -{ - return num_cmdbufs * sizeof(struct nvhost_channel_gather); -} - -static void free_gathers(struct nvhost_job *job) -{ - if (job->gathers) { - nvmap_munmap(job->gather_mem, job->gathers); - job->gathers = NULL; - } - if (job->gather_mem) { - nvmap_free(job->nvmap, job->gather_mem); - job->gather_mem = NULL; - } -} - -static int alloc_gathers(struct nvhost_job *job, - int num_cmdbufs) -{ - int err = 0; - - job->gather_mem = NULL; - job->gathers = NULL; - job->gather_mem_size = 0; - - if (num_cmdbufs) { - /* Allocate memory */ - job->gather_mem = nvmap_alloc(job->nvmap, - gather_size(num_cmdbufs), - 32, NVMAP_HANDLE_CACHEABLE, 0); - if (IS_ERR_OR_NULL(job->gather_mem)) { - err = job->gather_mem ? PTR_ERR(job->gather_mem) : -ENOMEM; - job->gather_mem = NULL; - goto error; - } - job->gather_mem_size = gather_size(num_cmdbufs); - - /* Map memory to kernel */ - job->gathers = nvmap_mmap(job->gather_mem); - if (IS_ERR_OR_NULL(job->gathers)) { - err = job->gathers ? PTR_ERR(job->gathers) : -ENOMEM; - job->gathers = NULL; - goto error; - } - } - - return 0; - -error: - free_gathers(job); - return err; -} - -static int realloc_gathers(struct nvhost_job *oldjob, - struct nvhost_job *newjob, - int num_cmdbufs) -{ - int err = 0; - - /* Check if we can reuse gather buffer */ - if (oldjob->gather_mem_size < gather_size(num_cmdbufs) - || oldjob->nvmap != newjob->nvmap) { - free_gathers(oldjob); - err = alloc_gathers(newjob, num_cmdbufs); - } else { - newjob->gather_mem = oldjob->gather_mem; - newjob->gathers = oldjob->gathers; - newjob->gather_mem_size = oldjob->gather_mem_size; - - oldjob->gather_mem = NULL; - oldjob->gathers = NULL; - oldjob->gather_mem_size = 0; - } - return err; + + num_relocs * sizeof(struct nvmap_pinarray_elem) + + num_unpins * sizeof(struct nvmap_handle_ref *) + + num_waitchks * sizeof(struct nvhost_waitchk) + + num_cmdbufs * sizeof(struct nvhost_job_gather); } static void init_fields(struct nvhost_job *job, struct nvhost_submit_hdr_ext *hdr, int priority, int clientid) { - int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0; + int num_relocs = hdr ? hdr->num_relocs : 0; int num_waitchks = hdr ? hdr->num_waitchks : 0; + int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0; + int num_unpins = num_cmdbufs + num_relocs; void *mem = job; /* First init state to zero */ - job->num_gathers = 0; - job->num_pins = 0; - job->num_unpins = 0; - job->num_waitchk = 0; - job->waitchk_mask = 0; - job->syncpt_id = 0; - job->syncpt_incrs = 0; - job->syncpt_end = 0; job->priority = priority; job->clientid = clientid; - job->null_kickoff = false; - job->first_get = 0; - job->num_slots = 0; /* Redistribute memory to the structs */ mem += sizeof(struct nvhost_job); - if (num_pins) { - job->pinarray = mem; - mem += num_pins * sizeof(struct nvmap_pinarray_elem); - job->unpins = mem; - mem += num_pins * sizeof(struct nvmap_handle *); - } else { - job->pinarray = NULL; - job->unpins = NULL; - } - + job->pinarray = num_relocs ? mem : NULL; + mem += num_relocs * sizeof(struct nvmap_pinarray_elem); + job->unpins = num_unpins ? mem : NULL; + mem += num_unpins * sizeof(struct nvmap_handle_ref *); job->waitchk = num_waitchks ? mem : NULL; + mem += num_waitchks * sizeof(struct nvhost_waitchk); + job->gathers = num_cmdbufs ? mem : NULL; /* Copy information from header */ if (hdr) { @@ -172,8 +86,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, int clientid) { struct nvhost_job *job = NULL; - int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0; - int err = 0; job = vzalloc(job_size(hdr)); if (!job) @@ -186,10 +98,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, hwctx->h->get(hwctx); job->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL; - err = alloc_gathers(job, num_cmdbufs); - if (err) - goto error; - init_fields(job, hdr, priority, clientid); return job; @@ -200,46 +108,6 @@ error: return NULL; } -struct nvhost_job *nvhost_job_realloc( - struct nvhost_job *oldjob, - struct nvhost_hwctx *hwctx, - struct nvhost_submit_hdr_ext *hdr, - struct nvmap_client *nvmap, - int priority, int clientid) -{ - struct nvhost_job *newjob = NULL; - int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0; - int err = 0; - - newjob = vzalloc(job_size(hdr)); - if (!newjob) - goto error; - kref_init(&newjob->ref); - newjob->ch = oldjob->ch; - newjob->hwctx = hwctx; - if (hwctx) - newjob->hwctx->h->get(newjob->hwctx); - newjob->timeout = oldjob->timeout; - newjob->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL; - - err = realloc_gathers(oldjob, newjob, num_cmdbufs); - if (err) - goto error; - - nvhost_job_put(oldjob); - - init_fields(newjob, hdr, priority, clientid); - - return newjob; - -error: - if (newjob) - nvhost_job_put(newjob); - if (oldjob) - nvhost_job_put(oldjob); - return NULL; -} - void nvhost_job_get(struct nvhost_job *job) { kref_get(&job->ref); @@ -253,10 +121,6 @@ static void job_free(struct kref *ref) job->hwctxref->h->put(job->hwctxref); if (job->hwctx) job->hwctx->h->put(job->hwctx); - if (job->gathers) - nvmap_munmap(job->gather_mem, job->gathers); - if (job->gather_mem) - nvmap_free(job->nvmap, job->gather_mem); if (job->nvmap) nvmap_client_put(job->nvmap); vfree(job); @@ -280,42 +144,119 @@ void nvhost_job_put(struct nvhost_job *job) void nvhost_job_add_gather(struct nvhost_job *job, u32 mem_id, u32 words, u32 offset) { - struct nvmap_pinarray_elem *pin; - struct nvhost_channel_gather *cur_gather = + struct nvhost_job_gather *cur_gather = &job->gathers[job->num_gathers]; - pin = &job->pinarray[job->num_pins++]; - pin->patch_mem = (u32)nvmap_ref_to_handle(job->gather_mem); - pin->patch_offset = (void *)&(cur_gather->mem) - (void *)job->gathers; - pin->pin_mem = nvmap_convert_handle_u2k(mem_id); - pin->pin_offset = offset; cur_gather->words = words; cur_gather->mem_id = mem_id; cur_gather->offset = offset; job->num_gathers += 1; } -int nvhost_job_pin(struct nvhost_job *job) +static int do_relocs(struct nvhost_job *job, u32 patch_mem, void *patch_addr) { - int err = 0; + phys_addr_t pin_phys; + int i; + u32 mem_id = 0; + struct nvmap_handle_ref *pin_ref = NULL; + + /* pin & patch the relocs for one gather */ + for (i = 0; i < job->num_relocs; i++) { + struct nvmap_pinarray_elem *pin = &job->pinarray[i]; + + /* skip all other gathers */ + if (patch_mem != pin->patch_mem) + continue; + + /* check if pin-mem is same as previous */ + if (pin->pin_mem != mem_id) { + pin_ref = nvmap_duplicate_handle_id(job->nvmap, + pin->pin_mem); + if (IS_ERR(pin_ref)) + return PTR_ERR(pin_ref); + + pin_phys = nvmap_pin(job->nvmap, pin_ref); + if (IS_ERR((void *)pin_phys)) { + nvmap_free(job->nvmap, pin_ref); + return pin_phys; + } + + mem_id = pin->pin_mem; + job->unpins[job->num_unpins++] = pin_ref; + } + + __raw_writel((pin_phys + pin->pin_offset) >> pin->reloc_shift, + (patch_addr + pin->patch_offset)); + + /* Different gathers might have same mem_id. This ensures we + * perform reloc only once per gather memid. */ + pin->patch_mem = 0; + } + + return 0; +} - /* pin mem handles and patch physical addresses */ - job->num_unpins = nvmap_pin_array(job->nvmap, - nvmap_ref_to_handle(job->gather_mem), - job->pinarray, job->num_pins, - job->unpins); - if (job->num_unpins < 0) - err = job->num_unpins; +int nvhost_job_pin(struct nvhost_job *job) +{ + int err = 0, i = 0; + phys_addr_t gather_phys = 0; + void *gather_addr = NULL; + + /* pin gathers */ + for (i = 0; i < job->num_gathers; i++) { + struct nvhost_job_gather *g = &job->gathers[i]; + + /* process each gather mem only once */ + if (!g->ref) { + g->ref = nvmap_duplicate_handle_id(job->nvmap, + job->gathers[i].mem_id); + if (IS_ERR(g->ref)) { + err = PTR_ERR(g->ref); + g->ref = NULL; + break; + } + + gather_phys = nvmap_pin(job->nvmap, g->ref); + if (IS_ERR((void *)gather_phys)) { + nvmap_free(job->nvmap, g->ref); + err = gather_phys; + break; + } + + /* store the gather ref into unpin array */ + job->unpins[job->num_unpins++] = g->ref; + + gather_addr = nvmap_mmap(g->ref); + if (!gather_addr) { + err = -ENOMEM; + break; + } + + err = do_relocs(job, g->mem_id, gather_addr); + nvmap_munmap(g->ref, gather_addr); + + if (err) + break; + } + g->mem = gather_phys + g->offset; + } + wmb(); return err; } void nvhost_job_unpin(struct nvhost_job *job) { - nvmap_unpin_handles(job->nvmap, job->unpins, - job->num_unpins); + int i; + + for (i = 0; i < job->num_unpins; i++) { + nvmap_unpin(job->nvmap, job->unpins[i]); + nvmap_free(job->nvmap, job->unpins[i]); + } + memset(job->unpins, BAD_MAGIC, - job->num_unpins * sizeof(struct nvmap_handle *)); + job->num_unpins * sizeof(struct nvmap_handle_ref *)); + job->num_unpins = 0; } /** diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h index ad9d1af60da1..48555a231412 100644 --- a/drivers/video/tegra/host/nvhost_job.h +++ b/drivers/video/tegra/host/nvhost_job.h @@ -29,6 +29,14 @@ struct nvmap_client; struct nvhost_waitchk; struct nvmap_handle; +struct nvhost_job_gather { + u32 words; + phys_addr_t mem; + u32 mem_id; + int offset; + struct nvmap_handle_ref *ref; +}; + /* * Each submit is tracked as a nvhost_job. */ @@ -50,10 +58,8 @@ struct nvhost_job { struct nvmap_client *nvmap; /* Gathers and their memory */ - struct nvmap_handle_ref *gather_mem; - struct nvhost_channel_gather *gathers; + struct nvhost_job_gather *gathers; int num_gathers; - int gather_mem_size; /* Wait checks to be processed at submit time */ struct nvhost_waitchk *waitchk; @@ -62,8 +68,8 @@ struct nvhost_job { /* Array of handles to be pinned & unpinned */ struct nvmap_pinarray_elem *pinarray; - int num_pins; - struct nvmap_handle **unpins; + int num_relocs; + struct nvmap_handle_ref **unpins; int num_unpins; /* Sync point id, number of increments and end related to the submit */ @@ -98,17 +104,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch, struct nvmap_client *nvmap, int priority, int clientid); -/* - * Allocate memory for a job. Just enough memory will be allocated to - * accomodate the submit announced in submit header. Gather memory from - * oldjob will be reused, and nvhost_job_put() will be called to it. - */ -struct nvhost_job *nvhost_job_realloc(struct nvhost_job *oldjob, - struct nvhost_hwctx *hwctx, - struct nvhost_submit_hdr_ext *hdr, - struct nvmap_client *nvmap, - int priority, int clientid); - /* * Add a gather to a job. */ -- cgit v1.2.3 From 2285ec5a2c09d0f3e0469a65291ffe983918d112 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Tue, 22 May 2012 11:28:12 +0300 Subject: video: tegra: host: Improve timing of syncpt wait nvhost_syncpt_wait_timeout() relies on sync point interrupt to signal reaching the sync point value. With low timeout values, the resolution is not good enough and an error is returned even when the value is reached. Update syncpoint value from hardware when doing a sync point wait and do an explicit check for reaching the value even if wait returns a timeout. bug 984166 bug 986788 bug 987597 Change-Id: I640e32cdcdfa66b8977eac273dd32f62bd72abd6 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/103827 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Mayuresh Kulkarni Reviewed-by: Juha Tukkinen --- drivers/video/tegra/host/nvhost_syncpt.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c index 4835d22881b8..1458a7cb5acc 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.c +++ b/drivers/video/tegra/host/nvhost_syncpt.c @@ -129,6 +129,19 @@ void nvhost_syncpt_incr(struct nvhost_syncpt *sp, u32 id) nvhost_module_idle(syncpt_to_dev(sp)->dev); } +/** + * Updated sync point form hardware, and returns true if syncpoint is expired, + * false if we may need to wait + */ +static bool syncpt_update_min_is_expired( + struct nvhost_syncpt *sp, + u32 id, + u32 thresh) +{ + syncpt_op().update_min(sp, id); + return nvhost_syncpt_is_expired(sp, id, thresh); +} + /** * Main entrypoint for syncpoint value waits. */ @@ -190,9 +203,9 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id, while (timeout) { u32 check = min_t(u32, SYNCPT_CHECK_PERIOD, timeout); int remain = wait_event_interruptible_timeout(wq, - nvhost_syncpt_is_expired(sp, id, thresh), + syncpt_update_min_is_expired(sp, id, thresh), check); - if (remain > 0) { + if (remain > 0 || nvhost_syncpt_is_expired(sp, id, thresh)) { if (value) *value = nvhost_syncpt_read_min(sp, id); err = 0; -- cgit v1.2.3 From c20772878b3e88a31ef3021e8030d2c20a2daa19 Mon Sep 17 00:00:00 2001 From: Krishna Reddy Date: Tue, 22 May 2012 11:36:03 -0700 Subject: video: tegra: nvmap: Change function declaration order. Change function declaration order to avoid multiple CONFIG_TEGRA_NVMAP #ifdef's. Change-Id: Icb10380f8da4b8037b90e787f961a28e8528814f Signed-off-by: Krishna Reddy Reviewed-on: http://git-master/r/103990 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Bo Yan Reviewed-by: Jon Mayo --- drivers/video/tegra/nvmap/nvmap.h | 86 +++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/nvmap/nvmap.h b/drivers/video/tegra/nvmap/nvmap.h index b0fb70f64a5c..25403f5e7098 100644 --- a/drivers/video/tegra/nvmap/nvmap.h +++ b/drivers/video/tegra/nvmap/nvmap.h @@ -37,6 +37,8 @@ struct nvmap_device; struct page; struct tegra_iovmm_area; +void _nvmap_handle_free(struct nvmap_handle *h); + #if defined(CONFIG_TEGRA_NVMAP) #define nvmap_err(_client, _fmt, ...) \ dev_err(nvmap_client_to_device(_client), \ @@ -162,7 +164,46 @@ static inline void nvmap_ref_unlock(struct nvmap_client *priv) { mutex_unlock(&priv->ref_lock); } -#endif /* CONFIG_TEGRA_NVMAP */ + +static inline struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h) +{ + if (unlikely(atomic_inc_return(&h->ref) <= 1)) { + pr_err("%s: %s getting a freed handle\n", + __func__, current->group_leader->comm); + if (atomic_read(&h->ref) <= 0) + return NULL; + } + return h; +} + +static inline void nvmap_handle_put(struct nvmap_handle *h) +{ + int cnt = atomic_dec_return(&h->ref); + + if (WARN_ON(cnt < 0)) { + pr_err("%s: %s put to negative references\n", + __func__, current->comm); + } else if (cnt == 0) + _nvmap_handle_free(h); +} + +static inline pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot) +{ + if (h->flags == NVMAP_HANDLE_UNCACHEABLE) + return pgprot_noncached(prot); + else if (h->flags == NVMAP_HANDLE_WRITE_COMBINE) + return pgprot_writecombine(prot); + else if (h->flags == NVMAP_HANDLE_INNER_CACHEABLE) + return pgprot_inner_writeback(prot); + return prot; +} + +#else /* CONFIG_TEGRA_NVMAP */ +struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h); +void nvmap_handle_put(struct nvmap_handle *h); +pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot); + +#endif /* !CONFIG_TEGRA_NVMAP */ struct device *nvmap_client_to_device(struct nvmap_client *client); @@ -216,51 +257,10 @@ int nvmap_pin_ids(struct nvmap_client *client, void nvmap_unpin_ids(struct nvmap_client *priv, unsigned int nr, const unsigned long *ids); -void _nvmap_handle_free(struct nvmap_handle *h); - int nvmap_handle_remove(struct nvmap_device *dev, struct nvmap_handle *h); void nvmap_handle_add(struct nvmap_device *dev, struct nvmap_handle *h); -#if defined(CONFIG_TEGRA_NVMAP) -static inline struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h) -{ - if (unlikely(atomic_inc_return(&h->ref) <= 1)) { - pr_err("%s: %s getting a freed handle\n", - __func__, current->group_leader->comm); - if (atomic_read(&h->ref) <= 0) - return NULL; - } - return h; -} - -static inline void nvmap_handle_put(struct nvmap_handle *h) -{ - int cnt = atomic_dec_return(&h->ref); - - if (WARN_ON(cnt < 0)) { - pr_err("%s: %s put to negative references\n", - __func__, current->comm); - } else if (cnt == 0) - _nvmap_handle_free(h); -} - -static inline pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot) -{ - if (h->flags == NVMAP_HANDLE_UNCACHEABLE) - return pgprot_noncached(prot); - else if (h->flags == NVMAP_HANDLE_WRITE_COMBINE) - return pgprot_writecombine(prot); - else if (h->flags == NVMAP_HANDLE_INNER_CACHEABLE) - return pgprot_inner_writeback(prot); - return prot; -} -#else /* CONFIG_TEGRA_NVMAP */ -struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h); -void nvmap_handle_put(struct nvmap_handle *h); -pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot); -#endif /* !CONFIG_TEGRA_NVMAP */ - int is_nvmap_vma(struct vm_area_struct *vma); struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client, @@ -268,4 +268,4 @@ struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client, void nvmap_free_iovm(struct nvmap_client *client, struct nvmap_handle_ref *r); -#endif +#endif /* __VIDEO_TEGRA_NVMAP_NVMAP_H */ -- cgit v1.2.3 From 9d85ccb8c12126fdb48f00a8951860d4ed070653 Mon Sep 17 00:00:00 2001 From: Krishna Reddy Date: Tue, 22 May 2012 15:46:04 -0700 Subject: video: tegra: nvmap: Clean up carveout to iovmm conversion. Clean up carveout to iovmm conversion code. Fixed bug in converting iovmm requests to carveout. Change-Id: I35a5238c955d0478f0e1a295e501bae9ee52b0a8 Signed-off-by: Krishna Reddy Reviewed-on: http://git-master/r/103991 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Yu-Huan Hsu --- drivers/video/tegra/nvmap/nvmap_handle.c | 58 ++++++++------------------------ 1 file changed, 14 insertions(+), 44 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index 2e2b8b3d46a1..56e2dab1820c 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -44,13 +44,6 @@ #include "nvmap_mru.h" #include "nvmap_common.h" -#define PRINT_CARVEOUT_CONVERSION 0 -#if PRINT_CARVEOUT_CONVERSION -#define PR_INFO pr_info -#else -#define PR_INFO(...) -#endif - #define NVMAP_SECURE_HEAPS (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_IOVMM | \ NVMAP_HEAP_CARVEOUT_VPR) #ifdef CONFIG_NVMAP_HIGHMEM_ONLY @@ -643,36 +636,19 @@ fail: static void alloc_handle(struct nvmap_client *client, struct nvmap_handle *h, unsigned int type) { + unsigned int carveout_mask = NVMAP_HEAP_CARVEOUT_MASK; + unsigned int iovmm_mask = NVMAP_HEAP_IOVMM; + BUG_ON(type & (type - 1)); #ifdef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM -#define __NVMAP_HEAP_CARVEOUT (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_CARVEOUT_VPR) -#define __NVMAP_HEAP_IOVMM (NVMAP_HEAP_IOVMM | NVMAP_HEAP_CARVEOUT_GENERIC) - if (type & NVMAP_HEAP_CARVEOUT_GENERIC) { -#ifdef CONFIG_NVMAP_ALLOW_SYSMEM - if (h->size <= PAGE_SIZE) { - PR_INFO("###CARVEOUT CONVERTED TO SYSMEM " - "0x%x bytes %s(%d)###\n", - h->size, current->comm, current->pid); - goto sysheap; - } -#endif - PR_INFO("###CARVEOUT CONVERTED TO IOVM " - "0x%x bytes %s(%d)###\n", - h->size, current->comm, current->pid); - } -#else -#define __NVMAP_HEAP_CARVEOUT NVMAP_HEAP_CARVEOUT_MASK -#define __NVMAP_HEAP_IOVMM NVMAP_HEAP_IOVMM + /* Convert generic carveout requests to iovmm requests. */ + carveout_mask &= ~NVMAP_HEAP_CARVEOUT_GENERIC; + iovmm_mask |= NVMAP_HEAP_CARVEOUT_GENERIC; #endif - if (type & __NVMAP_HEAP_CARVEOUT) { + if (type & carveout_mask) { struct nvmap_heap_block *b; -#ifdef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM - PR_INFO("###IRAM REQUEST RETAINED " - "0x%x bytes %s(%d)###\n", - h->size, current->comm, current->pid); -#endif /* Protect handle from relocation */ nvmap_usecount_inc(h); @@ -686,7 +662,7 @@ static void alloc_handle(struct nvmap_client *client, } nvmap_usecount_dec(h); - } else if (type & __NVMAP_HEAP_IOVMM) { + } else if (type & iovmm_mask) { size_t reserved = PAGE_ALIGN(h->size); int commit = 0; int ret; @@ -710,10 +686,6 @@ static void alloc_handle(struct nvmap_client *client, } } else if (type & NVMAP_HEAP_SYSMEM) { -#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) && \ - defined(CONFIG_NVMAP_ALLOW_SYSMEM) -sysheap: -#endif if (handle_page_alloc(client, h, true) == 0) { BUG_ON(!h->pgalloc.contig); h->heap_pgalloc = true; @@ -772,24 +744,22 @@ int nvmap_alloc_handle_id(struct nvmap_client *client, h->align = max_t(size_t, align, L1_CACHE_BYTES); #ifndef CONFIG_TEGRA_IOVMM + /* convert iovmm requests to generic carveout. */ if (heap_mask & NVMAP_HEAP_IOVMM) { - heap_mask &= NVMAP_HEAP_IOVMM; - heap_mask |= NVMAP_HEAP_CARVEOUT_GENERIC; + heap_mask = heap_mask & ~NVMAP_HEAP_IOVMM | + NVMAP_HEAP_CARVEOUT_GENERIC; } #endif -#ifndef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM #ifdef CONFIG_NVMAP_ALLOW_SYSMEM /* Allow single pages allocations in system memory to save * carveout space and avoid extra iovm mappings */ if (nr_page == 1) { - if (heap_mask & NVMAP_HEAP_IOVMM) + if (heap_mask & + (NVMAP_HEAP_IOVMM | NVMAP_HEAP_CARVEOUT_GENERIC)) heap_mask |= NVMAP_HEAP_SYSMEM; - else if (heap_mask & NVMAP_HEAP_CARVEOUT_GENERIC) { - heap_mask |= NVMAP_HEAP_SYSMEM; - } } #endif - +#ifndef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM /* This restriction is deprecated as alignments greater than PAGE_SIZE are now correctly handled, but it is retained for AP20 compatibility. */ -- cgit v1.2.3 From 043165e17e77abf771aae9ba03aff4467770cfc1 Mon Sep 17 00:00:00 2001 From: Krishna Reddy Date: Wed, 23 May 2012 14:58:52 -0700 Subject: video: tegra: nvmap: Fix debug allocations data shown. Debug allocations data for iovmm has carvout allocations also and vice versa. Fixed it to show only iovmm for iovmm and carveout for carveout. Add missing "FLAGS" print for iovmm allocations. Change-Id: I0fd271be24d0d2d3924ca473fd32476776fdcf84 Signed-off-by: Krishna Reddy Reviewed-on: http://git-master/r/104246 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Yu-Huan Hsu Reviewed-by: Jon Mayo --- drivers/video/tegra/nvmap/nvmap_dev.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c index c78818711f74..9ecce7eeeb17 100644 --- a/drivers/video/tegra/nvmap/nvmap_dev.c +++ b/drivers/video/tegra/nvmap/nvmap_dev.c @@ -973,20 +973,17 @@ static void client_stringify(struct nvmap_client *client, struct seq_file *s) } static void allocations_stringify(struct nvmap_client *client, - struct seq_file *s) + struct seq_file *s, bool iovmm) { - unsigned long base = 0; struct rb_node *n = rb_first(&client->handle_refs); for (; n != NULL; n = rb_next(n)) { struct nvmap_handle_ref *ref = rb_entry(n, struct nvmap_handle_ref, node); struct nvmap_handle *handle = ref->handle; - if (handle->alloc && !handle->heap_pgalloc) { - seq_printf(s, "%-18s %-18s %8lx %10u %8x\n", "", "", - (unsigned long)(handle->carveout->base), - handle->size, handle->userflags); - } else if (handle->alloc && handle->heap_pgalloc) { + if (handle->alloc && handle->heap_pgalloc == iovmm) { + unsigned long base = iovmm ? 0: + (unsigned long)(handle->carveout->base); seq_printf(s, "%-18s %-18s %8lx %10u %8x\n", "", "", base, handle->size, handle->userflags); } @@ -1010,7 +1007,7 @@ static int nvmap_debug_allocations_show(struct seq_file *s, void *unused) get_client_from_carveout_commit(node, commit); client_stringify(client, s); seq_printf(s, " %10u\n", commit->commit); - allocations_stringify(client, s); + allocations_stringify(client, s, false); seq_printf(s, "\n"); total += commit->commit; } @@ -1111,14 +1108,14 @@ static int nvmap_debug_iovmm_allocations_show(struct seq_file *s, void *unused) struct nvmap_device *dev = s->private; spin_lock_irqsave(&dev->clients_lock, flags); - seq_printf(s, "%-18s %18s %8s %10s\n", "CLIENT", "PROCESS", "PID", - "SIZE"); + seq_printf(s, "%-18s %18s %8s %10s %8s\n", "CLIENT", "PROCESS", "PID", + "SIZE", "FLAGS"); seq_printf(s, "%-18s %18s %8s %10s\n", "", "", "BASE", "SIZE"); list_for_each_entry(client, &dev->clients, list) { client_stringify(client, s); seq_printf(s, " %10u\n", atomic_read(&client->iovm_commit)); - allocations_stringify(client, s); + allocations_stringify(client, s, true); seq_printf(s, "\n"); total += atomic_read(&client->iovm_commit); } -- cgit v1.2.3 From f745e7ea486bcbf9665071df2e818141ed90ac07 Mon Sep 17 00:00:00 2001 From: Wen Yi Date: Wed, 23 May 2012 17:41:03 -0700 Subject: Revert "video: tegra: host: t30: use max 2d clock" This reverts commit 5bdd03b21f625d0a07c66e4894b79e557287a3a1. The reverted commit kept vcore at 1.2 volts whenever 2D engine is on and increased power consumption for use cases that utilize 2D but doesn't require its full speed. Bug 979545 Change-Id: I4297ab1fb83558501ff620952284c8590dc5f1dd Signed-off-by: Wen Yi Reviewed-on: http://git-master/r/104293 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Donghan Ryu Tested-by: Donghan Ryu GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/host/t30/t30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c index 257ba0849277..b2768741546a 100644 --- a/drivers/video/tegra/host/t30/t30.c +++ b/drivers/video/tegra/host/t30/t30.c @@ -95,7 +95,7 @@ struct nvhost_device t30_devices[] = { .waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1), .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) | BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B), - .clocks = { {"gr2d", UINT_MAX}, + .clocks = { {"gr2d", 0}, {"epp", 0}, {"emc", 300000000} }, NVHOST_MODULE_NO_POWERGATE_IDS, -- cgit v1.2.3 From 839b2b9c17da5b96ecccf0acf5e8c9d3ae3816af Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Thu, 24 May 2012 11:30:30 +0300 Subject: video: tegra: host: Merge waitchk and relocation Job pinning and relocation already maps the gather buffers to kernel memory. Move waitchk to be done at the same time so that we do not need to re-map the memory to patch expired waits. Bug 965206 Change-Id: I23634b501a45de080200e57d3debf267b39fea38 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/104415 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Juha Tukkinen Reviewed-by: Mayuresh Kulkarni --- drivers/video/tegra/host/bus_client.c | 8 +-- drivers/video/tegra/host/chip_support.h | 8 +-- drivers/video/tegra/host/host1x/host1x_channel.c | 16 ------ drivers/video/tegra/host/host1x/host1x_syncpt.c | 64 +++--------------------- drivers/video/tegra/host/nvhost_channel.h | 1 - drivers/video/tegra/host/nvhost_job.c | 58 ++++++++++++++++++++- drivers/video/tegra/host/nvhost_job.h | 7 ++- drivers/video/tegra/host/nvhost_syncpt.c | 13 ++--- drivers/video/tegra/host/nvhost_syncpt.h | 18 +------ 9 files changed, 81 insertions(+), 112 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c index 822f8f3a456d..397cd21f555d 100644 --- a/drivers/video/tegra/host/bus_client.c +++ b/drivers/video/tegra/host/bus_client.c @@ -306,7 +306,7 @@ static int nvhost_ioctl_channel_flush( struct nvhost_get_param_args *args, int null_kickoff) { - struct device *device = &ctx->ch->dev->dev; + struct nvhost_device *ndev = to_nvhost_device(&ctx->ch->dev->dev); int err; trace_nvhost_ioctl_channel_flush(ctx->ch->dev->name); @@ -316,13 +316,13 @@ static int nvhost_ioctl_channel_flush( ctx->hdr.num_cmdbufs || ctx->hdr.num_waitchks) { reset_submit(ctx); - dev_err(device, "channel submit out of sync\n"); + dev_err(&ndev->dev, "channel submit out of sync\n"); return -EFAULT; } - err = nvhost_job_pin(ctx->job); + err = nvhost_job_pin(ctx->job, &nvhost_get_host(ndev)->syncpt); if (err) { - dev_warn(device, "nvhost_job_pin failed: %d\n", err); + dev_warn(&ndev->dev, "nvhost_job_pin failed: %d\n", err); return err; } diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index 173a36065458..d69e1c4bccb9 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -28,7 +28,6 @@ struct output; struct nvhost_master; struct nvhost_intr; struct nvhost_syncpt; -struct nvhost_waitchk; struct nvhost_userctx_timeout; struct nvhost_channel; struct nvmap_handle_ref; @@ -106,11 +105,8 @@ struct nvhost_chip_support { void (*read_wait_base)(struct nvhost_syncpt *, u32 id); u32 (*update_min)(struct nvhost_syncpt *, u32 id); void (*cpu_incr)(struct nvhost_syncpt *, u32 id); - int (*wait_check)(struct nvhost_syncpt *sp, - struct nvmap_client *nvmap, - u32 waitchk_mask, - struct nvhost_waitchk *wait, - int num_waitchk); + int (*patch_wait)(struct nvhost_syncpt *sp, + void *patch_addr); void (*debug)(struct nvhost_syncpt *); const char * (*name)(struct nvhost_syncpt *, u32 id); int (*mutex_try_lock)(struct nvhost_syncpt *, diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c index 0b4d07cb9e47..c72e6478b806 100644 --- a/drivers/video/tegra/host/host1x/host1x_channel.c +++ b/drivers/video/tegra/host/host1x/host1x_channel.c @@ -242,22 +242,6 @@ int host1x_channel_submit(struct nvhost_job *job) goto error; } - /* remove stale waits */ - if (job->num_waitchk) { - err = nvhost_syncpt_wait_check(sp, - job->nvmap, - job->waitchk_mask, - job->waitchk, - job->num_waitchk); - if (err) { - dev_warn(&ch->dev->dev, - "nvhost_syncpt_wait_check failed: %d\n", err); - mutex_unlock(&ch->submitlock); - nvhost_module_idle(ch->dev); - goto error; - } - } - /* begin a CDMA submit */ err = nvhost_cdma_begin(&ch->cdma, job); if (err) { diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.c b/drivers/video/tegra/host/host1x/host1x_syncpt.c index b7d6587acc61..4cc8e9e212fa 100644 --- a/drivers/video/tegra/host/host1x/host1x_syncpt.c +++ b/drivers/video/tegra/host/host1x/host1x_syncpt.c @@ -103,62 +103,14 @@ static void t20_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id) wmb(); } -/* check for old WAITs to be removed (avoiding a wrap) */ -static int t20_syncpt_wait_check(struct nvhost_syncpt *sp, - struct nvmap_client *nvmap, - u32 waitchk_mask, - struct nvhost_waitchk *wait, - int num_waitchk) +/* remove a wait pointed to by patch_addr */ +static int host1x_syncpt_patch_wait(struct nvhost_syncpt *sp, + void *patch_addr) { - u32 idx; - int err = 0; - - /* get current syncpt values */ - for (idx = 0; idx < NV_HOST1X_SYNCPT_NB_PTS; idx++) { - if (BIT(idx) & waitchk_mask) - nvhost_syncpt_update_min(sp, idx); - } - - BUG_ON(!wait && !num_waitchk); - - /* compare syncpt vs wait threshold */ - while (num_waitchk) { - u32 override; - - BUG_ON(wait->syncpt_id >= NV_HOST1X_SYNCPT_NB_PTS); - trace_nvhost_syncpt_wait_check(wait->mem, wait->offset, - wait->syncpt_id, wait->thresh); - if (nvhost_syncpt_is_expired(sp, - wait->syncpt_id, wait->thresh)) { - /* - * NULL an already satisfied WAIT_SYNCPT host method, - * by patching its args in the command stream. The - * method data is changed to reference a reserved - * (never given out or incr) NVSYNCPT_GRAPHICS_HOST - * syncpt with a matching threshold value of 0, so - * is guaranteed to be popped by the host HW. - */ - dev_dbg(&syncpt_to_dev(sp)->dev->dev, - "drop WAIT id %d (%s) thresh 0x%x, min 0x%x\n", - wait->syncpt_id, - syncpt_op().name(sp, wait->syncpt_id), - wait->thresh, - nvhost_syncpt_read_min(sp, wait->syncpt_id)); - - /* patch the wait */ - override = nvhost_class_host_wait_syncpt( - NVSYNCPT_GRAPHICS_HOST, 0); - err = nvmap_patch_word(nvmap, - (struct nvmap_handle *)wait->mem, - wait->offset, override); - if (err) - break; - } - - wait++; - num_waitchk--; - } - return err; + u32 override = nvhost_class_host_wait_syncpt( + NVSYNCPT_GRAPHICS_HOST, 0); + __raw_writel(override, patch_addr); + return 0; } @@ -241,7 +193,7 @@ int host1x_init_syncpt_support(struct nvhost_master *host, op->syncpt.read_wait_base = t20_syncpt_read_wait_base; op->syncpt.update_min = t20_syncpt_update_min; op->syncpt.cpu_incr = t20_syncpt_cpu_incr; - op->syncpt.wait_check = t20_syncpt_wait_check; + op->syncpt.patch_wait = host1x_syncpt_patch_wait; op->syncpt.debug = t20_syncpt_debug; op->syncpt.name = t20_syncpt_name; op->syncpt.mutex_try_lock = syncpt_mutex_try_lock; diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h index a8f16f0c5abc..b3a904d5a3ee 100644 --- a/drivers/video/tegra/host/nvhost_channel.h +++ b/drivers/video/tegra/host/nvhost_channel.h @@ -31,7 +31,6 @@ #define NVHOST_MAX_POWERGATE_IDS 2 struct nvhost_master; -struct nvhost_waitchk; struct nvhost_device; struct nvhost_channel; struct nvhost_hwctx; diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c index 11d65964e2c9..6d8c3bd2bd50 100644 --- a/drivers/video/tegra/host/nvhost_job.c +++ b/drivers/video/tegra/host/nvhost_job.c @@ -27,6 +27,7 @@ #include "nvhost_channel.h" #include "nvhost_job.h" #include "nvhost_hwctx.h" +#include "nvhost_syncpt.h" #include "dev.h" /* Magic to use to fill freed handle slots */ @@ -196,11 +197,63 @@ static int do_relocs(struct nvhost_job *job, u32 patch_mem, void *patch_addr) return 0; } -int nvhost_job_pin(struct nvhost_job *job) +/* + * Check driver supplied waitchk structs for syncpt thresholds + * that have already been satisfied and NULL the comparison (to + * avoid a wrap condition in the HW). + */ +static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp, + u32 patch_mem, void *patch_addr) +{ + int i; + + /* compare syncpt vs wait threshold */ + for (i = 0; i < job->num_waitchk; i++) { + struct nvhost_waitchk *wait = &job->waitchk[i]; + + /* skip all other gathers */ + if (patch_mem != wait->mem) + continue; + + trace_nvhost_syncpt_wait_check(wait->mem, wait->offset, + wait->syncpt_id, wait->thresh); + if (nvhost_syncpt_is_expired(sp, + wait->syncpt_id, wait->thresh)) { + /* + * NULL an already satisfied WAIT_SYNCPT host method, + * by patching its args in the command stream. The + * method data is changed to reference a reserved + * (never given out or incr) NVSYNCPT_GRAPHICS_HOST + * syncpt with a matching threshold value of 0, so + * is guaranteed to be popped by the host HW. + */ + dev_dbg(&syncpt_to_dev(sp)->dev->dev, + "drop WAIT id %d (%s) thresh 0x%x, min 0x%x\n", + wait->syncpt_id, + syncpt_op().name(sp, wait->syncpt_id), + wait->thresh, + nvhost_syncpt_read_min(sp, wait->syncpt_id)); + + /* patch the wait */ + nvhost_syncpt_patch_wait(sp, + (patch_addr + wait->offset)); + } + + wait->mem = 0; + } + return 0; +} + +int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp) { int err = 0, i = 0; phys_addr_t gather_phys = 0; void *gather_addr = NULL; + unsigned long waitchk_mask = job->waitchk_mask; + + /* get current syncpt values for waitchk */ + for_each_set_bit(i, &waitchk_mask, sizeof(job->waitchk_mask)) + nvhost_syncpt_update_min(sp, i); /* pin gathers */ for (i = 0; i < job->num_gathers; i++) { @@ -233,6 +286,9 @@ int nvhost_job_pin(struct nvhost_job *job) } err = do_relocs(job, g->mem_id, gather_addr); + if (!err) + err = do_waitchks(job, sp, + g->mem_id, gather_addr); nvmap_munmap(g->ref, gather_addr); if (err) diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h index 48555a231412..b30f5faf7e8f 100644 --- a/drivers/video/tegra/host/nvhost_job.h +++ b/drivers/video/tegra/host/nvhost_job.h @@ -27,7 +27,7 @@ struct nvhost_channel; struct nvhost_hwctx; struct nvmap_client; struct nvhost_waitchk; -struct nvmap_handle; +struct nvhost_syncpt; struct nvhost_job_gather { u32 words; @@ -129,8 +129,11 @@ void nvhost_job_put(struct nvhost_job *job); * Pin memory related to job. This handles relocation of addresses to the * host1x address space. Handles both the gather memory and any other memory * referred to from the gather buffers. + * + * Handles also patching out host waits that would wait for an expired sync + * point value. */ -int nvhost_job_pin(struct nvhost_job *job); +int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp); /* * Unpin memory related to job. diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c index 1458a7cb5acc..7550512b0214 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.c +++ b/drivers/video/tegra/host/nvhost_syncpt.c @@ -74,7 +74,7 @@ u32 nvhost_syncpt_update_min(struct nvhost_syncpt *sp, u32 id) BUG_ON(!syncpt_op().update_min); - return syncpt_op().update_min(sp, id); + val = syncpt_op().update_min(sp, id); trace_nvhost_syncpt_update_min(id, val); return val; @@ -330,15 +330,10 @@ void nvhost_mutex_unlock(struct nvhost_syncpt *sp, int idx) atomic_dec(&sp->lock_counts[idx]); } -/* check for old WAITs to be removed (avoiding a wrap) */ -int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp, - struct nvmap_client *nvmap, - u32 waitchk_mask, - struct nvhost_waitchk *wait, - int num_waitchk) +/* remove a wait pointed to by patch_addr */ +int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr) { - return syncpt_op().wait_check(sp, nvmap, - waitchk_mask, wait, num_waitchk); + return syncpt_op().patch_wait(sp, patch_addr); } /* Displays the current value of the sync point via sysfs */ diff --git a/drivers/video/tegra/host/nvhost_syncpt.h b/drivers/video/tegra/host/nvhost_syncpt.h index b770ed91c76c..b58921bffa9c 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.h +++ b/drivers/video/tegra/host/nvhost_syncpt.h @@ -136,23 +136,7 @@ static inline int nvhost_syncpt_wait(struct nvhost_syncpt *sp, u32 id, u32 thres MAX_SCHEDULE_TIMEOUT, NULL); } -/* - * Check driver supplied waitchk structs for syncpt thresholds - * that have already been satisfied and NULL the comparison (to - * avoid a wrap condition in the HW). - * - * @param: sp - global shadowed syncpt struct - * @param: nvmap - needed to access command buffer - * @param: mask - bit mask of syncpt IDs referenced in WAITs - * @param: wait - start of filled in array of waitchk structs - * @param: waitend - end ptr (one beyond last valid waitchk) - */ -struct nvhost_waitchk; -int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp, - struct nvmap_client *nvmap, - u32 mask, - struct nvhost_waitchk *wait, - int num_waitchk); +int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr); void nvhost_syncpt_debug(struct nvhost_syncpt *sp); -- cgit v1.2.3 From 73f65f7f6898bd88fe457f96d4dc702f746058bc Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Thu, 24 May 2012 15:06:58 +0300 Subject: video: tegra: host: Replace nvmap structs with own Replace usage of nvmap_pinarray_elem with own nvhost_reloc and nvhost_reloc_shift structs. Bug 965206 Change-Id: I90618d8a34d79156d8880d9925dadbf416353811 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/104450 Reviewed-by: Juha Tukkinen Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Mayuresh Kulkarni --- drivers/video/tegra/host/bus_client.c | 39 +++++++++++++++---------- drivers/video/tegra/host/nvhost_job.c | 54 +++++++++++++++++++---------------- drivers/video/tegra/host/nvhost_job.h | 3 +- 3 files changed, 56 insertions(+), 40 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c index 397cd21f555d..9b71542a48aa 100644 --- a/drivers/video/tegra/host/bus_client.c +++ b/drivers/video/tegra/host/bus_client.c @@ -238,21 +238,28 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf, cmdbuf.mem, cmdbuf.words, cmdbuf.offset); hdr->num_cmdbufs--; } else if (hdr->num_relocs) { - consumed = sizeof(struct nvhost_reloc); - if (remaining < consumed) + int numrelocs = remaining / sizeof(struct nvhost_reloc); + if (!numrelocs) break; - if (copy_from_user(&job->pinarray[job->num_relocs], + numrelocs = min_t(int, numrelocs, priv->hdr.num_relocs); + consumed = numrelocs * sizeof(struct nvhost_reloc); + if (copy_from_user(&job->relocarray[job->num_relocs], buf, consumed)) { err = -EFAULT; break; } - trace_nvhost_channel_write_reloc(chname, - job->pinarray[job->num_relocs].patch_mem, - job->pinarray[job->num_relocs].patch_offset, - job->pinarray[job->num_relocs].pin_mem, - job->pinarray[job->num_relocs].pin_offset); - job->num_relocs++; - hdr->num_relocs--; + while (numrelocs) { + struct nvhost_reloc *reloc = + &job->relocarray[job->num_relocs]; + trace_nvhost_channel_write_reloc(chname, + reloc->cmdbuf_mem, + reloc->cmdbuf_offset, + reloc->target, + reloc->target_offset); + job->num_relocs++; + hdr->num_relocs--; + numrelocs--; + } } else if (hdr->num_waitchks) { int numwaitchks = (remaining / sizeof(struct nvhost_waitchk)); @@ -274,16 +281,18 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf, } else if (priv->num_relocshifts) { int next_shift = job->num_relocs - priv->num_relocshifts; - consumed = sizeof(struct nvhost_reloc_shift); - if (remaining < consumed) + int num = + (remaining / sizeof(struct nvhost_reloc_shift)); + if (!num) break; - if (copy_from_user( - &job->pinarray[next_shift].reloc_shift, + num = min_t(int, num, priv->num_relocshifts); + consumed = num * sizeof(struct nvhost_reloc_shift); + if (copy_from_user(&job->relocshiftarray[next_shift], buf, consumed)) { err = -EFAULT; break; } - priv->num_relocshifts--; + priv->num_relocshifts -= num; } else { err = -EFAULT; break; diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c index 6d8c3bd2bd50..e029449b6184 100644 --- a/drivers/video/tegra/host/nvhost_job.c +++ b/drivers/video/tegra/host/nvhost_job.c @@ -41,7 +41,8 @@ static int job_size(struct nvhost_submit_hdr_ext *hdr) int num_unpins = num_cmdbufs + num_relocs; return sizeof(struct nvhost_job) - + num_relocs * sizeof(struct nvmap_pinarray_elem) + + num_relocs * sizeof(struct nvhost_reloc) + + num_relocs * sizeof(struct nvhost_reloc_shift) + num_unpins * sizeof(struct nvmap_handle_ref *) + num_waitchks * sizeof(struct nvhost_waitchk) + num_cmdbufs * sizeof(struct nvhost_job_gather); @@ -63,8 +64,10 @@ static void init_fields(struct nvhost_job *job, /* Redistribute memory to the structs */ mem += sizeof(struct nvhost_job); - job->pinarray = num_relocs ? mem : NULL; - mem += num_relocs * sizeof(struct nvmap_pinarray_elem); + job->relocarray = num_relocs ? mem : NULL; + mem += num_relocs * sizeof(struct nvhost_reloc); + job->relocshiftarray = num_relocs ? mem : NULL; + mem += num_relocs * sizeof(struct nvhost_reloc_shift); job->unpins = num_unpins ? mem : NULL; mem += num_unpins * sizeof(struct nvmap_handle_ref *); job->waitchk = num_waitchks ? mem : NULL; @@ -154,44 +157,46 @@ void nvhost_job_add_gather(struct nvhost_job *job, job->num_gathers += 1; } -static int do_relocs(struct nvhost_job *job, u32 patch_mem, void *patch_addr) +static int do_relocs(struct nvhost_job *job, u32 cmdbuf_mem, void *cmdbuf_addr) { - phys_addr_t pin_phys; + phys_addr_t target_phys; int i; u32 mem_id = 0; - struct nvmap_handle_ref *pin_ref = NULL; + struct nvmap_handle_ref *target_ref = NULL; /* pin & patch the relocs for one gather */ for (i = 0; i < job->num_relocs; i++) { - struct nvmap_pinarray_elem *pin = &job->pinarray[i]; + struct nvhost_reloc *reloc = &job->relocarray[i]; + struct nvhost_reloc_shift *shift = &job->relocshiftarray[i]; /* skip all other gathers */ - if (patch_mem != pin->patch_mem) + if (cmdbuf_mem != reloc->cmdbuf_mem) continue; /* check if pin-mem is same as previous */ - if (pin->pin_mem != mem_id) { - pin_ref = nvmap_duplicate_handle_id(job->nvmap, - pin->pin_mem); - if (IS_ERR(pin_ref)) - return PTR_ERR(pin_ref); - - pin_phys = nvmap_pin(job->nvmap, pin_ref); - if (IS_ERR((void *)pin_phys)) { - nvmap_free(job->nvmap, pin_ref); - return pin_phys; + if (reloc->target != mem_id) { + target_ref = nvmap_duplicate_handle_id(job->nvmap, + reloc->target); + if (IS_ERR(target_ref)) + return PTR_ERR(target_ref); + + target_phys = nvmap_pin(job->nvmap, target_ref); + if (IS_ERR((void *)target_phys)) { + nvmap_free(job->nvmap, target_ref); + return target_phys; } - mem_id = pin->pin_mem; - job->unpins[job->num_unpins++] = pin_ref; + mem_id = reloc->target; + job->unpins[job->num_unpins++] = target_ref; } - __raw_writel((pin_phys + pin->pin_offset) >> pin->reloc_shift, - (patch_addr + pin->patch_offset)); + __raw_writel( + (target_phys + reloc->target_offset) >> shift->shift, + (cmdbuf_addr + reloc->cmdbuf_offset)); /* Different gathers might have same mem_id. This ensures we * perform reloc only once per gather memid. */ - pin->patch_mem = 0; + reloc->cmdbuf_mem = 0; } return 0; @@ -216,7 +221,8 @@ static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp, continue; trace_nvhost_syncpt_wait_check(wait->mem, wait->offset, - wait->syncpt_id, wait->thresh); + wait->syncpt_id, wait->thresh, + nvhost_syncpt_read(sp, wait->syncpt_id)); if (nvhost_syncpt_is_expired(sp, wait->syncpt_id, wait->thresh)) { /* diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h index b30f5faf7e8f..ec1366337279 100644 --- a/drivers/video/tegra/host/nvhost_job.h +++ b/drivers/video/tegra/host/nvhost_job.h @@ -67,7 +67,8 @@ struct nvhost_job { u32 waitchk_mask; /* Array of handles to be pinned & unpinned */ - struct nvmap_pinarray_elem *pinarray; + struct nvhost_reloc *relocarray; + struct nvhost_reloc_shift *relocshiftarray; int num_relocs; struct nvmap_handle_ref **unpins; int num_unpins; -- cgit v1.2.3 From b6f12a3449234f9960998954382e1a9afea7764d Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Thu, 24 May 2012 14:18:28 +0300 Subject: video: tegra: nvmap: Remove nvhost specific APIs Remove nvmap_pin_array() and nvmap_patch_word() and their utility functions. Bug 965206 Change-Id: I217a427934b0b99b5252b33ab3ac4eaaa8c7e076 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/104451 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Mayuresh Kulkarni GVS: Gerrit_Virtual_Submit Reviewed-by: Juha Tukkinen --- drivers/video/tegra/nvmap/nvmap.c | 268 -------------------------------------- 1 file changed, 268 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index a0c4156668e5..b7fd695d04ee 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -352,225 +352,6 @@ static phys_addr_t handle_phys(struct nvmap_handle *h) return addr; } -/* stores the physical address (+offset) of each handle relocation entry - * into its output location. see nvmap_pin_array for more details. - * - * each entry in arr (i.e., each relocation request) specifies two handles: - * the handle to pin (pin), and the handle where the address of pin should be - * written (patch). in pseudocode, this loop basically looks like: - * - * for (i = 0; i < nr; i++) { - * (pin, pin_offset, patch, patch_offset) = arr[i]; - * patch[patch_offset] = address_of(pin) + pin_offset; - * } - */ -static int nvmap_reloc_pin_array(struct nvmap_client *client, - const struct nvmap_pinarray_elem *arr, - int nr, struct nvmap_handle *gather) -{ - struct nvmap_handle *last_patch = NULL; - unsigned int last_pfn = 0; - pte_t **pte; - void *addr; - int i; - - pte = nvmap_alloc_pte(client->dev, &addr); - if (IS_ERR(pte)) - return PTR_ERR(pte); - - for (i = 0; i < nr; i++) { - struct nvmap_handle *patch; - struct nvmap_handle *pin; - phys_addr_t reloc_addr; - phys_addr_t phys; - unsigned int pfn; - - /* all of the handles are validated and get'ted prior to - * calling this function, so casting is safe here */ - pin = (struct nvmap_handle *)arr[i].pin_mem; - - if (arr[i].patch_mem == (unsigned long)last_patch) { - patch = last_patch; - } else if (arr[i].patch_mem == (unsigned long)gather) { - patch = gather; - } else { - if (last_patch) - nvmap_handle_put(last_patch); - - patch = nvmap_get_handle_id(client, arr[i].patch_mem); - if (!patch) { - nvmap_free_pte(client->dev, pte); - return -EPERM; - } - last_patch = patch; - } - - if (patch->heap_pgalloc) { - unsigned int page = arr[i].patch_offset >> PAGE_SHIFT; - phys = page_to_phys(patch->pgalloc.pages[page]); - phys += (arr[i].patch_offset & ~PAGE_MASK); - } else { - phys = patch->carveout->base + arr[i].patch_offset; - } - - pfn = __phys_to_pfn(phys); - if (pfn != last_pfn) { - pgprot_t prot = nvmap_pgprot(patch, pgprot_kernel); - phys_addr_t kaddr = (phys_addr_t)addr; - set_pte_at(&init_mm, kaddr, *pte, pfn_pte(pfn, prot)); - flush_tlb_kernel_page(kaddr); - last_pfn = pfn; - } - - reloc_addr = handle_phys(pin) + arr[i].pin_offset; - reloc_addr >>= arr[i].reloc_shift; - __raw_writel(reloc_addr, addr + (phys & ~PAGE_MASK)); - } - - nvmap_free_pte(client->dev, pte); - - if (last_patch) - nvmap_handle_put(last_patch); - - wmb(); - - return 0; -} - -static int nvmap_validate_get_pin_array(struct nvmap_client *client, - const struct nvmap_pinarray_elem *arr, - int nr, struct nvmap_handle **h) -{ - int i; - int ret = 0; - int count = 0; - - nvmap_ref_lock(client); - - for (i = 0; i < nr; i++) { - struct nvmap_handle_ref *ref; - - if (need_resched()) { - nvmap_ref_unlock(client); - schedule(); - nvmap_ref_lock(client); - } - - ref = _nvmap_validate_id_locked(client, arr[i].pin_mem); - - if (!ref) - nvmap_warn(client, "falied to validate id\n"); - else if (!ref->handle) - nvmap_warn(client, "id had no associated handle\n"); - else if (!ref->handle->alloc) - nvmap_warn(client, "handle had no allocation\n"); - - if (!ref || !ref->handle || !ref->handle->alloc) { - ret = -EPERM; - break; - } - - /* a handle may be referenced multiple times in arr, but - * it will only be pinned once; this ensures that the - * minimum number of sync-queue slots in the host driver - * are dedicated to storing unpin lists, which allows - * for greater parallelism between the CPU and graphics - * processor */ - if (ref->handle->flags & NVMAP_HANDLE_VISITED) - continue; - - ref->handle->flags |= NVMAP_HANDLE_VISITED; - - h[count] = nvmap_handle_get(ref->handle); - BUG_ON(!h[count]); - count++; - } - - nvmap_ref_unlock(client); - - if (ret) { - for (i = 0; i < count; i++) { - h[i]->flags &= ~NVMAP_HANDLE_VISITED; - nvmap_handle_put(h[i]); - } - } - - return ret ?: count; -} - -/* a typical mechanism host1x clients use for using the Tegra graphics - * processor is to build a command buffer which contains relocatable - * memory handle commands, and rely on the kernel to convert these in-place - * to addresses which are understood by the GPU hardware. - * - * this is implemented by having clients provide a sideband array - * of relocatable handles (+ offsets) and the location in the command - * buffer handle to patch with the GPU address when the client submits - * its command buffer to the host1x driver. - * - * the host driver also uses this relocation mechanism internally to - * relocate the client's (unpinned) command buffers into host-addressable - * memory. - * - * @client: nvmap_client which should be used for validation; should be - * owned by the process which is submitting command buffers - * @gather: special handle for relocated command buffer outputs used - * internally by the host driver. if this handle is encountered - * as an output handle in the relocation array, it is assumed - * to be a known-good output and is not validated. - * @arr: array of ((relocatable handle, offset), (output handle, offset)) - * tuples. - * @nr: number of entries in arr - * @unique_arr: list of nvmap_handle objects which were pinned by - * nvmap_pin_array. must be unpinned by the caller after the - * command buffers referenced in gather have completed. - */ -int nvmap_pin_array(struct nvmap_client *client, struct nvmap_handle *gather, - const struct nvmap_pinarray_elem *arr, int nr, - struct nvmap_handle **unique_arr) -{ - int count = 0; - int ret = 0; - int i; - - if (mutex_lock_interruptible(&client->share->pin_lock)) { - nvmap_warn(client, "%s interrupted when acquiring pin lock\n", - current->group_leader->comm); - return -EINTR; - } - - count = nvmap_validate_get_pin_array(client, arr, nr, unique_arr); - if (count < 0) { - mutex_unlock(&client->share->pin_lock); - nvmap_warn(client, "failed to validate pin array\n"); - return count; - } - - for (i = 0; i < count; i++) - unique_arr[i]->flags &= ~NVMAP_HANDLE_VISITED; - - ret = wait_pin_array_locked(client, unique_arr, count); - - mutex_unlock(&client->share->pin_lock); - - if (!ret) - ret = nvmap_reloc_pin_array(client, arr, nr, gather); - - if (WARN_ON(ret)) { - for (i = 0; i < count; i++) - nvmap_handle_put(unique_arr[i]); - return ret; - } else { - for (i = 0; i < count; i++) { - if (unique_arr[i]->heap_pgalloc && - unique_arr[i]->pgalloc.dirty) - map_iovmm_area(unique_arr[i]); - } - } - - return count; -} - phys_addr_t nvmap_pin(struct nvmap_client *client, struct nvmap_handle_ref *ref) { @@ -820,52 +601,3 @@ void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r) nvmap_free_handle_id(client, nvmap_ref_to_id(r)); } - -/* - * create a mapping to the user's buffer and write it - * (uses similar logic from nvmap_reloc_pin_array to map the cmdbuf) - */ -int nvmap_patch_word(struct nvmap_client *client, - struct nvmap_handle *patch, - u32 patch_offset, u32 patch_value) -{ - phys_addr_t phys; - unsigned long kaddr; - unsigned int pfn; - void *addr; - pte_t **pte; - pgprot_t prot; - - if (patch_offset >= patch->size) { - nvmap_warn(client, "read/write outside of handle\n"); - return -EFAULT; - } - - pte = nvmap_alloc_pte(client->dev, &addr); - if (IS_ERR(pte)) - return PTR_ERR(pte); - - /* derive physaddr of cmdbuf WAIT to patch */ - if (patch->heap_pgalloc) { - unsigned int page = patch_offset >> PAGE_SHIFT; - phys = page_to_phys(patch->pgalloc.pages[page]); - phys += (patch_offset & ~PAGE_MASK); - } else { - phys = patch->carveout->base + patch_offset; - } - - pfn = __phys_to_pfn(phys); - prot = nvmap_pgprot(patch, pgprot_kernel); - kaddr = (unsigned long)addr; - - /* write PTE, so addr points to cmdbuf PFN */ - set_pte_at(&init_mm, kaddr, *pte, pfn_pte(pfn, prot)); - flush_tlb_kernel_page(kaddr); - - /* write patch_value to addr + page offset */ - __raw_writel(patch_value, addr + (phys & ~PAGE_MASK)); - - nvmap_free_pte(client->dev, pte); - wmb(); - return 0; -} -- cgit v1.2.3 From bc056c017381a85acf2d41a1e537f45e04ea297a Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Mon, 28 May 2012 11:56:54 +0300 Subject: video: tegra: host: Throttle lower priority jobs Implement per channel counter for jobs in each priority level. If there are jobs active with higher priority than the one being submitted, throttle. Bug 926690 Change-Id: I5fed341e3f248325873b31d1c53bf57bf0a78074 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/104939 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Juha Tukkinen Reviewed-by: Mayuresh Kulkarni --- drivers/video/tegra/host/bus_client.c | 6 ------ drivers/video/tegra/host/nvhost_cdma.c | 33 +++++++++++++++++++++++++++++++ drivers/video/tegra/host/nvhost_cdma.h | 3 +++ drivers/video/tegra/host/nvhost_channel.c | 24 ++++++++++++++++++---- drivers/video/tegra/host/nvhost_intr.c | 10 +++++++--- 5 files changed, 63 insertions(+), 13 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c index 9b71542a48aa..87aa9c64d363 100644 --- a/drivers/video/tegra/host/bus_client.c +++ b/drivers/video/tegra/host/bus_client.c @@ -141,12 +141,6 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp) priv->clientid = atomic_add_return(1, &nvhost_get_host(ch->dev)->clientid); priv->timeout = MAX_STUCK_CHECK_COUNT * SYNCPT_CHECK_PERIOD; - - priv->job = nvhost_job_alloc(ch, priv->hwctx, &priv->hdr, - NULL, priv->priority, priv->clientid); - if (!priv->job) - goto fail; - return 0; fail: nvhost_channelrelease(inode, filp); diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c index b1f138317cc1..c87415bf5ac2 100644 --- a/drivers/video/tegra/host/nvhost_cdma.c +++ b/drivers/video/tegra/host/nvhost_cdma.c @@ -53,6 +53,18 @@ static void add_to_sync_queue(struct nvhost_cdma *cdma, job->num_slots = nr_slots; nvhost_job_get(job); list_add_tail(&job->list, &cdma->sync_queue); + + switch (job->priority) { + case NVHOST_PRIORITY_HIGH: + cdma->high_prio_count++; + break; + case NVHOST_PRIORITY_MEDIUM: + cdma->med_prio_count++; + break; + case NVHOST_PRIORITY_LOW: + cdma->low_prio_count++; + break; + } } /** @@ -200,6 +212,19 @@ static void update_cdma_locked(struct nvhost_cdma *cdma) } list_del(&job->list); + + switch (job->priority) { + case NVHOST_PRIORITY_HIGH: + cdma->high_prio_count--; + break; + case NVHOST_PRIORITY_MEDIUM: + cdma->med_prio_count--; + break; + case NVHOST_PRIORITY_LOW: + cdma->low_prio_count--; + break; + } + nvhost_job_put(job); } @@ -466,6 +491,12 @@ void nvhost_cdma_end(struct nvhost_cdma *cdma, if (job->timeout && was_idle) cdma_start_timer_locked(cdma, job); + trace_nvhost_cdma_end(job->ch->dev->name, + job->priority, + job->ch->cdma.high_prio_count, + job->ch->cdma.med_prio_count, + job->ch->cdma.low_prio_count); + mutex_unlock(&cdma->lock); } @@ -490,6 +521,8 @@ int nvhost_cdma_flush(struct nvhost_cdma *cdma, int timeout) unsigned int space, err = 0; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); + trace_nvhost_cdma_flush(cdma_to_channel(cdma)->dev->name, timeout); + /* * Wait for at most timeout ms. Recalculate timeout at each iteration * to better keep within given timeout. diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h index 98393f0cc765..2056774a7bc7 100644 --- a/drivers/video/tegra/host/nvhost_cdma.h +++ b/drivers/video/tegra/host/nvhost_cdma.h @@ -99,6 +99,9 @@ struct nvhost_cdma { struct buffer_timeout timeout; /* channel's timeout state/wq */ bool running; bool torndown; + int high_prio_count; + int med_prio_count; + int low_prio_count; }; #define cdma_to_channel(cdma) container_of(cdma, struct nvhost_channel, cdma) diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c index ef8886fe4652..ad303cf0a22d 100644 --- a/drivers/video/tegra/host/nvhost_channel.c +++ b/drivers/video/tegra/host/nvhost_channel.c @@ -51,10 +51,26 @@ int nvhost_channel_init(struct nvhost_channel *ch, int nvhost_channel_submit(struct nvhost_job *job) { - /* Low priority submits wait until sync queue is empty. Ignores result - * from nvhost_cdma_flush, as we submit either when push buffer is - * empty or when we reach the timeout. */ - if (job->priority < NVHOST_PRIORITY_MEDIUM) + /* + * Check if queue has higher priority jobs running. If so, wait until + * queue is empty. Ignores result from nvhost_cdma_flush, as we submit + * either when push buffer is empty or when we reach the timeout. + */ + int higher_count = 0; + + switch (job->priority) { + case NVHOST_PRIORITY_HIGH: + higher_count = 0; + break; + case NVHOST_PRIORITY_MEDIUM: + higher_count = job->ch->cdma.high_prio_count; + break; + case NVHOST_PRIORITY_LOW: + higher_count = job->ch->cdma.high_prio_count + + job->ch->cdma.med_prio_count; + break; + } + if (higher_count > 0) (void)nvhost_cdma_flush(&job->ch->cdma, NVHOST_CHANNEL_LOW_PRIO_MAX_WAIT); diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c index ba821f694cb4..af2e3ad1bdb5 100644 --- a/drivers/video/tegra/host/nvhost_intr.c +++ b/drivers/video/tegra/host/nvhost_intr.c @@ -128,12 +128,16 @@ static void action_submit_complete(struct nvhost_waitlist *waiter) struct nvhost_channel *channel = waiter->data; int nr_completed = waiter->count; + nvhost_cdma_update(&channel->cdma); + nvhost_module_idle_mult(channel->dev, nr_completed); + /* Add nr_completed to trace */ trace_nvhost_channel_submit_complete(channel->dev->name, - nr_completed, waiter->thresh); + nr_completed, waiter->thresh, + channel->cdma.high_prio_count, + channel->cdma.med_prio_count, + channel->cdma.low_prio_count); - nvhost_cdma_update(&channel->cdma); - nvhost_module_idle_mult(channel->dev, nr_completed); } static void action_ctxsave(struct nvhost_waitlist *waiter) -- cgit v1.2.3 From aef1c84834f5228316d1e096434abf98ced90eb6 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Mon, 28 May 2012 14:06:05 +0300 Subject: video: tegra: host: Dump sync queue in debug dump Dump contents of sync queue when debug dump is requested, either because of a stuck sync point, or when the debugfs entry is accessed. Exclude FIFO from normal debugfs dump. Dumping FIFO is invasive and actually changes how the channel behaves. It's safe to dump only when system is in fault condition. Change-Id: I12c68e8186acd7bd17e4ab52b2589f765396ed17 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/104970 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Juha Tukkinen --- drivers/video/tegra/host/debug.c | 67 +++++++++++++- drivers/video/tegra/host/host1x/host1x_debug.c | 117 +++++++++++++++---------- 2 files changed, 134 insertions(+), 50 deletions(-) (limited to 'drivers/video/tegra') diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c index 8a26f92c79f6..820eac85521d 100644 --- a/drivers/video/tegra/host/debug.c +++ b/drivers/video/tegra/host/debug.c @@ -106,13 +106,53 @@ static void show_all(struct nvhost_master *m, struct output *o) nvhost_get_chip_ops()->debug.show_mlocks(m, o); show_syncpts(m, o); nvhost_debug_output(o, "---- channels ----\n"); - bus_for_each_dev(&(nvhost_bus_get())->nvhost_bus_type, NULL, o, show_channels); + bus_for_each_dev(&(nvhost_bus_get())->nvhost_bus_type, NULL, o, + show_channels); nvhost_module_idle(m->dev); } #ifdef CONFIG_DEBUG_FS -static int nvhost_debug_show(struct seq_file *s, void *unused) +static int show_channels_no_fifo(struct device *dev, void *data) +{ + struct nvhost_channel *ch; + struct nvhost_device *nvdev = to_nvhost_device(dev); + struct output *o = data; + struct nvhost_master *m; + + if (nvdev == NULL) + return 0; + + m = nvhost_get_host(nvdev); + ch = nvdev->channel; + if (ch) { + mutex_lock(&ch->reflock); + if (ch->refcount) { + mutex_lock(&ch->cdma.lock); + nvhost_get_chip_ops()->debug.show_channel_cdma(m, + ch, o, nvdev->index); + mutex_unlock(&ch->cdma.lock); + } + mutex_unlock(&ch->reflock); + } + + return 0; +} + +static void show_all_no_fifo(struct nvhost_master *m, struct output *o) +{ + nvhost_module_busy(m->dev); + + nvhost_get_chip_ops()->debug.show_mlocks(m, o); + show_syncpts(m, o); + nvhost_debug_output(o, "---- channels ----\n"); + bus_for_each_dev(&(nvhost_bus_get())->nvhost_bus_type, NULL, o, + show_channels_no_fifo); + + nvhost_module_idle(m->dev); +} + +static int nvhost_debug_show_all(struct seq_file *s, void *unused) { struct output o = { .fn = write_to_seqfile, @@ -121,6 +161,27 @@ static int nvhost_debug_show(struct seq_file *s, void *unused) show_all(s->private, &o); return 0; } +static int nvhost_debug_show(struct seq_file *s, void *unused) +{ + struct output o = { + .fn = write_to_seqfile, + .ctx = s + }; + show_all_no_fifo(s->private, &o); + return 0; +} + +static int nvhost_debug_open_all(struct inode *inode, struct file *file) +{ + return single_open(file, nvhost_debug_show_all, inode->i_private); +} + +static const struct file_operations nvhost_debug_all_fops = { + .open = nvhost_debug_open_all, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; static int nvhost_debug_open(struct inode *inode, struct file *file) { @@ -140,6 +201,8 @@ void nvhost_debug_init(struct nvhost_master *master) debugfs_create_file("status", S_IRUGO, de, master, &nvhost_debug_fops); + debugfs_create_file("status_all", S_IRUGO, de, + master, &nvhost_debug_all_fops); debugfs_create_u32("null_kickoff_pid", S_IRUGO|S_IWUSR, de, &nvhost_debug_null_kickoff_pid); diff --git a/drivers/video/tegra/host/host1x/host1x_debug.c b/drivers/video/tegra/host/host1x/host1x_debug.c index a5574a0fb60a..7de342298c4d 100644 --- a/drivers/video/tegra/host/host1x/host1x_debug.c +++ b/drivers/video/tegra/host/host1x/host1x_debug.c @@ -28,8 +28,8 @@ #include "host1x_hardware.h" #include "nvhost_cdma.h" #include "nvhost_channel.h" -#include "../../nvmap/nvmap.h" #include "host1x_cdma.h" +#include "nvhost_job.h" #define NVHOST_DEBUG_MAX_PAGE_OFFSET 102400 @@ -160,6 +160,34 @@ static void show_channel_word(struct output *o, int *state, int *count, } } +static void do_show_channel_gather(struct output *o, + phys_addr_t phys_addr, + u32 words, struct nvhost_cdma *cdma, + phys_addr_t pin_addr, u32 *map_addr) +{ + /* Map dmaget cursor to corresponding nvmap_handle */ + u32 offset; + int state, count, i; + + offset = phys_addr - pin_addr; + /* + * Sometimes we're given different hardware address to the same + * page - in these cases the offset will get an invalid number and + * we just have to bail out. + */ + if (offset > NVHOST_DEBUG_MAX_PAGE_OFFSET) { + nvhost_debug_output(o, "[address mismatch]\n"); + } else { + /* GATHER buffer starts always with commands */ + state = NVHOST_DBG_STATE_CMD; + for (i = 0; i < words; i++) + show_channel_word(o, &state, &count, + phys_addr + i * 4, + *(map_addr + offset/4 + i), + cdma); + } +} + static void show_channel_gather(struct output *o, u32 addr, phys_addr_t phys_addr, u32 words, struct nvhost_cdma *cdma) @@ -171,10 +199,8 @@ static void show_channel_gather(struct output *o, u32 addr, struct nvmap_client_handle *nvmap = &pb->nvmap[cur/8]; u32 *map_addr, offset; phys_addr_t pin_addr; - int state, count, i; - if (!nvmap->handle || !nvmap->client - || atomic_read(&nvmap->handle->handle->ref) < 1) { + if (!nvmap || !nvmap->handle || !nvmap->client) { nvhost_debug_output(o, "[already deallocated]\n"); return; } @@ -194,51 +220,13 @@ static void show_channel_gather(struct output *o, u32 addr, } offset = phys_addr - pin_addr; - /* - * Sometimes we're given different hardware address to the same - * page - in these cases the offset will get an invalid number and - * we just have to bail out. - */ - if (offset > NVHOST_DEBUG_MAX_PAGE_OFFSET) { - nvhost_debug_output(o, "[address mismatch]\n"); - } else { - /* GATHER buffer starts always with commands */ - state = NVHOST_DBG_STATE_CMD; - for (i = 0; i < words; i++) - show_channel_word(o, &state, &count, - phys_addr + i * 4, - *(map_addr + offset/4 + i), - cdma); - } + do_show_channel_gather(o, phys_addr, words, cdma, + pin_addr, map_addr); nvmap_unpin(nvmap->client, nvmap->handle); nvmap_munmap(nvmap->handle, map_addr); #endif } -static void show_channel_pair(struct output *o, u32 addr, - u32 w0, u32 w1, struct nvhost_cdma *cdma) -{ - int state = NVHOST_DBG_STATE_CMD; - int count; - - show_channel_word(o, &state, &count, addr, w0, cdma); - show_channel_word(o, &state, &count, addr+4, w1, cdma); -} - -/** - * Retrieve the op pair at a slot offset from a DMA address - */ -static void cdma_peek(struct nvhost_cdma *cdma, - u32 dmaget, int slot, u32 *out) -{ - u32 offset = dmaget - cdma->push_buffer.phys; - u32 *p = cdma->push_buffer.mapped; - - offset = ((offset + slot * 8) & (PUSH_BUFFER_SIZE - 1)) >> 2; - out[0] = p[offset]; - out[1] = p[offset + 1]; -} - u32 previous_oppair(struct nvhost_cdma *cdma, u32 cur) { u32 pb = cdma->push_buffer.phys; @@ -248,6 +236,42 @@ u32 previous_oppair(struct nvhost_cdma *cdma, u32 cur) return prev; } +void show_channel_gathers(struct output *o, struct nvhost_cdma *cdma) +{ + struct nvhost_job *job; + + list_for_each_entry(job, &cdma->sync_queue, list) { + int i; + nvhost_debug_output(o, "\n%p: JOB, syncpt_id=%d, syncpt_val=%d," + " first_get=%08x, timeout=%d, ctx=%p," + " num_slots=%d, num_handles=%d\n", + job, + job->syncpt_id, + job->syncpt_end, + job->first_get, + job->timeout, + job->hwctx, + job->num_slots, + job->num_unpins); + + for (i = 0; i < job->num_gathers; i++) { + struct nvhost_job_gather *g = &job->gathers[i]; + u32 *mapped = nvmap_mmap(g->ref); + if (!mapped) { + nvhost_debug_output(o, "[could not mmap]\n"); + continue; + } + + nvhost_debug_output(o, " GATHER at %08x, %d words\n", + g->mem, g->words); + + do_show_channel_gather(o, g->mem + g->offset, + g->words, cdma, g->mem, mapped); + nvmap_munmap(g->ref, mapped); + } + } +} + static void t20_debug_show_channel_cdma(struct nvhost_master *m, struct nvhost_channel *ch, struct output *o, int chid) { @@ -256,7 +280,6 @@ static void t20_debug_show_channel_cdma(struct nvhost_master *m, u32 dmaput, dmaget, dmactrl; u32 cbstat, cbread; u32 val, base, baseval; - u32 pbw[2]; dmaput = readl(channel->aperture + HOST1X_CHANNEL_DMAPUT); dmaget = readl(channel->aperture + HOST1X_CHANNEL_DMAGET); @@ -305,9 +328,7 @@ static void t20_debug_show_channel_cdma(struct nvhost_master *m, dmaput, dmaget, dmactrl); nvhost_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat); - cdma_peek(cdma, dmaget, -1, pbw); - show_channel_pair(o, previous_oppair(cdma, dmaget), - pbw[0], pbw[1], &channel->cdma); + show_channel_gathers(o, cdma); nvhost_debug_output(o, "\n"); } -- cgit v1.2.3