From 6490ad47404539b479ca33f96793c4624bef2924 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 4 Jun 2015 10:26:37 -0400 Subject: drm/msm: clarify downstream bus scaling A few spots in the driver have support for downstream android CONFIG_MSM_BUS_SCALING. This is mainly to simplify backporting the driver for various devices which do not have sufficient upstream kernel support. But the intentionally dead code seems to cause some confusion. Rename the #define to make this more clear. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/msm/msm_gpu.c') diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4a0dce587745..98977ab130ee 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -24,7 +24,7 @@ * Power Management: */ -#ifdef CONFIG_MSM_BUS_SCALING +#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING #include static void bs_init(struct msm_gpu *gpu) { -- cgit v1.2.3-59-g8ed1b From de558cd2ae2e9999d0b6328c22c398ff85b6327c Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 6 May 2015 13:14:30 -0400 Subject: drm/msm: adreno a306 support As found in apq8016 (used in DragonBoard 410c) and msm8916. Note that numerically a306 is actually 307 (since a305c already claimed 306). Nice and confusing. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 12 +++++++++--- drivers/gpu/drm/msm/adreno/adreno_device.c | 8 ++++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.h | 6 ++++++ drivers/gpu/drm/msm/msm_gpu.c | 1 + drivers/gpu/drm/msm/msm_gpu.h | 2 +- 5 files changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_gpu.c') diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 0f0c45665dbd..fd266ed963b6 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -93,7 +93,10 @@ static int a3xx_hw_init(struct msm_gpu *gpu) /* Set up AOOO: */ gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); - + } else if (adreno_is_a306(adreno_gpu)) { + gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003); + gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a); + gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a); } else if (adreno_is_a320(adreno_gpu)) { /* Set up 16 deep read/write request queues: */ gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); @@ -186,7 +189,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); /* Enable Clock gating: */ - if (adreno_is_a320(adreno_gpu)) + if (adreno_is_a306(adreno_gpu)) + gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); + else if (adreno_is_a320(adreno_gpu)) gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff); else if (adreno_is_a330v2(adreno_gpu)) gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); @@ -271,7 +276,8 @@ static int a3xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]); /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ - if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) { + if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) || + adreno_is_a320(adreno_gpu)) { gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) | AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) | diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 37b18e2c9a3c..1ea2df524fac 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -41,6 +41,14 @@ static const struct adreno_info gpulist[] = { .pfpfw = "a300_pfp.fw", .gmem = SZ_256K, .init = a3xx_gpu_init, + }, { + .rev = ADRENO_REV(3, 0, 6, 0), + .revn = 307, /* because a305c is revn==306 */ + .name = "A306", + .pm4fw = "a300_pm4.fw", + .pfpfw = "a300_pfp.fw", + .gmem = SZ_128K, + .init = a3xx_gpu_init, }, { .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID), .revn = 320, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index ab7f40bef9f1..0a312e9d3afd 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -197,6 +197,12 @@ static inline bool adreno_is_a305(struct adreno_gpu *gpu) return gpu->revn == 305; } +static inline bool adreno_is_a306(struct adreno_gpu *gpu) +{ + /* yes, 307, because a305c is 306 */ + return gpu->revn == 307; +} + static inline bool adreno_is_a320(struct adreno_gpu *gpu) { return gpu->revn == 320; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 98977ab130ee..4016aef56c50 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -522,6 +522,7 @@ static irqreturn_t irq_handler(int irq, void *data) static const char *clk_names[] = { "src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk", + "alt_mem_iface_clk", }; int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 2c46f1d820e0..7b3ec21d5d77 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -100,7 +100,7 @@ struct msm_gpu { /* Power Control: */ struct regulator *gpu_reg, *gpu_cx; - struct clk *ebi1_clk, *grp_clks[5]; + struct clk *ebi1_clk, *grp_clks[6]; uint32_t fast_rate, slow_rate, bus_freq; #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -- cgit v1.2.3-59-g8ed1b From 1a370be9ac51129e40b0ed7fa71d2b2b92bc47e5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 7 Jun 2015 13:46:04 -0400 Subject: drm/msm: restart queued submits after hang Track the list of in-flight submits. If the gpu hangs, retire up to an including the offending submit, and then re-submit the remainder. This way, for concurrently running piglit tests (for example), one failing test doesn't cause unrelated tests to fail simply because it's submit was queued up after one that triggered a hang. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem.h | 1 + drivers/gpu/drm/msm/msm_gem_submit.c | 1 - drivers/gpu/drm/msm/msm_gpu.c | 49 +++++++++++++++++++++++++++++++++--- drivers/gpu/drm/msm/msm_gpu.h | 2 ++ 4 files changed, 49 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_gpu.c') diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 85d481e29276..6fc59bfeedeb 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -96,6 +96,7 @@ static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj, struct msm_gem_submit { struct drm_device *dev; struct msm_gpu *gpu; + struct list_head node; /* node in gpu submit_list */ struct list_head bo_list; struct ww_acquire_ctx ticket; uint32_t fence; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index cd0554f68316..6d7cd3fe21e7 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -314,7 +314,6 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool fail) } ww_acquire_fini(&submit->ticket); - kfree(submit); } int msm_ioctl_gem_submit(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4016aef56c50..8f70d9248ac5 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -265,6 +265,8 @@ static void inactive_start(struct msm_gpu *gpu) * Hangcheck detection for locked gpu: */ +static void retire_submits(struct msm_gpu *gpu, uint32_t fence); + static void recover_worker(struct work_struct *work) { struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); @@ -274,8 +276,19 @@ static void recover_worker(struct work_struct *work) mutex_lock(&dev->struct_mutex); if (msm_gpu_active(gpu)) { + struct msm_gem_submit *submit; + uint32_t fence = gpu->funcs->last_fence(gpu); + + /* retire completed submits, plus the one that hung: */ + retire_submits(gpu, fence + 1); + inactive_cancel(gpu); gpu->funcs->recover(gpu); + + /* replay the remaining submits after the one that hung: */ + list_for_each_entry(submit, &gpu->submit_list, node) { + gpu->funcs->submit(gpu, submit, NULL); + } } mutex_unlock(&dev->struct_mutex); @@ -418,6 +431,27 @@ out: * Cmdstream submission/retirement: */ +static void retire_submits(struct msm_gpu *gpu, uint32_t fence) +{ + struct drm_device *dev = gpu->dev; + + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + + while (!list_empty(&gpu->submit_list)) { + struct msm_gem_submit *submit; + + submit = list_first_entry(&gpu->submit_list, + struct msm_gem_submit, node); + + if (submit->fence <= fence) { + list_del(&submit->node); + kfree(submit); + } else { + break; + } + } +} + static void retire_worker(struct work_struct *work) { struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work); @@ -428,6 +462,8 @@ static void retire_worker(struct work_struct *work) mutex_lock(&dev->struct_mutex); + retire_submits(gpu, fence); + while (!list_empty(&gpu->active_list)) { struct msm_gem_object *obj; @@ -467,21 +503,22 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, struct msm_drm_private *priv = dev->dev_private; int i, ret; + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + submit->fence = ++priv->next_fence; gpu->submitted_fence = submit->fence; inactive_cancel(gpu); + list_add_tail(&submit->node, &gpu->submit_list); + msm_rd_dump_submit(submit); gpu->submitted_fence = submit->fence; update_sw_cntrs(gpu); - ret = gpu->funcs->submit(gpu, submit, ctx); - priv->lastctx = ctx; - for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; @@ -505,6 +542,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); } + + ret = gpu->funcs->submit(gpu, submit, ctx); + priv->lastctx = ctx; + hangcheck_timer_reset(gpu); return ret; @@ -545,6 +586,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, INIT_WORK(&gpu->inactive_work, inactive_worker); INIT_WORK(&gpu->recover_work, recover_worker); + INIT_LIST_HEAD(&gpu->submit_list); + setup_timer(&gpu->inactive_timer, inactive_handler, (unsigned long)gpu); setup_timer(&gpu->hangcheck_timer, hangcheck_handler, diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 7b3ec21d5d77..2bbe85a3d6f6 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -119,6 +119,8 @@ struct msm_gpu { struct timer_list hangcheck_timer; uint32_t hangcheck_fence; struct work_struct recover_work; + + struct list_head submit_list; }; static inline bool msm_gpu_active(struct msm_gpu *gpu) -- cgit v1.2.3-59-g8ed1b