From 35b09c9bf619c4fc6040c52dcea6bd5bd6af7679 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 28 Oct 2011 14:42:41 +0300 Subject: drm/i915: fix if statement (bogus semi-colon) The semi-colon is a typo here and it makes the if statement unconditional. Signed-off-by: Dan Carpenter Signed-off-by: Keith Packard diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 66cd0b8..3a8d448 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1236,7 +1236,7 @@ static int i9xx_setup(void) intel_private.gtt_bus_addr = reg_addr + gtt_offset; } - if (needs_idle_maps()); + if (needs_idle_maps()) intel_private.base.do_idle_maps = 1; intel_i9xx_setup_flush(); -- cgit v0.10.2 From a08185a3eb658854b29c05bcbfac0f85038ffe9f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 28 Oct 2011 10:28:00 -0700 Subject: agp: iommu_gfx_mapped only available if CONFIG_INTEL_IOMMU is set Kernels with no iommu support cannot ever need the Ironlake work-around, so never enable it in that case. Might be better to completely remove the work-around from the kernel in this case? Signed-off-by: Keith Packard Reviewed-by: Ben Widawsky diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 3a8d448..c92424c 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1186,10 +1186,11 @@ static void gen6_cleanup(void) /* Certain Gen5 chipsets require require idling the GPU before * unmapping anything from the GTT when VT-d is enabled. */ -extern int intel_iommu_gfx_mapped; static inline int needs_idle_maps(void) { +#ifdef CONFIG_INTEL_IOMMU const unsigned short gpu_devid = intel_private.pcidev->device; + extern int intel_iommu_gfx_mapped; /* Query intel_iommu to see if we need the workaround. Presumably that * was loaded first. @@ -1198,7 +1199,7 @@ static inline int needs_idle_maps(void) gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && intel_iommu_gfx_mapped) return 1; - +#endif return 0; } -- cgit v0.10.2 From 14660ccd599dc7bd6ecef17408bd76dc853f9b77 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 31 Oct 2011 23:16:21 -0700 Subject: drm/i915: Fix object refcount leak on mmappable size limit error path. I've been seeing memory leaks on my system in the form of large (300-400MB) GEM objects created by now-dead processes laying around clogging up memory. I usually notice when it gets to about 1.2GB of them. Hopefully this clears up the issue, but I just found this bug by inspection. Signed-off-by: Eric Anholt Cc: stable@kernel.org Signed-off-by: Keith Packard diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6651c36..d18b07a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1396,7 +1396,7 @@ i915_gem_mmap_gtt(struct drm_file *file, if (obj->base.size > dev_priv->mm.gtt_mappable_end) { ret = -E2BIG; - goto unlock; + goto out; } if (obj->madv != I915_MADV_WILLNEED) { -- cgit v0.10.2 From bde4889aaa2d59c1febfeadd7f690be0ed143ed5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jul 2011 12:52:27 +1000 Subject: drm: make sure drm_vblank_init() has been called before touching vbl_lock Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index cb3794a..4d3760c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -407,13 +407,16 @@ int drm_irq_uninstall(struct drm_device *dev) /* * Wake up any waiters so they don't hang. */ - spin_lock_irqsave(&dev->vbl_lock, irqflags); - for (i = 0; i < dev->num_crtcs; i++) { - DRM_WAKEUP(&dev->vbl_queue[i]); - dev->vblank_enabled[i] = 0; - dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i); + if (dev->num_crtcs) { + spin_lock_irqsave(&dev->vbl_lock, irqflags); + for (i = 0; i < dev->num_crtcs; i++) { + DRM_WAKEUP(&dev->vbl_queue[i]); + dev->vblank_enabled[i] = 0; + dev->last_vblank[i] = + dev->driver->get_vblank_counter(dev, i); + } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); if (!irq_enabled) return -EINVAL; -- cgit v0.10.2 From 46b348865011bf0d706fe1ec8c9cef08cf86ad40 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 22 Sep 2011 12:51:31 +1000 Subject: drm/nouveau: fix oops if i2c bus not found in nouveau_i2c_identify() Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index c6143df..d39b220 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -333,7 +333,7 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); - for (i = 0; info[i].addr; i++) { + for (i = 0; i2c && info[i].addr; i++) { if (nouveau_probe_i2c_addr(i2c, info[i].addr) && (!match || match(i2c, &info[i]))) { NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); -- cgit v0.10.2 From ee9f7ef99f4422463634c075b22197c22c5cfa71 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 23 Sep 2011 15:37:38 +1000 Subject: drm/nv50/bios: fixup mpll programming from the init table parser Reportedly this has been causing stability and corruption issues after resuming from suspend for a few people. Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 032a820..5fc201b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -640,10 +640,9 @@ static int nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t reg0 = nv_rd32(dev, reg + 0); - uint32_t reg1 = nv_rd32(dev, reg + 4); struct nouveau_pll_vals pll; struct pll_lims pll_limits; + u32 ctrl, mask, coef; int ret; ret = get_pll_limits(dev, reg, &pll_limits); @@ -654,15 +653,20 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk) if (!clk) return -ERANGE; - reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16); - reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1; - - if (dev_priv->vbios.execute) { - still_alive(); - nv_wr32(dev, reg + 4, reg1); - nv_wr32(dev, reg + 0, reg0); + coef = pll.N1 << 8 | pll.M1; + ctrl = pll.log2P << 16; + mask = 0x00070000; + if (reg == 0x004008) { + mask |= 0x01f80000; + ctrl |= (pll_limits.log2p_bias << 19); + ctrl |= (pll.log2P << 22); } + if (!dev_priv->vbios.execute) + return 0; + + nv_mask(dev, reg + 0, mask, ctrl); + nv_wr32(dev, reg + 4, coef); return 0; } -- cgit v0.10.2 From dce411cdf60eb64638443f953b52c18192378305 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 29 Sep 2011 13:15:17 +1000 Subject: drm/nv50/gr: typo fix, how about we not reset fifo during graph init? Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 8c979b3..ac601f7 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -131,8 +131,8 @@ nv50_graph_init(struct drm_device *dev, int engine) NV_DEBUG(dev, "\n"); /* master reset */ - nv_mask(dev, 0x000200, 0x00200100, 0x00000000); - nv_mask(dev, 0x000200, 0x00200100, 0x00200100); + nv_mask(dev, 0x000200, 0x00201000, 0x00000000); + nv_mask(dev, 0x000200, 0x00201000, 0x00201000); nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ /* reset/enable traps and interrupts */ -- cgit v0.10.2 From 7b4b98fa0c4d3a975b36bfe9984e4cd117f2ddff Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 7 Oct 2011 16:00:31 +1000 Subject: drm/nv50/vram: fix incorrect detection of bank count on newer chipsets NVA3+ has an extra bit here compared to NV50:NVA3 chipsets. Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c index 9da2383..2e45e57 100644 --- a/drivers/gpu/drm/nouveau/nv50_vram.c +++ b/drivers/gpu/drm/nouveau/nv50_vram.c @@ -160,7 +160,7 @@ nv50_vram_rblock(struct drm_device *dev) colbits = (r4 & 0x0000f000) >> 12; rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; - banks = ((r4 & 0x01000000) ? 8 : 4); + banks = 1 << (((r4 & 0x03000000) >> 24) + 2); rowsize = parts * banks * (1 << colbits) * 8; predicted = rowsize << rowbitsa; -- cgit v0.10.2 From 5e60ee780e792efe6dce97eceb110b1d30bab850 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Fri, 9 Sep 2011 14:16:42 +0200 Subject: drm/nouveau: initialize chan->fence.lock before use Fence lock needs to be initialized before any call to nouveau_channel_put because it calls nouveau_channel_idle->nouveau_fence_update which uses fence lock. BUG: spinlock bad magic on CPU#0, test/24134 lock: ffff88019f90dba8, .magic: 00000000, .owner: /-1, .owner_cpu: 0 Pid: 24134, comm: test Not tainted 3.0.0-nv+ #800 Call Trace: spin_bug+0x9c/0xa3 do_raw_spin_lock+0x29/0x13c _raw_spin_lock+0x1e/0x22 nouveau_fence_update+0x2d/0xf1 nouveau_channel_idle+0x22/0xa0 nouveau_channel_put_unlocked+0x84/0x1bd nouveau_channel_put+0x20/0x24 nouveau_channel_alloc+0x4ec/0x585 nouveau_ioctl_fifo_alloc+0x50/0x130 drm_ioctl+0x289/0x361 do_vfs_ioctl+0x4dd/0x52c sys_ioctl+0x42/0x65 system_call_fastpath+0x16/0x1b It's easily triggerable from userspace. Additionally remove double initialization of chan->fence.pending. Signed-off-by: Marcin Slusarz Cc: stable@kernel.org Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index a319d564..bb6ec9e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, INIT_LIST_HEAD(&chan->nvsw.vbl_wait); INIT_LIST_HEAD(&chan->nvsw.flip); INIT_LIST_HEAD(&chan->fence.pending); + spin_lock_init(&chan->fence.lock); /* setup channel's memory and vm */ ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 81116cf..2f6daae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) return ret; } - INIT_LIST_HEAD(&chan->fence.pending); - spin_lock_init(&chan->fence.lock); atomic_set(&chan->fence.last_sequence_irq, 0); return 0; } -- cgit v0.10.2 From 71856abefb49bae5d67275752ada02853c16660d Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Sun, 9 Oct 2011 22:58:31 +0200 Subject: drm/nv50: fix stability issue on NV86. Confirmed to fix random hangs while running all Unegine demos on NV86. Signed-off-by: Maxim Levitsky Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c index d05c2c3..4b46d69 100644 --- a/drivers/gpu/drm/nouveau/nv50_grctx.c +++ b/drivers/gpu/drm/nouveau/nv50_grctx.c @@ -601,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) gr_def(ctx, offset + 0x1c, 0x00880000); break; case 0x86: - gr_def(ctx, offset + 0x1c, 0x008c0000); + gr_def(ctx, offset + 0x1c, 0x018c0000); break; case 0x92: case 0x96: -- cgit v0.10.2 From 12b6d9d881ccb64a833d53565a3579e12ab1d026 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Fri, 7 Oct 2011 18:10:45 +0200 Subject: drm/nvc0/vram: storage type 0xc3 is not compressed Signed-off-by: Christoph Bumiller Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c index edbfe93..041ff2b 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vram.c +++ b/drivers/gpu/drm/nouveau/nvc0_vram.c @@ -43,7 +43,7 @@ static const u8 types[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 -- cgit v0.10.2 From ef5ced4bfe48ba2acb16e867ceb9c473dd0ef192 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Oct 2011 09:07:51 +0300 Subject: drm/nouveau: testing the wrong variable memtimings is a valid pointer here, the intent was to test for kcalloc() failure. Signed-off-by: Dan Carpenter Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index 9f178aa..33d03fb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -239,7 +239,7 @@ nouveau_perf_init(struct drm_device *dev) if(version == 0x15) { memtimings->timing = kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); - if(!memtimings) { + if (!memtimings->timing) { NV_WARN(dev,"Could not allocate memtiming table\n"); return; } -- cgit v0.10.2 From 2bfa7482224903097a50c14a4389a29f56e19c3b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 19 Oct 2011 14:06:59 +1000 Subject: drm/nv40/pm: fix issues on igp chipsets, which don't have memory Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index bbc0b9c..e676b0d 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg) int P = (ctrl & 0x00070000) >> 16; u32 ref = 27000, clk = 0; - if (ctrl & 0x80000000) + if ((ctrl & 0x80000000) && M1) { clk = ref * N1 / M1; - - if (!(ctrl & 0x00000100)) { - if (ctrl & 0x40000000) - clk = clk * N2 / M2; + if ((ctrl & 0x40000100) == 0x40000000) { + if (M2) + clk = clk * N2 / M2; + else + clk = 0; + } } return clk >> P; @@ -177,6 +179,11 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) } /* memory clock */ + if (!perflvl->memory) { + info->mpll_ctrl = 0x00000000; + goto out; + } + ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, &N1, &M1, &N2, &M2, &log2P); if (ret < 0) @@ -264,6 +271,9 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) mdelay(5); nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); + if (!info->mpll_ctrl) + goto resume; + /* wait for vblank start on active crtcs, disable memory access */ for (i = 0; i < 2; i++) { if (!(crtc_mask & (1 << i))) -- cgit v0.10.2 From d4547ed8cc219f2e06078ac05147a873b2a03d5a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 27 Oct 2011 11:26:17 +1000 Subject: drm/nvc0/vram: skip disabled PBFB subunits Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c index 041ff2b..ce984d5 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vram.c +++ b/drivers/gpu/drm/nouveau/nvc0_vram.c @@ -110,22 +110,26 @@ nvc0_vram_init(struct drm_device *dev) u32 bsize = nv_rd32(dev, 0x10f20c); u32 offset, length; bool uniform = true; - int ret, i; + int ret, part; NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); /* read amount of vram attached to each memory controller */ - for (i = 0; i < parts; i++) { - u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000)); + part = 0; + while (parts) { + u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000)); + if (psize == 0) + continue; + parts--; + if (psize != bsize) { if (psize < bsize) bsize = psize; uniform = false; } - NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize); - + NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); dev_priv->vram_size += (u64)psize << 20; } -- cgit v0.10.2 From 80859760daa01fb38497aa6326a32a16489d8c97 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 27 Oct 2011 11:31:49 +1000 Subject: drm/nvc0: enable acceleration on 0xc8 by default Worked well enough for glxgears and gnome-shell at least, no reason to have this off anymore. Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 82478e0..2afd5b1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -1103,7 +1103,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) if (nouveau_noaccel == -1) { switch (dev_priv->chipset) { case 0xc1: /* known broken */ - case 0xc8: /* never tested */ NV_INFO(dev, "acceleration disabled by default, pass " "noaccel=0 to force enable\n"); dev_priv->noaccel = true; -- cgit v0.10.2 From af6d9fe5368aadd8f0f3647b38405ffcd3ed5f81 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 11 Jul 2011 15:40:43 +1000 Subject: drm/nvc0/gr: fix some bugs in grctx generation Most serious is for chips with only 1 TPC, we'd get stuck in an infinite loop. The fix here will slightly change the setup for all other chipsets too, but, it shouldn't matter too much, and this all needs figuring out and likely redone anyway. Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c index dd0e6a7..96b0b93 100644 --- a/drivers/gpu/drm/nouveau/nvc0_grctx.c +++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c @@ -1812,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) /* calculate first set of magics */ memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + gpc = -1; for (tp = 0; tp < priv->tp_total; tp++) { do { gpc = (gpc + 1) % priv->gpc_nr; @@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan) if (1) { u32 tp_mask = 0, tp_set = 0; - u8 tpnr[GPC_MAX]; + u8 tpnr[GPC_MAX], a, b; memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); for (gpc = 0; gpc < priv->gpc_nr; gpc++) tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8); - gpc = -1; - for (i = 0, gpc = -1; i < 32; i++) { - int ltp = i * (priv->tp_total - 1) / 32; - - do { - gpc = (gpc + 1) % priv->gpc_nr; - } while (!tpnr[gpc]); - tp = priv->tp_nr[gpc] - tpnr[gpc]--; + for (i = 0, gpc = -1, b = -1; i < 32; i++) { + a = (i * (priv->tp_total - 1)) / 32; + if (a != b) { + b = a; + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpnr[gpc]); + tp = priv->tp_nr[gpc] - tpnr[gpc]--; - tp_set |= 1 << ((gpc * 8) + tp); + tp_set |= 1 << ((gpc * 8) + tp); + } - do { - nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); - tp_set ^= tp_mask; - nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set); - tp_set ^= tp_mask; - } while (ltp == (++i * (priv->tp_total - 1) / 32)); - i--; + nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); + nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); } } -- cgit v0.10.2 From 4c5df493eb30089ff0b8d03a50a86293f758a786 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 28 Oct 2011 10:59:45 +1000 Subject: drm/nvc1: hacky workaround to fix accel issues Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 2afd5b1..9a5ab61 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out_display_early; + /* workaround an odd issue on nvc1 by disabling the device's + * nosnoop capability. hopefully won't cause issues until a + * better fix is found - assuming there is one... + */ + if (dev_priv->chipset == 0xc1) { + nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); + } + nouveau_pm_init(dev); ret = engine->vram.init(dev); -- cgit v0.10.2 From 6688a4dd20bf774d654203a0629d454447b80502 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 28 Oct 2011 11:43:04 +1000 Subject: drm/nvc0/gr: fixup the mmio list register writes for 0xc1 Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index bbdbc51..a74e501 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -157,8 +157,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; int i = 0, gpc, tp, ret; - u32 magic; ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, &grch->unk408004); @@ -207,14 +207,37 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) nv_wo32(grch->mmio, i++ * 4, 0x0041880c); nv_wo32(grch->mmio, i++ * 4, 0x80000018); - magic = 0x02180000; - nv_wo32(grch->mmio, i++ * 4, 0x00405830); - nv_wo32(grch->mmio, i++ * 4, magic); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) { - u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800); - nv_wo32(grch->mmio, i++ * 4, reg); - nv_wo32(grch->mmio, i++ * 4, magic); + if (dev_priv->chipset != 0xc1) { + u32 magic = 0x02180000; + nv_wo32(grch->mmio, i++ * 4, 0x00405830); + nv_wo32(grch->mmio, i++ * 4, magic); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { + u32 reg = TP_UNIT(gpc, tp, 0x520); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, magic); + magic += 0x0324; + } + } + } else { + u32 magic = 0x02180000; + nv_wo32(grch->mmio, i++ * 4, 0x00405830); + nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218); + nv_wo32(grch->mmio, i++ * 4, 0x004064c4); + nv_wo32(grch->mmio, i++ * 4, 0x0086ffff); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { + u32 reg = TP_UNIT(gpc, tp, 0x520); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic); + magic += 0x0324; + } + for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { + u32 reg = TP_UNIT(gpc, tp, 0x544); + nv_wo32(grch->mmio, i++ * 4, reg); + nv_wo32(grch->mmio, i++ * 4, magic); + magic += 0x0324; + } } } -- cgit v0.10.2 From 1c77e0f7fa4b398652f8e03f125aed258fa7018e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 28 Oct 2011 11:00:39 +1000 Subject: drm/nvc0: enable acceleration for nvc1 by default Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 9a5ab61..d8831ab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -1110,11 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev_priv->noaccel = !!nouveau_noaccel; if (nouveau_noaccel == -1) { switch (dev_priv->chipset) { - case 0xc1: /* known broken */ +#if 0 + case 0xXX: /* known broken */ NV_INFO(dev, "acceleration disabled by default, pass " "noaccel=0 to force enable\n"); dev_priv->noaccel = true; break; +#endif default: dev_priv->noaccel = false; break; -- cgit v0.10.2 From 4beb116a454867cc3a98d02d906e0f0459aefe72 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 6 Nov 2011 21:21:28 +0100 Subject: drm/nv10: Change the BO size threshold determining the memory placement range. Fixes the framebuffer memory allocation failure seen on some low-memory cards, followed by X refusing to start. https://bugs.freedesktop.org/show_bug.cgi?id=42384 Reported-by: Chris Paulson-Ellis Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7226f41..7cc37e6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -148,7 +148,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type) if (dev_priv->card_type == NV_10 && nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && - nvbo->bo.mem.num_pages < vram_pages / 2) { + nvbo->bo.mem.num_pages < vram_pages / 4) { /* * Make sure that the color and depth buffers are handled * by independent memory controller units. Up to a 9x -- cgit v0.10.2 From 1e482f75f169861e992eb6b5602dc73a9e0b63a2 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 6 Nov 2011 20:32:04 +0100 Subject: drm/nouveau: by default use low bpp framebuffer on low memory cards Framebuffer's BPP is not that important but can waste significant part of memory on low-VRAM cards. Lower it to 8bpp on < 32MB cards and to 16bpp on 64MB cards. It can still be overridden by video= option. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 14a8627..3a4cc32 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -487,6 +487,7 @@ int nouveau_fbcon_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fbdev *nfbdev; + int preferred_bpp; int ret; nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); @@ -505,7 +506,15 @@ int nouveau_fbcon_init(struct drm_device *dev) } drm_fb_helper_single_add_all_connectors(&nfbdev->helper); - drm_fb_helper_initial_config(&nfbdev->helper, 32); + + if (dev_priv->vram_size <= 32 * 1024 * 1024) + preferred_bpp = 8; + else if (dev_priv->vram_size <= 64 * 1024 * 1024) + preferred_bpp = 16; + else + preferred_bpp = 32; + + drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp); return 0; } -- cgit v0.10.2 From 5c79507b2c50ddab8f51bc692e3c0a39e3da2ad6 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 25 Oct 2011 13:09:43 -0400 Subject: drm/nouveau: Fix bandwidth calculation for DisplayPort Ported from the equivalent fix in drm-intel-next: http://cgit.freedesktop.org/~keithp/linux/commit/?h=drm-intel-next&id=cd9dde44f47501394b9f0715b6a36a92aa74c0d0 Signed-off-by: Adam Jackson Signed-off-by: Ben Skeggs diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index e0d275e..cea6696 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -710,7 +710,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, case OUTPUT_DP: max_clock = nv_encoder->dp.link_nr; max_clock *= nv_encoder->dp.link_bw; - clock = clock * nouveau_connector_bpp(connector) / 8; + clock = clock * nouveau_connector_bpp(connector) / 10; break; default: BUG_ON(1); -- cgit v0.10.2 From c0d18316ae99e1f19738f9cb5e0a2a9dc57dd8cd Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 9 Nov 2011 10:25:26 +0100 Subject: vmwgfx: Close screen object system Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 03daefa..f3ab1fe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1323,7 +1323,10 @@ int vmw_kms_close(struct vmw_private *dev_priv) * drm_encoder_cleanup which takes the lock we deadlock. */ drm_mode_config_cleanup(dev_priv->dev); - vmw_kms_close_legacy_display_system(dev_priv); + if (dev_priv->sou_priv) + vmw_kms_close_screen_object_display(dev_priv); + else + vmw_kms_close_legacy_display_system(dev_priv); return 0; } -- cgit v0.10.2 From f0c8a6524dca1d37ab7b0247aa7681e490af1ee4 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 9 Nov 2011 10:25:27 +0100 Subject: vmwgfx: Initialize clip rect loop correctly in surface dirty Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index f3ab1fe..40c7e61 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -410,8 +410,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, top = clips->y1; bottom = clips->y2; - clips_ptr = clips; - for (i = 1; i < num_clips; i++, clips_ptr += inc) { + /* skip the first clip rect */ + for (i = 1, clips_ptr = clips + inc; + i < num_clips; i++, clips_ptr += inc) { left = min_t(int, left, (int)clips_ptr->x1); right = max_t(int, right, (int)clips_ptr->x2); top = min_t(int, top, (int)clips_ptr->y1); -- cgit v0.10.2 From baa91d640034dd8d0b58a9088f5fefe5cec3c8c4 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 9 Nov 2011 10:25:28 +0100 Subject: vmwgfx: Only allow 64x64 cursors Snooping code expects this to be the case. Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 40c7e61..880e285 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -105,6 +105,10 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, struct vmw_dma_buffer *dmabuf = NULL; int ret; + /* A lot of the code assumes this */ + if (handle && (width != 64 || height != 64)) + return -EINVAL; + if (handle) { ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, &surface); -- cgit v0.10.2 From 471dd2ef3761de01348b19e83128a778df1d45b2 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Thu, 10 Nov 2011 11:55:40 -0800 Subject: drm: Ensure string is null terminated. Fixes Coverity buffer not null terminated defect. Signed-off-by: Vinson Lee Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 9a2e2a1..405c63b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2118,8 +2118,10 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, property->num_values = num_values; INIT_LIST_HEAD(&property->enum_blob_list); - if (name) + if (name) { strncpy(property->name, name, DRM_PROP_NAME_LEN); + property->name[DRM_PROP_NAME_LEN-1] = '\0'; + } list_add_tail(&property->head, &dev->mode_config.property_list); return property; -- cgit v0.10.2 From 7a1619b97e978bb9c05fa4bbe64171068bd5bf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 10 Nov 2011 18:57:26 +0100 Subject: drm/radeon: Make sure CS mutex is held across GPU reset. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was only the case if the GPU reset was triggered from the CS ioctl, otherwise other processes could happily enter the CS ioctl and wreak havoc during the GPU reset. This is a little complicated because the GPU reset can be triggered from the CS ioctl, in which case we're already holding the mutex, or from other call paths, in which case we need to lock the mutex. AFAICT the mutex API doesn't allow recursive locking or finding out the mutex owner, so we need to handle this with helper functions which allow recursive locking from the same process. Signed-off-by: Michel Dänzer Reviewed-by: Jerome Glisse Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b316b30..85ef693 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1142,6 +1142,48 @@ struct r600_vram_scratch { u64 gpu_addr; }; + +/* + * Mutex which allows recursive locking from the same process. + */ +struct radeon_mutex { + struct mutex mutex; + struct task_struct *owner; + int level; +}; + +static inline void radeon_mutex_init(struct radeon_mutex *mutex) +{ + mutex_init(&mutex->mutex); + mutex->owner = NULL; + mutex->level = 0; +} + +static inline void radeon_mutex_lock(struct radeon_mutex *mutex) +{ + if (mutex_trylock(&mutex->mutex)) { + /* The mutex was unlocked before, so it's ours now */ + mutex->owner = current; + } else if (mutex->owner != current) { + /* Another process locked the mutex, take it */ + mutex_lock(&mutex->mutex); + mutex->owner = current; + } + /* Otherwise the mutex was already locked by this process */ + + mutex->level++; +} + +static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) +{ + if (--mutex->level > 0) + return; + + mutex->owner = NULL; + mutex_unlock(&mutex->mutex); +} + + /* * Core structure, functions and helpers. */ @@ -1197,7 +1239,7 @@ struct radeon_device { struct radeon_gem gem; struct radeon_pm pm; uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; - struct mutex cs_mutex; + struct radeon_mutex cs_mutex; struct radeon_wb wb; struct radeon_dummy_page dummy_page; bool gpu_lockup; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index fae00c0..ccaa243 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -222,7 +222,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) struct radeon_cs_chunk *ib_chunk; int r; - mutex_lock(&rdev->cs_mutex); + radeon_mutex_lock(&rdev->cs_mutex); /* initialize parser */ memset(&parser, 0, sizeof(struct radeon_cs_parser)); parser.filp = filp; @@ -233,14 +233,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r) { DRM_ERROR("Failed to initialize parser !\n"); radeon_cs_parser_fini(&parser, r); - mutex_unlock(&rdev->cs_mutex); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } r = radeon_ib_get(rdev, &parser.ib); if (r) { DRM_ERROR("Failed to get ib !\n"); radeon_cs_parser_fini(&parser, r); - mutex_unlock(&rdev->cs_mutex); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } r = radeon_cs_parser_relocs(&parser); @@ -248,7 +248,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r != -ERESTARTSYS) DRM_ERROR("Failed to parse relocation %d!\n", r); radeon_cs_parser_fini(&parser, r); - mutex_unlock(&rdev->cs_mutex); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } /* Copy the packet into the IB, the parser will read from the @@ -260,14 +260,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r || parser.parser_error) { DRM_ERROR("Invalid command stream !\n"); radeon_cs_parser_fini(&parser, r); - mutex_unlock(&rdev->cs_mutex); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } r = radeon_cs_finish_pages(&parser); if (r) { DRM_ERROR("Invalid command stream !\n"); radeon_cs_parser_fini(&parser, r); - mutex_unlock(&rdev->cs_mutex); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } r = radeon_ib_schedule(rdev, parser.ib); @@ -275,7 +275,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) DRM_ERROR("Failed to schedule IB !\n"); } radeon_cs_parser_fini(&parser, r); - mutex_unlock(&rdev->cs_mutex); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c33bc91..c4d00a1 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -716,7 +716,7 @@ int radeon_device_init(struct radeon_device *rdev, /* mutex initialization are all done here so we * can recall function without having locking issues */ - mutex_init(&rdev->cs_mutex); + radeon_mutex_init(&rdev->cs_mutex); mutex_init(&rdev->ib_pool.mutex); mutex_init(&rdev->cp.mutex); mutex_init(&rdev->dc_hw_i2c_mutex); @@ -955,6 +955,9 @@ int radeon_gpu_reset(struct radeon_device *rdev) int r; int resched; + /* Prevent CS ioctl from interfering */ + radeon_mutex_lock(&rdev->cs_mutex); + radeon_save_bios_scratch_regs(rdev); /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); @@ -967,10 +970,15 @@ int radeon_gpu_reset(struct radeon_device *rdev) radeon_restore_bios_scratch_regs(rdev); drm_helper_resume_force_mode(rdev->ddev); ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); - return 0; } - /* bad news, how to tell it to userspace ? */ - dev_info(rdev->dev, "GPU reset failed\n"); + + radeon_mutex_unlock(&rdev->cs_mutex); + + if (r) { + /* bad news, how to tell it to userspace ? */ + dev_info(rdev->dev, "GPU reset failed\n"); + } + return r; } -- cgit v0.10.2 From 3b9832f662d195755e7308f92368d44458268457 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Nov 2011 08:59:39 -0500 Subject: drm/radeon/kms: fix use of vram scratch page on evergreen/ni This hunk seems to have gotten lost when I rebased the patch. Reported-by: Sylvain Bertrand Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e4c384b..2e30160 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1219,7 +1219,7 @@ void evergreen_mc_program(struct radeon_device *rdev) WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12); } - WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); if (rdev->flags & RADEON_IS_IGP) { tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24; -- cgit v0.10.2 From b3e067c0b276197b59046d7095b01b99f98b2821 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 9 Nov 2011 22:20:35 +0100 Subject: drm: serialize access to list of debugfs files Nouveau, when configured with debugfs, creates debugfs files for every channel, so structure holding list of files needs to be protected from simultaneous changes by multiple threads. Without this patch it's possible to hit kernel oops in drm_debugfs_remove_files just by running a couple of xterms with looped glxinfo. Signed-off-by: Marcin Slusarz Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index d067c12..1c7a1c0 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -118,7 +118,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count, tmp->minor = minor; tmp->dent = ent; tmp->info_ent = &files[i]; - list_add(&(tmp->list), &(minor->debugfs_nodes.list)); + + mutex_lock(&minor->debugfs_lock); + list_add(&tmp->list, &minor->debugfs_list); + mutex_unlock(&minor->debugfs_lock); } return 0; @@ -146,7 +149,8 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, char name[64]; int ret; - INIT_LIST_HEAD(&minor->debugfs_nodes.list); + INIT_LIST_HEAD(&minor->debugfs_list); + mutex_init(&minor->debugfs_lock); sprintf(name, "%d", minor_id); minor->debugfs_root = debugfs_create_dir(name, root); if (!minor->debugfs_root) { @@ -192,8 +196,9 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count, struct drm_info_node *tmp; int i; + mutex_lock(&minor->debugfs_lock); for (i = 0; i < count; i++) { - list_for_each_safe(pos, q, &minor->debugfs_nodes.list) { + list_for_each_safe(pos, q, &minor->debugfs_list) { tmp = list_entry(pos, struct drm_info_node, list); if (tmp->info_ent == &files[i]) { debugfs_remove(tmp->dent); @@ -202,6 +207,7 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count, } } } + mutex_unlock(&minor->debugfs_lock); return 0; } EXPORT_SYMBOL(drm_debugfs_remove_files); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d14b44e..4f40f1c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1506,7 +1506,10 @@ drm_add_fake_info_node(struct drm_minor *minor, node->minor = minor; node->dent = ent; node->info_ent = (void *) key; - list_add(&node->list, &minor->debugfs_nodes.list); + + mutex_lock(&minor->debugfs_lock); + list_add(&node->list, &minor->debugfs_list); + mutex_unlock(&minor->debugfs_lock); return 0; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index cf39949..1f9e951 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -990,7 +990,9 @@ struct drm_minor { struct proc_dir_entry *proc_root; /**< proc directory entry */ struct drm_info_node proc_nodes; struct dentry *debugfs_root; - struct drm_info_node debugfs_nodes; + + struct list_head debugfs_list; + struct mutex debugfs_lock; /* Protects debugfs_list. */ struct drm_master *master; /* currently active master for this node */ struct list_head master_list; -- cgit v0.10.2 From 87cb73dafef765c6e20452ebf2581ba113c0360a Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Wed, 9 Nov 2011 01:16:50 +0100 Subject: drm: drop select of SLOW_WORK slow-work got killed in commit 181a51f6e0. This means that since v2.6.36 there is no Kconfig symbol SLOW_WORK. Apparently selecting that symbol is a nop. Drop that select. Signed-off-by: Paul Bolle Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 785127c..866095c 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -9,7 +9,6 @@ menuconfig DRM depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU select I2C select I2C_ALGOBIT - select SLOW_WORK help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select -- cgit v0.10.2 From 091264f0bc12419560ac64fcef4567809d611658 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 8 Nov 2011 10:09:58 -0500 Subject: drm/radeon/kms: make an aux failure debug only Can happen when there is no DP panel attached, confusing users. Make it debug only. Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index a0de485..6fb335a 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -283,7 +283,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, } } - DRM_ERROR("aux i2c too many retries, giving up\n"); + DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); return -EREMOTEIO; } -- cgit v0.10.2 From c5006cfe2f5fc3cc03ebe2342aaca83d051d99e0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 7 Nov 2011 10:39:57 -0800 Subject: drm: try to restore previous CRTC config if mode set fails We restore the CRTC, encoder, and connector configurations, but if the mode set failed, the attached display may have been turned off, so we need to try set_config again to restore things to the way they were. Signed-off-by: Jesse Barnes Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 2957636..3969f75 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -484,6 +484,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) struct drm_connector *save_connectors, *connector; int count = 0, ro, fail = 0; struct drm_crtc_helper_funcs *crtc_funcs; + struct drm_mode_set save_set; int ret = 0; int i; @@ -556,6 +557,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) save_connectors[count++] = *connector; } + save_set.crtc = set->crtc; + save_set.mode = &set->crtc->mode; + save_set.x = set->crtc->x; + save_set.y = set->crtc->y; + save_set.fb = set->crtc->fb; + /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ if (set->crtc->fb != set->fb) { @@ -721,6 +728,12 @@ fail: *connector = save_connectors[count++]; } + /* Try to restore the config */ + if (mode_changed && + !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x, + save_set.y, save_set.fb)) + DRM_ERROR("failed to restore config after modeset failure\n"); + kfree(save_connectors); kfree(save_encoders); kfree(save_crtcs); -- cgit v0.10.2 From 398a6d4a02257d6065c2afe1413f5b6ae3a76f09 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Wed, 2 Nov 2011 11:33:16 +0900 Subject: MAINTAINERS: exynos: Add EXYNOS DRM maintainer entry As Exynos DRM is merged at mainline. Also update the maintainer entry. Signed-off-by: Kyungmin Park Signed-off-by: Dave Airlie diff --git a/MAINTAINERS b/MAINTAINERS index 4808256..c1b1f3e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2342,6 +2342,13 @@ S: Supported F: drivers/gpu/drm/i915 F: include/drm/i915* +DRM DRIVERS FOR EXYNOS +M: Inki Dae +L: dri-devel@lists.freedesktop.org +S: Supported +F: drivers/gpu/drm/exynos +F: include/drm/exynos* + DSCC4 DRIVER M: Francois Romieu L: netdev@vger.kernel.org -- cgit v0.10.2 From 8f4ff2b06afcd6f151868474a432c603057eaf56 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Mon, 31 Oct 2011 17:46:18 -0400 Subject: drm: do not sleep on vblank while holding a mutex drm_wait_vblank must be DRM_UNLOCKED because otherwise it will grab the drm_global_mutex and then go to sleep until the vblank event it is waiting for. That can wreck havoc in the windowing system because if one process issues this ioctl, it will block all other processes for the duration of all vblanks between the current and the one it is waiting for. In some cases it can block the entire windowing system. v2: incorporate comments received from Daniel Vetter and Michel Daenzer. v3/v4: after a lengty discussion with Daniel Vetter, it was concluded that the only thing not yet protected with locks and atomic ops is the write to dev->last_vblank_wait. It's only used in a debug file in proc, and the current code already employs no correct locking: the proc file only takes dev->struct_mutex, whereas drm_wait_vblank implicitly took the drm_global_mutex. Given all this, it's not worth bothering to try to fix the locks at this time. Signed-off-by: Ilija Hadzic Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index fc81af9..40c187c 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -125,7 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0), + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0), -- cgit v0.10.2 From bfba16582600ab2c75dc39250a2b8f3b2a42da11 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Oct 2011 10:21:28 +0300 Subject: drm/radeon/benchmark: signedness bug in radeon_benchmark_move() radeon_benchmark_do_move() returns an int so "time" should be int too. Making it unsigned breaks the error handling. Signed-off-by: Dan Carpenter Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 5cafc90..17e1a9b 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -98,7 +98,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, struct radeon_bo *sobj = NULL; uint64_t saddr, daddr; int r, n; - unsigned int time; + int time; n = RADEON_BENCHMARK_ITERATIONS; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj); -- cgit v0.10.2 From a6778e9e7fb57603f15344ceb30098a3f6b7caf4 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Mon, 31 Oct 2011 13:11:57 -0400 Subject: drm: add some comments to drm_wait_vblank and drm_queue_vblank_event during the review of the fix for locks problems in drm_wait_vblank, a couple of false concerns were raised about how the drm_vblank_get and drm_vblank_put are used in this function; it turned out that the code is correct and that it cannot be simplified add a few comments to explain non-obvious flows in the code, to prevent "false alarms" in the future v2: incorporate comments received from Daniel Vetter Signed-off-by: Ilija Hadzic Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index cb3794a..aa3ac01 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1125,6 +1125,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, trace_drm_vblank_event_delivered(current->pid, pipe, vblwait->request.sequence); } else { + /* drm_handle_vblank_events will call drm_vblank_put */ list_add_tail(&e->base.link, &dev->vblank_event_list); vblwait->reply.sequence = vblwait->request.sequence; } @@ -1205,8 +1206,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data, goto done; } - if (flags & _DRM_VBLANK_EVENT) + if (flags & _DRM_VBLANK_EVENT) { + /* must hold on to the vblank ref until the event fires + * drm_vblank_put will be called asynchronously + */ return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); + } if ((flags & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1<<23)) { -- cgit v0.10.2 From 44a1dabf4cfb787459bfbff305a2a1cda628766d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 31 Oct 2011 12:51:30 -0700 Subject: drm: fix kconfig unmet dependency warning Fix kconfig unmet dependency warning. BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_LCD_SUPPORT, so select the latter along with the former. warning: (DRM_RADEON_KMS && DRM_I915 && STUB_POULSBO && FB_BACKLIGHT && PANEL_SHARP_LS037V7DW01 && PANEL_ACX565AKM && USB_APPLEDISPLAY && FB_OLPC_DCON && ASUS_LAPTOP && SONY_LAPTOP && THINKPAD_ACPI && EEEPC_LAPTOP && ACPI_ASUS && ACPI_CMPC && SAMSUNG_Q10) selects BACKLIGHT_CLASS_DEVICE which has unmet direct dependencies (HAS_IOMEM && BACKLIGHT_LCD_SUPPORT) Signed-off-by: Randy Dunlap Cc: David Airlie Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 866095c..1368826 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -95,6 +95,7 @@ config DRM_I915 select FB_CFB_IMAGEBLIT # i915 depends on ACPI_VIDEO when ACPI is enabled # but for select to work, need to select ACPI_VIDEO's dependencies, ick + select BACKLIGHT_LCD_SUPPORT if ACPI select BACKLIGHT_CLASS_DEVICE if ACPI select VIDEO_OUTPUT_CONTROL if ACPI select INPUT if ACPI -- cgit v0.10.2 From 6c3d904b48e44bd9c3121c24efb87c9d39d7736c Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Fri, 4 Nov 2011 21:09:50 +0900 Subject: drm/exynos: added padding to be 64-bit align. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park Signed-off-by: Dave Airlie diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 874c4d2..1d161cb 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -36,11 +36,13 @@ * - this size value would be page-aligned internally. * @flags: user request for setting memory type or cache attributes. * @handle: returned handle for the object. + * @pad: just padding to be 64-bit aligned. */ struct drm_exynos_gem_create { unsigned int size; unsigned int flags; unsigned int handle; + unsigned int pad; }; /** -- cgit v0.10.2 From 10b391b946c459a39b631aaf81880f94dcfbff46 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 4 Nov 2011 10:09:40 -0400 Subject: drm/radeon/kms: remove extraneous calls to radeon_pm_compute_clocks() It's already called via the DPMS functions. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 87921c8..87631fe 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1522,12 +1522,6 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - - /* adjust pm to upcoming mode change */ - radeon_pm_compute_clocks(rdev); - if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) return false; return true; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 41a5d48..daadf21 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -991,12 +991,6 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - - /* adjust pm to upcoming mode change */ - radeon_pm_compute_clocks(rdev); - if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) return false; return true; -- cgit v0.10.2 From a4c9e2eed17457b30e17235158657801ec686a14 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 4 Nov 2011 10:09:41 -0400 Subject: drm/radeon/kms/pm: add a proper pm profile init function for fusion The new power tables need to be handled differently when setting up the profiles. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 2e30160..1d603a3 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -157,6 +157,57 @@ int sumo_get_temp(struct radeon_device *rdev) return actual_temp * 1000; } +void sumo_pm_init_profile(struct radeon_device *rdev) +{ + int idx; + + /* default */ + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; + + /* low,mid sh/mh */ + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; + + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; + + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; + + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; + + /* high sh/mh */ + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = + rdev->pm.power_state[idx].num_clock_modes - 1; + + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = + rdev->pm.power_state[idx].num_clock_modes - 1; +} + void evergreen_pm_misc(struct radeon_device *rdev) { int req_ps_idx = rdev->pm.requested_power_state_index; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 19afc43..dc162dd 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -288,24 +288,6 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev) pcie_lanes); } -static int r600_pm_get_type_index(struct radeon_device *rdev, - enum radeon_pm_state_type ps_type, - int instance) -{ - int i; - int found_instance = -1; - - for (i = 0; i < rdev->pm.num_power_states; i++) { - if (rdev->pm.power_state[i].type == ps_type) { - found_instance++; - if (found_instance == instance) - return i; - } - } - /* return default if no match */ - return rdev->pm.default_power_state_index; -} - void rs780_pm_init_profile(struct radeon_device *rdev) { if (rdev->pm.num_power_states == 2) { @@ -504,79 +486,79 @@ void r600_pm_init_profile(struct radeon_device *rdev) /* low sh */ if (rdev->flags & RADEON_IS_MOBILITY) { rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; } else { rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; } /* mid sh */ if (rdev->flags & RADEON_IS_MOBILITY) { rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; } else { rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; } /* high sh */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; /* low mh */ if (rdev->flags & RADEON_IS_MOBILITY) { rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; } else { rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; } /* mid mh */ if (rdev->flags & RADEON_IS_MOBILITY) { rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; } else { rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; } /* high mh */ rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = - r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 85ef693..41f7cd2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -855,6 +855,9 @@ struct radeon_pm { struct device *int_hwmon_dev; }; +int radeon_pm_get_type_index(struct radeon_device *rdev, + enum radeon_pm_state_type ps_type, + int instance); /* * Benchmarking diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e294456..a2e1eae 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -834,7 +834,7 @@ static struct radeon_asic sumo_asic = { .pm_misc = &evergreen_pm_misc, .pm_prepare = &evergreen_pm_prepare, .pm_finish = &evergreen_pm_finish, - .pm_init_profile = &rs780_pm_init_profile, + .pm_init_profile = &sumo_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 85f14f0..5991484 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -413,6 +413,7 @@ extern int evergreen_cs_parse(struct radeon_cs_parser *p); extern void evergreen_pm_misc(struct radeon_device *rdev); extern void evergreen_pm_prepare(struct radeon_device *rdev); extern void evergreen_pm_finish(struct radeon_device *rdev); +extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 6fabe89..78a665b 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -53,6 +53,24 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev); #define ACPI_AC_CLASS "ac_adapter" +int radeon_pm_get_type_index(struct radeon_device *rdev, + enum radeon_pm_state_type ps_type, + int instance) +{ + int i; + int found_instance = -1; + + for (i = 0; i < rdev->pm.num_power_states; i++) { + if (rdev->pm.power_state[i].type == ps_type) { + found_instance++; + if (found_instance == instance) + return i; + } + } + /* return default if no match */ + return rdev->pm.default_power_state_index; +} + #ifdef CONFIG_ACPI static int radeon_acpi_event(struct notifier_block *nb, unsigned long val, -- cgit v0.10.2 From bbe26ffe9ffd231de7cf88c4361f1939858e8594 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 4 Nov 2011 10:09:42 -0400 Subject: drm/radeon/kms: optimize r600_pm_profile_init Avoid a lot of extra loops through the pm state array. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index dc162dd..9cdda0b 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -403,6 +403,8 @@ void rs780_pm_init_profile(struct radeon_device *rdev) void r600_pm_init_profile(struct radeon_device *rdev) { + int idx; + if (rdev->family == CHIP_R600) { /* XXX */ /* default */ @@ -484,81 +486,43 @@ void r600_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; /* low sh */ - if (rdev->flags & RADEON_IS_MOBILITY) { - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; - } else { - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; - } + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; /* mid sh */ - if (rdev->flags & RADEON_IS_MOBILITY) { - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; - } else { - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; - } + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; /* high sh */ - rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); - rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; /* low mh */ - if (rdev->flags & RADEON_IS_MOBILITY) { - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; - } else { - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; - } + if (rdev->flags & RADEON_IS_MOBILITY) + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); + else + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; /* mid mh */ - if (rdev->flags & RADEON_IS_MOBILITY) { - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; - } else { - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; - rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; - } + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; + rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; /* high mh */ - rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); - rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = - radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; + rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; } -- cgit v0.10.2 From 8f3f1c9a22a6420e28c2d3eff59b832893bc8efc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 4 Nov 2011 10:09:43 -0400 Subject: drm/radeon/kms/pm: switch to dynamically allocating clock mode array On newer chips the number of clock modes per power state varies. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 41f7cd2..fc5a1d6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -784,8 +784,7 @@ struct radeon_pm_clock_info { struct radeon_power_state { enum radeon_pm_state_type type; - /* XXX: use a define for num clock modes */ - struct radeon_pm_clock_info clock_info[8]; + struct radeon_pm_clock_info *clock_info; /* number of valid clock modes in this power state */ int num_clock_modes; struct radeon_pm_clock_info *default_clock_mode; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 08d0b94..d2d1792 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1999,6 +1999,10 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; switch (frev) { case 1: + rdev->pm.power_state[state_index].clock_info = + kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + if (!rdev->pm.power_state[state_index].clock_info) + return state_index; rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].mclk = le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); @@ -2035,6 +2039,10 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) state_index++; break; case 2: + rdev->pm.power_state[state_index].clock_info = + kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + if (!rdev->pm.power_state[state_index].clock_info) + return state_index; rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].mclk = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); @@ -2072,6 +2080,10 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) state_index++; break; case 3: + rdev->pm.power_state[state_index].clock_info = + kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + if (!rdev->pm.power_state[state_index].clock_info) + return state_index; rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].mclk = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); @@ -2257,7 +2269,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde rdev->pm.default_power_state_index = state_index; rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; - if (ASIC_IS_DCE5(rdev)) { + if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) { /* NI chips post without MC ucode, so default clocks are strobe mode only */ rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; @@ -2377,17 +2389,31 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + (power_state->v1.ucNonClockStateIndex * power_info->pplib.ucNonClockSize)); - for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { - clock_info = (union pplib_clock_info *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + - (power_state->v1.ucClockStateIndices[j] * - power_info->pplib.ucClockInfoSize)); - valid = radeon_atombios_parse_pplib_clock_info(rdev, - state_index, mode_index, - clock_info); - if (valid) - mode_index++; + rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * + ((power_info->pplib.ucStateEntrySize - 1) ? + (power_info->pplib.ucStateEntrySize - 1) : 1), + GFP_KERNEL); + if (!rdev->pm.power_state[i].clock_info) + return state_index; + if (power_info->pplib.ucStateEntrySize - 1) { + for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { + clock_info = (union pplib_clock_info *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + + (power_state->v1.ucClockStateIndices[j] * + power_info->pplib.ucClockInfoSize)); + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); + if (valid) + mode_index++; + } + } else { + rdev->pm.power_state[state_index].clock_info[0].mclk = + rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = + rdev->clock.default_sclk; + mode_index++; } rdev->pm.power_state[state_index].num_clock_modes = mode_index; if (mode_index) { @@ -2456,18 +2482,32 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) &non_clock_info_array->nonClockInfo[non_clock_array_index]; - for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { - clock_array_index = power_state->v2.clockInfoIndex[j]; - /* XXX this might be an inagua bug... */ - if (clock_array_index >= clock_info_array->ucNumEntries) - continue; - clock_info = (union pplib_clock_info *) - &clock_info_array->clockInfo[clock_array_index]; - valid = radeon_atombios_parse_pplib_clock_info(rdev, - state_index, mode_index, - clock_info); - if (valid) - mode_index++; + rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * + (power_state->v2.ucNumDPMLevels ? + power_state->v2.ucNumDPMLevels : 1), + GFP_KERNEL); + if (!rdev->pm.power_state[i].clock_info) + return state_index; + if (power_state->v2.ucNumDPMLevels) { + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = power_state->v2.clockInfoIndex[j]; + /* XXX this might be an inagua bug... */ + if (clock_array_index >= clock_info_array->ucNumEntries) + continue; + clock_info = (union pplib_clock_info *) + &clock_info_array->clockInfo[clock_array_index]; + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); + if (valid) + mode_index++; + } + } else { + rdev->pm.power_state[state_index].clock_info[0].mclk = + rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = + rdev->clock.default_sclk; + mode_index++; } rdev->pm.power_state[state_index].num_clock_modes = mode_index; if (mode_index) { @@ -2524,19 +2564,23 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) } else { rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); if (rdev->pm.power_state) { - /* add the default mode */ - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.power_state[state_index].num_clock_modes = 1; - rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; - rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; - rdev->pm.power_state[state_index].default_clock_mode = - &rdev->pm.power_state[state_index].clock_info[0]; - rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; - rdev->pm.power_state[state_index].pcie_lanes = 16; - rdev->pm.default_power_state_index = state_index; - rdev->pm.power_state[state_index].flags = 0; - state_index++; + rdev->pm.power_state[0].clock_info = + kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); + if (rdev->pm.power_state[0].clock_info) { + /* add the default mode */ + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[0]; + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + rdev->pm.power_state[state_index].pcie_lanes = 16; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].flags = 0; + state_index++; + } } } -- cgit v0.10.2