[PATCH v2 3/4] drm/exynos: added userptr feature.

2012-04-25 Thread InKi Dae
Hi Dave,

2012/4/25, Dave Airlie :
> On Tue, Apr 24, 2012 at 6:17 AM, Inki Dae  wrote:
>> this feature could be used to use memory region allocated by malloc() in
>> user
>> mode and mmaped memory region allocated by other memory allocators.
>> userptr
>> interface can identify memory type through vm_flags value and would get
>> pages or page frame numbers to user space appropriately.
>
> Is there anything to stop the unpriviledged userspace driver locking
> all the RAM in the machine inside userptr?
>
> seems like a very bad plan, I know TTM has code to address this sort
> of things with limits.
>

Thank you for your pointing and I will look into it. could anyone tell
me that I can refer to which part of TTM? if doing so, it would be
helpful to me.

Thanks,
Inki Dae.


> Dave.
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>


[RFC v2 3/5] i2c: Add of_i2c_get_adapter() function

2012-04-25 Thread Thierry Reding
* Stephen Warren wrote:
> On 04/25/2012 03:45 AM, Thierry Reding wrote:
> > This function resolves an OF device node to an I2C adapter registered
> > with the I2C core.
> 
> I think this is doing the same thing as a patch I posted recently:
> http://www.spinics.net/lists/linux-i2c/msg07808.html

I wasn't aware of that patch.

> What's the advantage of one way over the other?

Both are fine I think. Your version is shorter but mine may be a little
faster since it doesn't iterate over all devices on the bus. Since the
lookup doesn't happen very frequently this isn't much of an issue.

Thierry
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120425/ae82b75a/attachment.pgp>


[PATCH 24/24] drm/radeon: add faulty command buffer dump facilities

2012-04-25 Thread Jerome Glisse
On Wed, Apr 25, 2012 at 5:53 PM, Luca Tettamanti  wrote:
> Hi Jerome,
>
> On Wed, Apr 25, 2012 at 9:03 PM, ? wrote:
>> From: Jerome Glisse 
>>
>> This add a command buffer dumping facilities, that will
>> dump command buffer and all associated bo that most likely
>> triggered a lockup.
> [cut]
>
> I spotted this:
>
>> +void radeon_fence_blob_faulty_ib(struct radeon_device *rdev, int ring)
>> +{
>> + ? ? ? struct radeon_fence *fence;
>> + ? ? ? struct list_head *i;
>> + ? ? ? unsigned long irq_flags;
>> + ? ? ? uint32_t seq;
>> +
>> + ? ? ? write_lock_irqsave(>fence_lock, irq_flags);
>> + ? ? ? seq = radeon_fence_read(rdev, ring);
>> + ? ? ? list_for_each(i, >fence_drv[ring].emitted) {
>> + ? ? ? ? ? ? ? fence = list_entry(i, struct radeon_fence, list);
>> + ? ? ? ? ? ? ? if (fence->seq != seq && fence->ib) {
>> + ? ? ? ? ? ? ? ? ? ? ? radeon_lockup_build_blob(rdev, fence->ib);
>
> radeon_lockup_build_blob() will take a mutex and call vmalloc() inside
> an atomic context.
>
> Luca

Yeah, you right, i only compile tested, i haven't checked if it works
ok on lockup.
Thought solution for this is easy.

Cheers,
Jerome


[PATCH 26/26] drm/radeon: add the ib content and relocs to the ring debugfs file

2012-04-25 Thread Christian König
On 25.04.2012 16:36, Jerome Glisse wrote:
> NAK i would rather have a full dump as i described. I can do a patch
> for that if you want.
>
I don't stick with those files neither, just wanted to restore the same 
functionality as we had before.

Just finished a conference call with Alex and the rest of the team, and 
Alex suggested that we stick with the AMD internal binary format for 
crash dumps. With that we could reuse the AMD internal tools, but the 
obvious downside is that those aren't available to you (for example).

We should sync with Alex how that format looks like, and if we 
could/should/whatever move the driver to wards it.

Cheers,
Christian.

PS: I'm not at home this evening, so please answer on my AMD mail 
address also.


linux-next: Tree for Apr 17 (pci-sysfs.c and vga_switcheroo.c)

2012-04-25 Thread Matthew Garrett
On Wed, Apr 25, 2012 at 10:37:26AM -0600, Bjorn Helgaas wrote:
> I assume this is related to 77b267c7549e3629ea55cf780aa3d474da7bc2d5
> ("vgaarb: Add support for setting the default video device") and that
> Matthew will take care of whatever needs to be done (if it's not fixed
> already).

Dave has patches.

-- 
Matthew Garrett | mjg59 at srcf.ucam.org


[PATCH 06/26] drm/radeon: fix a critical bug in the SA code

2012-04-25 Thread Christian König
On 25.04.2012 16:34, Jerome Glisse wrote:
> On Wed, Apr 25, 2012 at 9:40 AM, Alex Deucher  
> wrote:
>> On Wed, Apr 25, 2012 at 9:19 AM, Michel D?nzer  wrote:
>>> On Mit, 2012-04-25 at 14:46 +0200, Christian K?nig wrote:
 Aligning offset can make it bigger than tmp->offset
 leading to an overrun bug in the following subtraction.

 Signed-off-by: Christian K?nig
>>> Please add
>>>
>>> Cc: stable at vger.kernel.org
>>>
>>> to the commit log (but don't send the patch to that address during
>>> review). That way, once Linus merges the fix, it'll be picked up for the
>>> 3.3.y stable tree.
>>>
>>> With that addition,
>>>
>>> Reviewed-by: Michel D?nzer
>> Reviewed-by: Alex Deucher
>>
>> This should probably go in now via drm-fixes (with stable cced).  Might fix:
>> https://bugs.freedesktop.org/show_bug.cgi?id=45018
>>
>> Alex
> I don't think this patch fix anything, as up until now they all used
> same alignment.
Correct, as I allready mentioned in the other mail: The VM code and the 
IB code do use different alignments, but they also use different 
instances of SA manager. So that problem won't hurt us in the current 
mainline.

Christian.


[Bug 45018] [bisected] rendering regression since added support for virtual address space on cayman v11

2012-04-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=45018

--- Comment #50 from Michel D?nzer  2012-04-25 09:16:19 
PDT ---
Comment on attachment 60582
  --> https://bugs.freedesktop.org/attachment.cgi?id=60582
possible fix

Review of attachment 60582:
 --> 
(https://bugs.freedesktop.org/page.cgi?id=splinter.html=45018=60582)
-

::: src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ +221,4 @@
>  pipe_mutex_unlock(mgr->bo_va_mutex);
>  return offset;
>  }
> +if (waste < hole->size && (hole->size - waste) >= size) {

AFAICT the 'if (offset >= (hole->offset + hole->size))' test further up is a
roundabout way of saying 'if (waste >= hole->size)', so I'm afraid this won't
have any effect.

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[Bug 45018] [bisected] rendering regression since added support for virtual address space on cayman v11

2012-04-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=45018

--- Comment #49 from Alex Deucher  2012-04-25 08:59:57 PDT 
---
Created attachment 60582
  --> https://bugs.freedesktop.org/attachment.cgi?id=60582
possible fix

Does this patch help?

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH 06/26] drm/radeon: fix a critical bug in the SA code

2012-04-25 Thread Christian König
On 25.04.2012 15:19, Michel D?nzer wrote:
> On Mit, 2012-04-25 at 14:46 +0200, Christian K?nig wrote:
>> Aligning offset can make it bigger than tmp->offset
>> leading to an overrun bug in the following subtraction.
>>
>> Signed-off-by: Christian K?nig
> Please add
>
> Cc: stable at vger.kernel.org
>
> to the commit log (but don't send the patch to that address during
> review). That way, once Linus merges the fix, it'll be picked up for the
> 3.3.y stable tree.
>
> With that addition,
>
> Reviewed-by: Michel D?nzer
>
>
I don't think that's necessary, cause I checked the vm code again and 
Jerome has given it a separate instance of the SA.

So the bug can't happen in the stable kernel, it just happens when you 
add another user (the semaphore code) to the SA.

Over all it's not so critical as I thought it is in the first place and 
we need to keep digging for VM problems in other places.

Thanks for the explanation anyway,
Christian.


[Bug 45018] [bisected] rendering regression since added support for virtual address space on cayman v11

2012-04-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=45018

--- Comment #48 from Alexandre Demers  
2012-04-25 08:21:12 PDT ---
(In reply to comment #47)
> (In reply to comment #46)
> > Does this kernel patch help?
> > http://lists.freedesktop.org/archives/dri-devel/2012-April/022037.html
> 
> I was wondering about that as well, but I'm afraid it can't, as Christian
> pointed out.
> 
> (In reply to comment #44)
> > [ 1454.142346] radeon :01:00.0: offset 0x10 is in reserved area
> > 0x80
> 
> The offset 0x10 comes from userspace, so it could still be a pure 
> userspace
> problem. Maybe it runs out of VM space and into the reserved area or something
> like that.

I'll try it just in case ASAP. However, this means it won't probably be until
Friday or the weekend.

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH 06/26] drm/radeon: fix a critical bug in the SA code

2012-04-25 Thread Michel Dänzer
On Mit, 2012-04-25 at 14:46 +0200, Christian K?nig wrote: 
> Aligning offset can make it bigger than tmp->offset
> leading to an overrun bug in the following subtraction.
> 
> Signed-off-by: Christian K?nig 

Please add

Cc: stable at vger.kernel.org

to the commit log (but don't send the patch to that address during
review). That way, once Linus merges the fix, it'll be picked up for the
3.3.y stable tree.

With that addition,

Reviewed-by: Michel D?nzer 


-- 
Earthling Michel D?nzer   |   http://www.amd.com
Libre software enthusiast |  Debian, X and DRI developer


[PATCH 1/3] acpi_video: fix leaking PCI references

2012-04-25 Thread Matthew Garrett
Acked-by: Matthew Garrett 

for the set.

-- 
Matthew Garrett | mjg59 at srcf.ucam.org


[REGRESSION]: hibernate/sleep regression w/ bisection

2012-04-25 Thread Andrew Watts
Hello all.

I wanted to follow-up on a very peculiar yet highly reproducible bug
involving suspend/resume, radeon, and a seemingly unrelated patch to
input serio.

The last comment in the thread was from Jerome Glisse saying it was a tough
bug to fix. Has anyone had any good ideas on how to fix it since?

Thanks!

~ Andy


On Fri, Nov 04, 2011 at 09:14:31AM -0700, Tejun Heo wrote:
> (cc'ing David Airlie and dri-devel)
> 
> Hello, the original thread can be read from
> 
>   http://thread.gmane.org/gmane.linux.kernel/1209587
> 
> Full sysrq-t output at
> 
>   http://article.gmane.org/gmane.linux.kernel/1211256
> 
> So, the problem is that after a seemingly unreated update to input
> serio driver (convert to use workqueue), X seems to lock up
> sporadically across suspend/resume cycles.
> 
> I went through the full sysrq-t output but couldn't spot anything
> suspicious w/ anything else.  No worker is stuck and nobody is waiting
> for flush to finish.
> 
> Stack trace for X follows.
> 
> > X   S f499b944  5800  1652   1651 0x00400080
> >  f499b9a8 3086  f499b944 c100d4a4   f499b958
> >   f499b9a8 f5173140 d7857c56 0057 f5173140 d8b69880 0057
> >  0001  f499b9b4 c104dd89 000f4240   f499ba68
> > Call Trace:
> >  [] ttm_bo_wait_unreserved+0x5f/0x106
> >  [] ttm_bo_reserve_locked+0xb7/0xe1
> >  [] ttm_bo_reserve+0x26/0x95
> >  [] radeon_crtc_do_set_base+0xbd/0x6d2
> >  [] radeon_crtc_set_base+0x1b/0x1d
> >  [] radeon_crtc_mode_set+0x24/0xdd7
> >  [] drm_crtc_helper_set_mode+0x32c/0x48b
> >  [] drm_helper_resume_force_mode+0x79/0x23e
> >  [] radeon_gpu_reset+0x84/0x98
> >  [] radeon_fence_wait+0x2d1/0x311
> >  [] radeon_sync_obj_wait+0xc/0xe
> >  [] ttm_bo_wait+0xa1/0x108
> >  [] radeon_gem_wait_idle_ioctl+0x76/0xc4
> >  [] drm_ioctl+0x1c2/0x42c
> >  [] do_vfs_ioctl+0x79/0x54b
> >  [] sys_ioctl+0x6b/0x70
> >  [] sysenter_do_call+0x12/0x22
> 
> Do you guys have any ideas what's going on?  It seems to be waiting
> for bo->reserved to go zero.  Is it possible that someone there is
> forgetting to properly kick a work item after resume causing the wait
> to stall?
> 
> Andrew, can you please kill the X server after the hang and see
> whether that brings the system back?  I think sshd should still work
> and if not you can write a script to kill the X server after 30secs
> after resume (and kill that script if resume succeeds).
> 
> Thank you.
> 
> -- 
> tejun


[PATCH 24/24] drm/radeon: add faulty command buffer dump facilities

2012-04-25 Thread j.gli...@gmail.com
From: Jerome Glisse 

This add a command buffer dumping facilities, that will
dump command buffer and all associated bo that most likely
triggered a lockup.

Idea is that we go through unsignaled fence and we dump the
ib of the oldest unsignaled fence. Dumping is a 2 step process
on lockup detection we try to allocate a big object that will
old all the the current state (ib pm4 packet, bo content,
relocation table). Upon reading radeon_lockup_blob debugfs
file user will get this big blob and kernel will free memory.

Kernel side try to handle as gracefully as possible failure
such as mapping bo by not dumping such bo. Userspace tools
those need to have enough logic to handle such cases.

Signed-off-by: Jerome Glisse 
---
 drivers/gpu/drm/radeon/radeon.h|   14 -
 drivers/gpu/drm/radeon/radeon_cs.c |   20 --
 drivers/gpu/drm/radeon/radeon_device.c |3 +
 drivers/gpu/drm/radeon/radeon_fence.c  |   19 +
 drivers/gpu/drm/radeon/radeon_gart.c   |   10 ++-
 drivers/gpu/drm/radeon/radeon_ring.c   |  118 
 6 files changed, 173 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 7b2125b..c9f51be 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -241,6 +241,7 @@ struct radeon_fence {
 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
 int radeon_fence_driver_init(struct radeon_device *rdev);
 void radeon_fence_driver_fini(struct radeon_device *rdev);
+void radeon_fence_blob_faulty_ib(struct radeon_device *rdev, int ring);
 int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence 
**fence, int ring);
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence);
 void radeon_fence_process(struct radeon_device *rdev, int ring);
@@ -569,6 +570,10 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device 
*rdev, int crtc);
  */
 struct radeon_cs_reloc;

+#define RADEON_IB_TYPE_NONE0
+#define RADEON_IB_TYPE_CS  1
+#define RADEON_IB_TYPE_CS_VM   2
+
 struct radeon_ib {
struct radeon_sa_bo sa_bo;
uint32_tlength_dw;
@@ -579,6 +584,7 @@ struct radeon_ib {
boolis_const_ib;
unsignednrelocs;
struct radeon_cs_reloc  *relocs;
+   unsignedtype;
 };

 struct radeon_ring {
@@ -745,6 +751,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct 
radeon_ring *cp, unsigne
 unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg,
 u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop);
 void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp);
+void radeon_lockup_build_blob(struct radeon_device *rdev, struct radeon_ib 
*ib);


 /*
@@ -756,6 +763,7 @@ struct radeon_cs_reloc {
struct radeon_bo_list   lobj;
uint32_thandle;
uint32_tflags;
+   uint64_tgpu_addr;
 };

 struct radeon_cs_chunk {
@@ -1496,6 +1504,9 @@ struct radeon_device {
unsigneddebugfs_count;
/* virtual memory */
struct radeon_vm_managervm_manager;
+   uint32_t*blob;
+   unsignedblob_size_dw;
+   struct mutexblob_mutex;
 };

 int radeon_device_init(struct radeon_device *rdev,
@@ -1742,7 +1753,8 @@ void radeon_vm_unbind(struct radeon_device *rdev, struct 
radeon_vm *vm);
 int radeon_vm_bo_update_pte(struct radeon_device *rdev,
struct radeon_vm *vm,
struct radeon_bo *bo,
-   struct ttm_mem_reg *mem);
+   struct ttm_mem_reg *mem,
+   uint64_t *gpu_addr);
 void radeon_vm_bo_invalidate(struct radeon_device *rdev,
 struct radeon_bo *bo);
 int radeon_vm_bo_add(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index ecef708..0c0bcaa 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -334,6 +334,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
  struct radeon_cs_parser *parser)
 {
struct radeon_cs_chunk *ib_chunk;
+   unsigned i;
int r;

if (parser->chunk_ib_idx == -1)
@@ -369,6 +370,10 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
DRM_ERROR("Failed to synchronize rings !\n");
}
parser->ib->vm_id = 0;
+   parser->ib->type = RADEON_IB_TYPE_CS;
+   for (i = 0; i < parser->nrelocs; ++i) {
+   parser->relocs[i].gpu_addr = parser->relocs[i].lobj.gpu_offset;
+   }
r = radeon_ib_schedule(rdev, parser->ib);
if (r) {
   

[PATCH 23/24] drm/radeon: keep the cs relocs inside the ib

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Free them wenn the ib is freed, another
step to better debugging.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h  |3 +++
 drivers/gpu/drm/radeon/radeon_cs.c   |   14 --
 drivers/gpu/drm/radeon/radeon_ring.c |3 +++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 6377f8c..7b2125b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -567,6 +567,7 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device 
*rdev, int crtc);
 /*
  * CP & rings.
  */
+struct radeon_cs_reloc;

 struct radeon_ib {
struct radeon_sa_bo sa_bo;
@@ -576,6 +577,8 @@ struct radeon_ib {
struct radeon_fence *fence;
unsignedvm_id;
boolis_const_ib;
+   unsignednrelocs;
+   struct radeon_cs_reloc  *relocs;
 };

 struct radeon_ring {
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 38e1496..ecef708 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -308,7 +308,6 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser 
*parser, int error)
}
}
kfree(parser->track);
-   kfree(parser->relocs);
kfree(parser->relocs_ptr);
for (i = 0; i < parser->nchunks; i++) {
kfree(parser->chunks[i].kdata);
@@ -317,7 +316,18 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser 
*parser, int error)
}
kfree(parser->chunks);
kfree(parser->chunks_array);
-   radeon_ib_free(parser->rdev, >ib);
+
+   if (parser->ib) {
+   /* keep the relocs for debugging */
+   parser->ib->nrelocs = parser->nrelocs;
+   parser->ib->relocs = parser->relocs;
+
+   /* even if we locally free it the ib stays
+  alive until it is processed */
+   radeon_ib_free(parser->rdev, >ib);
+   } else {
+   kfree(parser->relocs);
+   }
 }

 static int radeon_cs_ib_chunk(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index f256eae..c635aad 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -95,6 +95,8 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
(*ib)->gpu_addr += (*ib)->sa_bo.offset;
(*ib)->vm_id = 0;
(*ib)->is_const_ib = false;
+   (*ib)->nrelocs = 0;
+   (*ib)->relocs = NULL;

return 0;
 }
@@ -116,6 +118,7 @@ void radeon_ib_free(struct radeon_device *rdev, struct 
radeon_ib **ib)
if (destroy) {
radeon_sa_bo_free(rdev, >sa_bo);
radeon_fence_unref(>fence);
+   kfree(tmp->relocs);
kfree(tmp);
}
 }
-- 
1.7.7.6



[PATCH 22/24] drm/radeon: extend ring debugfs files with fence info c2

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

That should aid in debugging multi ring lockups.

v2 rebase on top of debugfs removal

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |1 +
 drivers/gpu/drm/radeon/radeon_fence.c |1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 91b48ac..6377f8c 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -233,6 +233,7 @@ struct radeon_fence {
boolsignaled;
/* RB, DMA, etc. */
int ring;
+   unsignedemitted_at;
struct radeon_semaphore *semaphore;
struct radeon_ib*ib;
 };
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 2868eda..2e56101 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -71,6 +71,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
return 0;
}
fence->seq = atomic_add_return(1, >fence_drv[fence->ring].seq);
+   fence->emitted_at = rdev->ring[fence->ring].wptr;
radeon_fence_ring_emit(rdev, fence->ring, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq);
fence->emitted = true;
-- 
1.7.7.6



[PATCH 21/24] drm/radeon: remove cayman_gpu_is_lockup

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Since it is now identical to evergreen_gpu_is_lockup.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/ni.c  |   19 ---
 drivers/gpu/drm/radeon/radeon_asic.c |   12 ++--
 drivers/gpu/drm/radeon/radeon_asic.h |1 -
 3 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 8a9c85d..107b217 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1392,25 +1392,6 @@ int cayman_cp_resume(struct radeon_device *rdev)
return 0;
 }

-bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-   u32 srbm_status;
-   u32 grbm_status;
-   u32 grbm_status_se0, grbm_status_se1;
-
-   srbm_status = RREG32(SRBM_STATUS);
-   grbm_status = RREG32(GRBM_STATUS);
-   grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
-   grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
-   if (!(grbm_status & GUI_ACTIVE)) {
-   radeon_ring_lockup_update(ring);
-   return false;
-   }
-   /* force CP activities */
-   radeon_ring_force_activity(rdev, ring);
-   return radeon_ring_test_lockup(rdev, ring);
-}
-
 static int cayman_gpu_soft_reset(struct radeon_device *rdev)
 {
struct evergreen_mc_save save;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index 5e5694e..f533df5 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1339,7 +1339,7 @@ static struct radeon_asic cayman_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP1_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1349,7 +1349,7 @@ static struct radeon_asic cayman_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP2_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1359,7 +1359,7 @@ static struct radeon_asic cayman_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -1433,7 +1433,7 @@ static struct radeon_asic trinity_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP1_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1443,7 +1443,7 @@ static struct radeon_asic trinity_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP2_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1453,7 +1453,7 @@ static struct radeon_asic trinity_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index 58454b4..ddb145d 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -435,7 +435,6 @@ int cayman_init(struct radeon_device *rdev);
 void cayman_fini(struct radeon_device *rdev);
 int cayman_suspend(struct radeon_device *rdev);
 int cayman_resume(struct radeon_device *rdev);
-bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
 int cayman_asic_reset(struct radeon_device *rdev);
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int cayman_vm_init(struct radeon_device *rdev);
-- 
1.7.7.6



[PATCH 20/24] drm/radeon: remove r300_gpu_is_lockup

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Since it is now identical to r100_gpu_is_lockup.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/r300.c|   14 --
 drivers/gpu/drm/radeon/radeon_asic.c |   16 
 drivers/gpu/drm/radeon/radeon_asic.h |1 -
 3 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index c496778..7c53729 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -372,20 +372,6 @@ void r300_gpu_init(struct radeon_device *rdev)
 rdev->num_gb_pipes, rdev->num_z_pipes);
 }

-bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-   u32 rbbm_status;
-
-   rbbm_status = RREG32(R_000E40_RBBM_STATUS);
-   if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
-   radeon_ring_lockup_update(ring);
-   return false;
-   }
-   /* force CP activities */
-   radeon_ring_force_activity(rdev, ring);
-   return radeon_ring_test_lockup(rdev, ring);
-}
-
 int r300_asic_reset(struct radeon_device *rdev)
 {
struct r100_mc_save save;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index 958b9ea..5e5694e 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -299,7 +299,7 @@ static struct radeon_asic r300_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -373,7 +373,7 @@ static struct radeon_asic r300_asic_pcie = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -447,7 +447,7 @@ static struct radeon_asic r420_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -521,7 +521,7 @@ static struct radeon_asic rs400_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -595,7 +595,7 @@ static struct radeon_asic rs600_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -669,7 +669,7 @@ static struct radeon_asic rs690_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -743,7 +743,7 @@ static struct radeon_asic rv515_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -817,7 +817,7 @@ static struct radeon_asic r520_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index 84f3552..58454b4 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -151,7 +151,6 @@ extern int r300_init(struct radeon_device *rdev);
 extern void r300_fini(struct radeon_device *rdev);
 extern int r300_suspend(struct radeon_device *rdev);
 extern int r300_resume(struct radeon_device *rdev);
-extern bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring 
*cp);
 extern int r300_asic_reset(struct radeon_device *rdev);
 extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring 
*ring);
 extern void r300_fence_ring_emit(struct radeon_device *rdev,
-- 
1.7.7.6



[PATCH 19/24] drm/radeon: make forcing ring activity a common function

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Nothing chipset or ring specific with it,
so also move it to radon_ring.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/evergreen.c   |   10 +-
 drivers/gpu/drm/radeon/ni.c  |   11 +--
 drivers/gpu/drm/radeon/r100.c|   10 +-
 drivers/gpu/drm/radeon/r300.c|   10 +-
 drivers/gpu/drm/radeon/r600.c|   10 +-
 drivers/gpu/drm/radeon/radeon.h  |1 +
 drivers/gpu/drm/radeon/radeon_ring.c |   16 
 drivers/gpu/drm/radeon/si.c  |   11 +--
 8 files changed, 23 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index 353d10a..ec61194 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2424,7 +2424,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   int r;

srbm_status = RREG32(SRBM_STATUS);
grbm_status = RREG32(GRBM_STATUS);
@@ -2435,14 +2434,7 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   ring->rptr = RREG32(CP_RB_RPTR);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 4327b32..8a9c85d 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1397,7 +1397,6 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   int r;

srbm_status = RREG32(SRBM_STATUS);
grbm_status = RREG32(GRBM_STATUS);
@@ -1408,15 +1407,7 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   /* XXX deal with CP0,1,2 */
-   ring->rptr = RREG32(ring->rptr_reg);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 0a62ada..68b1674 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2155,7 +2155,6 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
 bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
u32 rbbm_status;
-   int r;

rbbm_status = RREG32(R_000E40_RBBM_STATUS);
if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
@@ -2163,14 +2162,7 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   ring->rptr = RREG32(ring->rptr_reg);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index e46bbd0..c496778 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -375,7 +375,6 @@ void r300_gpu_init(struct radeon_device *rdev)
 bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
u32 rbbm_status;
-   int r;

rbbm_status = RREG32(R_000E40_RBBM_STATUS);
if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
@@ -383,14 +382,7 @@ bool r300_gpu_is_lockup(struct radeon_device *rdev, struct 
radeon_ring *ring)
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   ring->rptr = RREG32(RADEON_CP_RB_RPTR);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git 

[PATCH 18/24] drm/radeon: unlock the ring mutex while waiting for the next fence

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Fixing just another deadlock problem with gpu reset tests.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_ring.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index d7245db..bb5715a 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -275,7 +275,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct 
radeon_ring *ring, unsi
if (ndw < ring->ring_free_dw) {
break;
}
+   mutex_unlock(>mutex);
r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring));
+   mutex_lock(>mutex);
if (r)
return r;
}
-- 
1.7.7.6



[PATCH 17/24] drm/radeon: make lockup timeout a module param

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Don't hard code the 10 seconds timeout. Compute jobs
can run much longer.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h  |1 +
 drivers/gpu/drm/radeon/radeon_drv.c  |4 
 drivers/gpu/drm/radeon/radeon_ring.c |2 +-
 3 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c0ed077..fde5eaa 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -94,6 +94,7 @@ extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
 extern int radeon_pcie_gen2;
 extern int radeon_msi;
+extern int radeon_lockup_timeout;

 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index ef7bb3f..e62e56a 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -128,6 +128,7 @@ int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
 int radeon_msi = -1;
+int radeon_lockup_timeout = 1;

 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -177,6 +178,9 @@ module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
 MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(msi, radeon_msi, int, 0444);

+MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 1 = 10 
seconds, 0 = disable)");
+module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
drm_radeon_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index f2dfcbf..d7245db 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -370,7 +370,7 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
return false;
}
elapsed = jiffies_to_msecs(cjiffies - ring->last_activity);
-   if (elapsed >= 1) {
+   if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) {
dev_err(rdev->dev, "GPU lockup CP stall for more than 
%lumsec\n", elapsed);
return true;
}
-- 
1.7.7.6



[PATCH 16/24] drm/radeon: move lockup detection code into radeon_ring.c v2

2012-04-25 Thread j.gli...@gmail.com
From: Jerome Glisse 

It isn't chipset specific, so it makes no sense
to have that inside r100.c.

v2: rebase on debugfs removal

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/evergreen.c   |5 +--
 drivers/gpu/drm/radeon/ni.c  |5 +--
 drivers/gpu/drm/radeon/r100.c|   57 +
 drivers/gpu/drm/radeon/r300.c|4 +-
 drivers/gpu/drm/radeon/r600.c|   10 +-
 drivers/gpu/drm/radeon/radeon.h  |   16 ++---
 drivers/gpu/drm/radeon/radeon_asic.h |5 ---
 drivers/gpu/drm/radeon/radeon_ring.c |   53 +++
 drivers/gpu/drm/radeon/si.c  |5 +--
 9 files changed, 69 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index a76389c..353d10a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2424,7 +2424,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   struct r100_gpu_lockup *lockup = >config.evergreen.lockup;
int r;

srbm_status = RREG32(SRBM_STATUS);
@@ -2432,7 +2431,7 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
if (!(grbm_status & GUI_ACTIVE)) {
-   r100_gpu_lockup_update(lockup, ring);
+   radeon_ring_lockup_update(ring);
return false;
}
/* force CP activities */
@@ -2444,7 +2443,7 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
radeon_ring_unlock_commit(rdev, ring);
}
ring->rptr = RREG32(CP_RB_RPTR);
-   return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+   return radeon_ring_test_lockup(rdev, ring);
 }

 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index c0b0956..4327b32 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1397,7 +1397,6 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   struct r100_gpu_lockup *lockup = >config.cayman.lockup;
int r;

srbm_status = RREG32(SRBM_STATUS);
@@ -1405,7 +1404,7 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
if (!(grbm_status & GUI_ACTIVE)) {
-   r100_gpu_lockup_update(lockup, ring);
+   radeon_ring_lockup_update(ring);
return false;
}
/* force CP activities */
@@ -1418,7 +1417,7 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
}
/* XXX deal with CP0,1,2 */
ring->rptr = RREG32(ring->rptr_reg);
-   return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+   return radeon_ring_test_lockup(rdev, ring);
 }

 static int cayman_gpu_soft_reset(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index be51f7b..0a62ada 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2152,59 +2152,6 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
return -1;
 }

-void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_ring 
*ring)
-{
-   lockup->last_cp_rptr = ring->rptr;
-   lockup->last_jiffies = jiffies;
-}
-
-/**
- * r100_gpu_cp_is_lockup() - check if CP is lockup by recording information
- * @rdev:  radeon device structure
- * @lockup:r100_gpu_lockup structure holding CP lockup tracking 
informations
- * @cp:radeon_cp structure holding CP information
- *
- * We don't need to initialize the lockup tracking information as we will 
either
- * have CP rptr to a different value of jiffies wrap around which will force
- * initialization of the lockup tracking informations.
- *
- * A possible false positivie is if we get call after while and last_cp_rptr ==
- * the current CP rptr, even if it's unlikely it might happen. To avoid this
- * if the elapsed time since last call is bigger than 2 second than we return
- * false and update the tracking information. Due to this the caller must call
- * r100_gpu_cp_is_lockup several time in less than 2sec for lockup to be 
reported
- * the fencing code should be cautious about that.
- *
- * Caller should write to the ring to force CP to do something so we don't get
- * false positive when CP is just gived nothing to do.
- *
- **/
-bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct 

[PATCH 15/24] drm/radeon: remove recursive mutex implementation

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Not needed anymore.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|   44 +---
 drivers/gpu/drm/radeon/radeon_cs.c |   10 +++---
 drivers/gpu/drm/radeon/radeon_device.c |2 +-
 drivers/gpu/drm/radeon/radeon_gart.c   |   16 ++--
 drivers/gpu/drm/radeon/radeon_gem.c|4 +-
 5 files changed, 17 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c7f14d7..6ec4025 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -155,48 +155,6 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t 
*bios, int offset, int len)
 #endif
 bool radeon_get_bios(struct radeon_device *rdev);

-
-/*
- * Mutex which allows recursive locking from the same process.
- */
-struct radeon_mutex {
-   struct mutexmutex;
-   struct task_struct  *owner;
-   int level;
-};
-
-static inline void radeon_mutex_init(struct radeon_mutex *mutex)
-{
-   mutex_init(>mutex);
-   mutex->owner = NULL;
-   mutex->level = 0;
-}
-
-static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
-{
-   if (mutex_trylock(>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->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);
-}
-
-
 /*
  * Dummy page
  */
@@ -1497,7 +1455,7 @@ struct radeon_device {
struct radeon_gem   gem;
struct radeon_pmpm;
uint32_tbios_scratch[RADEON_BIOS_NUM_SCRATCH];
-   struct radeon_mutex cs_mutex;
+   struct mutexcs_mutex;
struct radeon_wbwb;
struct radeon_dummy_pagedummy_page;
boolshutdown;
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index a0826bb..38e1496 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -505,9 +505,9 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
struct radeon_cs_parser parser;
int r;

-   radeon_mutex_lock(>cs_mutex);
+   mutex_lock(>cs_mutex);
if (!rdev->accel_working) {
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return -EBUSY;
}
/* initialize parser */
@@ -521,7 +521,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
DRM_ERROR("Failed to initialize parser !\n");
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return r;
}
r = radeon_cs_parser_relocs();
@@ -530,7 +530,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
DRM_ERROR("Failed to parse relocation %d!\n", r);
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return r;
}
r = radeon_cs_ib_chunk(rdev, );
@@ -544,7 +544,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
 out:
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return r;
 }

diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 1dac27d..5df53dd 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -722,7 +722,7 @@ int radeon_device_init(struct radeon_device *rdev,

/* mutex initialization are all done here so we
 * can recall function without having locking issues */
-   radeon_mutex_init(>cs_mutex);
+   mutex_init(>cs_mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(>ring[i].mutex);
mutex_init(>dc_hw_i2c_mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c 
b/drivers/gpu/drm/radeon/radeon_gart.c
index 220dbb8..b4a4982 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -356,13 +356,13 @@ int 

[PATCH 14/24] drm/radeon: rework recursive gpu reset handling

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Instead of all this humpy pumpy with recursive
mutex (which also fixes only halve of the problem)
move the actual gpu reset out of the fence code,
return -EDEADLK and then reset the gpu in the
calling ioctl function.

v2: Split removal of radeon_mutex into separate patch.
Return -EAGAIN if reset is successful.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_cs.c |   13 +
 drivers/gpu/drm/radeon/radeon_device.c |5 -
 drivers/gpu/drm/radeon/radeon_fence.c  |   10 +++---
 drivers/gpu/drm/radeon/radeon_gem.c|   16 
 4 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 64b86e7..a0826bb 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -489,6 +489,16 @@ out:
return r;
 }

+static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r)
+{
+   if (r == -EDEADLK) {
+   r = radeon_gpu_reset(rdev);
+   if (!r)
+   r = -EAGAIN;
+   }
+   return r;
+}
+
 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
struct radeon_device *rdev = dev->dev_private;
@@ -510,6 +520,7 @@ 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(, r);
+   r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(>cs_mutex);
return r;
}
@@ -518,6 +529,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(, r);
+   r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(>cs_mutex);
return r;
}
@@ -531,6 +543,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
}
 out:
radeon_cs_parser_fini(, r);
+   r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(>cs_mutex);
return r;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 26fb9da..1dac27d 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -984,9 +984,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
int r;
int resched;

-   /* Prevent CS ioctl from interfering */
-   radeon_mutex_lock(>cs_mutex);
-
radeon_save_bios_scratch_regs(rdev);
/* block TTM */
resched = ttm_bo_lock_delayed_workqueue(>mman.bdev);
@@ -1001,8 +998,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
ttm_bo_unlock_delayed_workqueue(>mman.bdev, resched);
}

-   radeon_mutex_unlock(>cs_mutex);
-
if (r) {
/* bad news, how to tell it to userspace ? */
dev_info(rdev->dev, "GPU reset failed\n");
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index abd10f9..2868eda 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -267,6 +267,8 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
/* change sequence value on all rings, so nobody else 
things there is a lockup */
for (i = 0; i < RADEON_NUM_RINGS; ++i)
rdev->fence_drv[i].last_seq -= 0x1;
+
+   rdev->fence_drv[fence->ring].last_activity = jiffies;
write_unlock_irqrestore(>fence_lock, irq_flags);

if (radeon_ring_is_lockup(rdev, fence->ring, 
>ring[fence->ring])) {
@@ -277,13 +279,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool 
intr)

/* mark the ring as not ready any more */
rdev->ring[fence->ring].ready = false;
-   r = radeon_gpu_reset(rdev);
-   if (r)
-   return r;
-
-   write_lock_irqsave(>fence_lock, 
irq_flags);
-   rdev->fence_drv[fence->ring].last_activity = 
jiffies;
-   write_unlock_irqrestore(>fence_lock, 
irq_flags);
+   return -EDEADLK;
}
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index c7008b5..e15cb1f 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -154,6 +154,17 @@ void radeon_gem_object_close(struct drm_gem_object *obj,

[PATCH 13/24] drm/radeon: fix a bug with the ring syncing code

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Rings need to lock in order, otherwise
the ring subsystem can deadlock.

v2: fix error handling and number of locked doublewords.
v3: stop creating unneeded semaphores.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |4 ++
 drivers/gpu/drm/radeon/radeon_cs.c|   35 ++
 drivers/gpu/drm/radeon/radeon_semaphore.c |   56 +
 drivers/gpu/drm/radeon/radeon_ttm.c   |   48 +++--
 4 files changed, 93 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 575dc05..c7f14d7 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -442,6 +442,10 @@ void radeon_semaphore_emit_signal(struct radeon_device 
*rdev, int ring,
  struct radeon_semaphore *semaphore);
 void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
struct radeon_semaphore *semaphore);
+int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+   struct radeon_semaphore *semaphore,
+   bool sync_to[RADEON_NUM_RINGS],
+   int dst_ring);
 void radeon_semaphore_free(struct radeon_device *rdev,
   struct radeon_semaphore *semaphore);

diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 5cac832..64b86e7 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -118,6 +118,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, 
u32 ring, s32 priority
 static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
 {
bool sync_to_ring[RADEON_NUM_RINGS] = { };
+   bool need_sync = false;
int i, r;

for (i = 0; i < p->nrelocs; i++) {
@@ -126,36 +127,24 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser 
*p)

if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) {
struct radeon_fence *fence = 
p->relocs[i].robj->tbo.sync_obj;
-   if (!radeon_fence_signaled(fence)) {
+   if (fence->ring != p->ring && 
!radeon_fence_signaled(fence)) {
sync_to_ring[fence->ring] = true;
+   need_sync = true;
}
}
}

-   for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-   /* no need to sync to our own or unused rings */
-   if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready)
-   continue;
-
-   if (!p->ib->fence->semaphore) {
-   r = radeon_semaphore_create(p->rdev, 
>ib->fence->semaphore);
-   if (r)
-   return r;
-   }
-
-   r = radeon_ring_lock(p->rdev, >rdev->ring[i], 3);
-   if (r)
-   return r;
-   radeon_semaphore_emit_signal(p->rdev, i, 
p->ib->fence->semaphore);
-   radeon_ring_unlock_commit(p->rdev, >rdev->ring[i]);
+   if (!need_sync) {
+   return 0;
+   }

-   r = radeon_ring_lock(p->rdev, >rdev->ring[p->ring], 3);
-   if (r)
-   return r;
-   radeon_semaphore_emit_wait(p->rdev, p->ring, 
p->ib->fence->semaphore);
-   radeon_ring_unlock_commit(p->rdev, >rdev->ring[p->ring]);
+   r = radeon_semaphore_create(p->rdev, >ib->fence->semaphore);
+   if (r) {
+   return r;
}
-   return 0;
+
+   return radeon_semaphore_sync_rings(p->rdev, p->ib->fence->semaphore,
+  sync_to_ring, p->ring);
 }

 int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c 
b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 9e2cf40..042dbfe 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -75,6 +75,62 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, 
int ring,
radeon_semaphore_ring_emit(rdev, ring, >ring[ring], semaphore, 
true);
 }

+int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+   struct radeon_semaphore *semaphore,
+   bool sync_to[RADEON_NUM_RINGS],
+   int dst_ring)
+{
+   int i, r;
+
+   for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+   unsigned num_ops = i == dst_ring ? RADEON_NUM_RINGS : 1;
+
+   /* don't lock unused rings */
+   if (!sync_to[i] && i != dst_ring)
+   continue;
+
+   /* prevent GPU deadlocks */
+   if (!rdev->ring[i].ready) {
+   dev_err(rdev->dev, 

[PATCH 12/24] drm/radeon: rip out the ib pool v2

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

It isn't necessary any more and the suballocator
seems to perform even better.

v2: drop debugfs

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |   22 +---
 drivers/gpu/drm/radeon/radeon_device.c|1 -
 drivers/gpu/drm/radeon/radeon_fence.c |   44 ++-
 drivers/gpu/drm/radeon/radeon_gart.c  |   12 +-
 drivers/gpu/drm/radeon/radeon_ring.c  |  187 ++---
 drivers/gpu/drm/radeon/radeon_semaphore.c |6 +-
 6 files changed, 116 insertions(+), 156 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 7f73f40..575dc05 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -249,6 +249,8 @@ extern void evergreen_tiling_fields(unsigned tiling_flags, 
unsigned *bankw,
 /*
  * Fences.
  */
+struct radeon_ib;
+
 struct radeon_fence_driver {
uint32_tscratch_reg;
uint64_tgpu_addr;
@@ -259,7 +261,6 @@ struct radeon_fence_driver {
wait_queue_head_t   queue;
struct list_headcreated;
struct list_heademitted;
-   struct list_headsignaled;
boolinitialized;
 };

@@ -274,6 +275,7 @@ struct radeon_fence {
/* RB, DMA, etc. */
int ring;
struct radeon_semaphore *semaphore;
+   struct radeon_ib*ib;
 };

 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
@@ -289,6 +291,7 @@ int radeon_fence_wait_empty(struct radeon_device *rdev, int 
ring);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
+bool radeon_fence_set_associated_ib(struct radeon_fence *fence, struct 
radeon_ib *ib);

 /*
  * Tiling registers
@@ -603,7 +606,6 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device 
*rdev, int crtc);

 struct radeon_ib {
struct radeon_sa_bo sa_bo;
-   unsignedidx;
uint32_tlength_dw;
uint64_tgpu_addr;
uint32_t*ptr;
@@ -612,18 +614,6 @@ struct radeon_ib {
boolis_const_ib;
 };

-/*
- * locking -
- * mutex protects scheduled_ibs, ready, alloc_bm
- */
-struct radeon_ib_pool {
-   struct radeon_mutex mutex;
-   struct radeon_sa_managersa_manager;
-   struct radeon_ibibs[RADEON_IB_POOL_SIZE];
-   boolready;
-   unsignedhead_id;
-};
-
 struct radeon_ring {
struct radeon_bo*ring_obj;
volatile uint32_t   *ring;
@@ -764,7 +754,6 @@ struct si_rlc {
 int radeon_ib_get(struct radeon_device *rdev, int ring,
  struct radeon_ib **ib, unsigned size);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
-bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
@@ -1497,7 +1486,8 @@ struct radeon_device {
rwlock_tfence_lock;
struct radeon_fence_driver  fence_drv[RADEON_NUM_RINGS];
struct radeon_ring  ring[RADEON_NUM_RINGS];
-   struct radeon_ib_pool   ib_pool;
+   boolib_pool_ready;
+   struct radeon_sa_managersa_manager;
struct radeon_irq   irq;
struct radeon_asic  *asic;
struct radeon_gem   gem;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index d77f19f..26fb9da 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -723,7 +723,6 @@ int radeon_device_init(struct radeon_device *rdev,
/* mutex initialization are all done here so we
 * can recall function without having locking issues */
radeon_mutex_init(>cs_mutex);
-   radeon_mutex_init(>ib_pool.mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(>ring[i].mutex);
mutex_init(>dc_hw_i2c_mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index c96d112..abd10f9 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -83,7 +83,8 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
return 0;
 }

-static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring)
+static bool radeon_fence_poll_locked(struct radeon_device 

[PATCH 11/24] drm/radeon: rename fence_wait_last to fence_wait_empty

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

As discussed with Michel that name better
describes the behavior of this function.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|2 +-
 drivers/gpu/drm/radeon/radeon_device.c |2 +-
 drivers/gpu/drm/radeon/radeon_fence.c  |4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 222939f..7f73f40 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -285,7 +285,7 @@ void radeon_fence_process(struct radeon_device *rdev, int 
ring);
 bool radeon_fence_signaled(struct radeon_fence *fence);
 int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
 int radeon_fence_wait_next(struct radeon_device *rdev, int ring);
-int radeon_fence_wait_last(struct radeon_device *rdev, int ring);
+int radeon_fence_wait_empty(struct radeon_device *rdev, int ring);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index f314819..d77f19f 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -913,7 +913,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t 
state)
radeon_bo_evict_vram(rdev);
/* wait for gpu to finish processing current batch */
for (i = 0; i < RADEON_NUM_RINGS; i++)
-   radeon_fence_wait_last(rdev, i);
+   radeon_fence_wait_empty(rdev, i);

radeon_save_bios_scratch_regs(rdev);

diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index b8db542..c96d112 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -297,7 +297,7 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int 
ring)
return r;
 }

-int radeon_fence_wait_last(struct radeon_device *rdev, int ring)
+int radeon_fence_wait_empty(struct radeon_device *rdev, int ring)
 {
unsigned long irq_flags;
struct radeon_fence *fence;
@@ -439,7 +439,7 @@ void radeon_fence_driver_fini(struct radeon_device *rdev)
for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
if (!rdev->fence_drv[ring].initialized)
continue;
-   radeon_fence_wait_last(rdev, ring);
+   radeon_fence_wait_empty(rdev, ring);
wake_up_all(>fence_drv[ring].queue);
write_lock_irqsave(>fence_lock, irq_flags);
radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
-- 
1.7.7.6



[PATCH 10/24] drm/radeon: return -ENOENT in fence_wait_next v2

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

We should signal the caller that we haven't waited at all.

v2: only change fence_wait_next not fence_wait_last.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_fence.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 5d2ca1d..b8db542 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -286,7 +286,7 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int 
ring)
}
if (list_empty(>fence_drv[ring].emitted)) {
write_unlock_irqrestore(>fence_lock, irq_flags);
-   return 0;
+   return -ENOENT;
}
fence = list_entry(rdev->fence_drv[ring].emitted.next,
   struct radeon_fence, list);
-- 
1.7.7.6



[PATCH 09/24] drm/radeon: simplify semaphore handling

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Directly use the suballocator to get small chunks
of memory. It's equally fast and doesn't crash when
we encounter a GPU reset.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/evergreen.c|1 -
 drivers/gpu/drm/radeon/ni.c   |1 -
 drivers/gpu/drm/radeon/r600.c |1 -
 drivers/gpu/drm/radeon/radeon.h   |   29 +--
 drivers/gpu/drm/radeon/radeon_device.c|2 -
 drivers/gpu/drm/radeon/radeon_semaphore.c |  137 +
 drivers/gpu/drm/radeon/rv770.c|1 -
 drivers/gpu/drm/radeon/si.c   |1 -
 8 files changed, 26 insertions(+), 147 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index ca47f52..a76389c 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3431,7 +3431,6 @@ void evergreen_fini(struct radeon_device *rdev)
evergreen_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
-   radeon_semaphore_driver_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_agp_fini(rdev);
radeon_bo_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 0146428..c0b0956 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1773,7 +1773,6 @@ void cayman_fini(struct radeon_device *rdev)
cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
-   radeon_semaphore_driver_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index bc3a2ef..24e68fd 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2667,7 +2667,6 @@ void r600_fini(struct radeon_device *rdev)
r600_vram_scratch_fini(rdev);
radeon_agp_fini(rdev);
radeon_gem_fini(rdev);
-   radeon_semaphore_driver_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 415a496..222939f 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -427,34 +427,12 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
 /*
  * Semaphores.
  */
-struct radeon_ring;
-
-#defineRADEON_SEMAPHORE_BO_SIZE256
-
-struct radeon_semaphore_driver {
-   rwlock_tlock;
-   struct list_headbo;
-};
-
-struct radeon_semaphore_bo;
-
-/* everything here is constant */
 struct radeon_semaphore {
-   struct list_headlist;
-   uint64_tgpu_addr;
-   uint32_t*cpu_ptr;
-   struct radeon_semaphore_bo  *bo;
-};
-
-struct radeon_semaphore_bo {
-   struct list_headlist;
-   struct radeon_ib*ib;
-   struct list_headfree;
-   struct radeon_semaphore semaphores[RADEON_SEMAPHORE_BO_SIZE/8];
-   unsignednused;
+   struct radeon_sa_bo sa_bo;
+   signed  waiters;
+   uint64_tgpu_addr;
 };

-void radeon_semaphore_driver_fini(struct radeon_device *rdev);
 int radeon_semaphore_create(struct radeon_device *rdev,
struct radeon_semaphore **semaphore);
 void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
@@ -1518,7 +1496,6 @@ struct radeon_device {
struct radeon_mman  mman;
rwlock_tfence_lock;
struct radeon_fence_driver  fence_drv[RADEON_NUM_RINGS];
-   struct radeon_semaphore_driver  semaphore_drv;
struct radeon_ring  ring[RADEON_NUM_RINGS];
struct radeon_ib_pool   ib_pool;
struct radeon_irq   irq;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index eb63a06..f314819 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -733,11 +733,9 @@ int radeon_device_init(struct radeon_device *rdev,
mutex_init(>pm.mutex);
mutex_init(>vram_mutex);
rwlock_init(>fence_lock);
-   rwlock_init(>semaphore_drv.lock);
INIT_LIST_HEAD(>gem.objects);
init_waitqueue_head(>irq.vblank_queue);
init_waitqueue_head(>irq.idle_queue);
-   INIT_LIST_HEAD(>semaphore_drv.bo);
/* initialize vm here */
rdev->vm_manager.use_bitmap = 1;
rdev->vm_manager.max_pfn = 1 << 20;
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c 
b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 61dd4e3..b67c259 100644
--- 

[PATCH 08/24] drm/radeon: add biggest hole tracking and wakequeue to the sa v4

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

With that in place clients are automatically blocking
until their memory request can be handled.

v2: block only if the memory request can't be satisfied
in the first try, the first version actually lacked
a night of sleep.

v3: make blocking optional, update comments and fix
another bug with biggest hole tracking.

v4: drop debugfs portion

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|5 +-
 drivers/gpu/drm/radeon/radeon_gart.c   |2 +-
 drivers/gpu/drm/radeon/radeon_object.h |2 +-
 drivers/gpu/drm/radeon/radeon_ring.c   |   20 ++--
 drivers/gpu/drm/radeon/radeon_sa.c |  178 ++--
 5 files changed, 138 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 1aefbd9..415a496 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -381,17 +381,16 @@ struct radeon_bo_list {
  * alignment).
  */
 struct radeon_sa_manager {
-   spinlock_t  lock;
+   wait_queue_head_t   queue;
struct radeon_bo*bo;
struct list_headsa_bo;
unsignedsize;
+   struct list_head*biggest_hole;
uint64_tgpu_addr;
void*cpu_ptr;
uint32_tdomain;
 };

-struct radeon_sa_bo;
-
 /* sub-allocation buffer */
 struct radeon_sa_bo {
struct list_headlist;
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c 
b/drivers/gpu/drm/radeon/radeon_gart.c
index c58a036..7af4ff9 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -395,7 +395,7 @@ int radeon_vm_bind(struct radeon_device *rdev, struct 
radeon_vm *vm)
 retry:
r = radeon_sa_bo_new(rdev, >vm_manager.sa_manager, >sa_bo,
 RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8),
-RADEON_GPU_PAGE_SIZE);
+RADEON_GPU_PAGE_SIZE, false);
if (r) {
if (list_empty(>vm_manager.lru_vm)) {
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_object.h 
b/drivers/gpu/drm/radeon/radeon_object.h
index f9104be..a181c2f 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -158,7 +158,7 @@ extern int radeon_sa_bo_manager_suspend(struct 
radeon_device *rdev,
 extern int radeon_sa_bo_new(struct radeon_device *rdev,
struct radeon_sa_manager *sa_manager,
struct radeon_sa_bo *sa_bo,
-   unsigned size, unsigned align);
+   unsigned size, unsigned align, bool block);
 extern void radeon_sa_bo_free(struct radeon_device *rdev,
  struct radeon_sa_bo *sa_bo);

diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index e394131..b06e04f 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -121,7 +121,7 @@ retry:
if (rdev->ib_pool.ibs[idx].fence == NULL) {
r = radeon_sa_bo_new(rdev, >ib_pool.sa_manager,
 >ib_pool.ibs[idx].sa_bo,
-size, 256);
+size, 256, false);
if (!r) {
*ib = >ib_pool.ibs[idx];
(*ib)->ptr = rdev->ib_pool.sa_manager.cpu_ptr;
@@ -202,10 +202,16 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct 
radeon_ib *ib)

 int radeon_ib_pool_init(struct radeon_device *rdev)
 {
-   struct radeon_sa_manager tmp;
int i, r;

-   r = radeon_sa_bo_manager_init(rdev, ,
+   radeon_mutex_lock(>ib_pool.mutex);
+   if (rdev->ib_pool.ready) {
+   return 0;
+   }
+   rdev->ib_pool.ready = true;
+   radeon_mutex_unlock(>ib_pool.mutex);
+
+   r = radeon_sa_bo_manager_init(rdev, >ib_pool.sa_manager,
  RADEON_IB_POOL_SIZE*64*1024,
  RADEON_GEM_DOMAIN_GTT);
if (r) {
@@ -213,14 +219,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
}

radeon_mutex_lock(>ib_pool.mutex);
-   if (rdev->ib_pool.ready) {
-   radeon_mutex_unlock(>ib_pool.mutex);
-   radeon_sa_bo_manager_fini(rdev, );
-   return 0;
-   }
-
-   rdev->ib_pool.sa_manager = tmp;
-   INIT_LIST_HEAD(>ib_pool.sa_manager.sa_bo);
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
rdev->ib_pool.ibs[i].fence = NULL;
rdev->ib_pool.ibs[i].idx = i;
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 4ce5c51..3212293 100644
--- 

[PATCH 07/24] drm/radeon: add proper locking to the SA v2

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Make the suballocator self containing to locking.

v2: split the bugfix into a seperate patch.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|1 +
 drivers/gpu/drm/radeon/radeon_sa.c |   17 +++--
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 85a3aa9..1aefbd9 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -381,6 +381,7 @@ struct radeon_bo_list {
  * alignment).
  */
 struct radeon_sa_manager {
+   spinlock_t  lock;
struct radeon_bo*bo;
struct list_headsa_bo;
unsignedsize;
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 8fbfe69..4ce5c51 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -37,6 +37,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev,
 {
int r;

+   spin_lock_init(_manager->lock);
sa_manager->bo = NULL;
sa_manager->size = size;
sa_manager->domain = domain;
@@ -136,18 +137,19 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
struct radeon_sa_bo *tmp;
struct list_head *head;
unsigned offset = 0, wasted = 0;
+   unsigned long flags;

BUG_ON(align > RADEON_GPU_PAGE_SIZE);
BUG_ON(size > sa_manager->size);
+   spin_lock_irqsave(_manager->lock, flags);

/* no one ? */
-   head = sa_manager->sa_bo.prev;
if (list_empty(_manager->sa_bo)) {
+   head = _manager->sa_bo;
goto out;
}

/* look for a hole big enough */
-   offset = 0;
list_for_each_entry(tmp, _manager->sa_bo, list) {
/* room before this object ? */
if (offset < tmp->offset && (tmp->offset - offset) >= size) {
@@ -157,9 +159,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
offset = tmp->offset + tmp->size;
wasted = offset % align;
if (wasted) {
-   wasted = align - wasted;
+   offset += align - wasted;
}
-   offset += wasted;
}
/* room at the end ? */
head = sa_manager->sa_bo.prev;
@@ -167,11 +168,11 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
offset = tmp->offset + tmp->size;
wasted = offset % align;
if (wasted) {
-   wasted = align - wasted;
+   offset += wasted = align - wasted;
}
-   offset += wasted;
if ((sa_manager->size - offset) < size) {
/* failed to find somethings big enough */
+   spin_unlock_irqrestore(_manager->lock, flags);
return -ENOMEM;
}

@@ -180,10 +181,14 @@ out:
sa_bo->offset = offset;
sa_bo->size = size;
list_add(_bo->list, head);
+   spin_unlock_irqrestore(_manager->lock, flags);
return 0;
 }

 void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo *sa_bo)
 {
+   unsigned long flags;
+   spin_lock_irqsave(_bo->manager->lock, flags);
list_del_init(_bo->list);
+   spin_unlock_irqrestore(_bo->manager->lock, flags);
 }
-- 
1.7.7.6



[PATCH 06/24] drm/radeon: fix a critical bug in the SA code

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Aligning offset can make it bigger than tmp->offset
leading to an overrun bug in the following subtraction.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_sa.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 4cce47e..8fbfe69 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -150,7 +150,7 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
offset = 0;
list_for_each_entry(tmp, _manager->sa_bo, list) {
/* room before this object ? */
-   if ((tmp->offset - offset) >= size) {
+   if (offset < tmp->offset && (tmp->offset - offset) >= size) {
head = tmp->list.prev;
goto out;
}
-- 
1.7.7.6



[PATCH 05/24] drm/radeon: rework gpu lockup detection and processing

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Previusly multiple rings could trigger multiple GPU
resets at the same time.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |3 +-
 drivers/gpu/drm/radeon/radeon_fence.c |  150 +
 2 files changed, 77 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8801657..85a3aa9 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -255,8 +255,7 @@ struct radeon_fence_driver {
volatile uint32_t   *cpu_addr;
atomic_tseq;
uint32_tlast_seq;
-   unsigned long   last_jiffies;
-   unsigned long   last_timeout;
+   unsigned long   last_activity;
wait_queue_head_t   queue;
struct list_headcreated;
struct list_heademitted;
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index c0ec19d..5d2ca1d 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -74,6 +74,10 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
radeon_fence_ring_emit(rdev, fence->ring, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq);
fence->emitted = true;
+   /* are we the first fence on a previusly idle ring? */
+   if (list_empty(>fence_drv[fence->ring].emitted)) {
+   rdev->fence_drv[fence->ring].last_activity = jiffies;
+   }
list_move_tail(>list, >fence_drv[fence->ring].emitted);
write_unlock_irqrestore(>fence_lock, irq_flags);
return 0;
@@ -85,34 +89,14 @@ static bool radeon_fence_poll_locked(struct radeon_device 
*rdev, int ring)
struct list_head *i, *n;
uint32_t seq;
bool wake = false;
-   unsigned long cjiffies;

seq = radeon_fence_read(rdev, ring);
-   if (seq != rdev->fence_drv[ring].last_seq) {
-   rdev->fence_drv[ring].last_seq = seq;
-   rdev->fence_drv[ring].last_jiffies = jiffies;
-   rdev->fence_drv[ring].last_timeout = 
RADEON_FENCE_JIFFIES_TIMEOUT;
-   } else {
-   cjiffies = jiffies;
-   if (time_after(cjiffies, rdev->fence_drv[ring].last_jiffies)) {
-   cjiffies -= rdev->fence_drv[ring].last_jiffies;
-   if (time_after(rdev->fence_drv[ring].last_timeout, 
cjiffies)) {
-   /* update the timeout */
-   rdev->fence_drv[ring].last_timeout -= cjiffies;
-   } else {
-   /* the 500ms timeout is elapsed we should test
-* for GPU lockup
-*/
-   rdev->fence_drv[ring].last_timeout = 1;
-   }
-   } else {
-   /* wrap around update last jiffies, we will just wait
-* a little longer
-*/
-   rdev->fence_drv[ring].last_jiffies = cjiffies;
-   }
+   if (seq == rdev->fence_drv[ring].last_seq)
return false;
-   }
+
+   rdev->fence_drv[ring].last_seq = seq;
+   rdev->fence_drv[ring].last_activity = jiffies;
+
n = NULL;
list_for_each(i, >fence_drv[ring].emitted) {
fence = list_entry(i, struct radeon_fence, list);
@@ -207,66 +191,84 @@ int radeon_fence_wait(struct radeon_fence *fence, bool 
intr)
struct radeon_device *rdev;
unsigned long irq_flags, timeout;
u32 seq;
-   int r;
+   int i, r;
+   bool signaled;

if (fence == NULL) {
WARN(1, "Querying an invalid fence : %p !\n", fence);
-   return 0;
+   return -EINVAL;
}
+
rdev = fence->rdev;
-   if (radeon_fence_signaled(fence)) {
-   return 0;
-   }
-   timeout = rdev->fence_drv[fence->ring].last_timeout;
-retry:
-   /* save current sequence used to check for GPU lockup */
-   seq = rdev->fence_drv[fence->ring].last_seq;
-   trace_radeon_fence_wait_begin(rdev->ddev, seq);
-   if (intr) {
+   signaled = radeon_fence_signaled(fence);
+   while (!signaled) {
+   read_lock_irqsave(>fence_lock, irq_flags);
+   timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT;
+   if (time_after(rdev->fence_drv[fence->ring].last_activity, 
timeout)) {
+   /* the normal case, timeout is somewhere before 
last_activity */
+   timeout = rdev->fence_drv[fence->ring].last_activity - 
timeout;
+   } else {
+   /* either jiffies wrapped around, or no 

[PATCH 04/24] drm/radeon: use central function for IB testing

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Removing all the different error messages and
having just one standard behaviour over all
chipset generations.

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/evergreen.c   |7 ++-
 drivers/gpu/drm/radeon/ni.c  |7 ++-
 drivers/gpu/drm/radeon/r100.c|7 ++-
 drivers/gpu/drm/radeon/r300.c|7 ++-
 drivers/gpu/drm/radeon/r420.c|7 ++-
 drivers/gpu/drm/radeon/r520.c|8 +++-
 drivers/gpu/drm/radeon/r600.c|7 ++-
 drivers/gpu/drm/radeon/radeon.h  |1 +
 drivers/gpu/drm/radeon/radeon_ring.c |   30 ++
 drivers/gpu/drm/radeon/rs400.c   |7 ++-
 drivers/gpu/drm/radeon/rs600.c   |7 ++-
 drivers/gpu/drm/radeon/rs690.c   |7 ++-
 drivers/gpu/drm/radeon/rv515.c   |8 +++-
 drivers/gpu/drm/radeon/rv770.c   |7 ++-
 14 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index cfa372c..ca47f52 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3248,12 +3248,9 @@ static int evergreen_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

r = r600_audio_init(rdev);
if (r) {
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index a48ca53..0146428 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1601,12 +1601,9 @@ static int cayman_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

r = radeon_vm_manager_start(rdev);
if (r)
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 01e597ad..be51f7b 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3780,12 +3780,9 @@ static int r100_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 40baaec..ae15c10 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -1367,12 +1367,9 @@ static int r300_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 2eba44c..744348b 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -269,12 +269,9 @@ static int r420_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
index 2e5ff86..2ef0c34 100644
--- a/drivers/gpu/drm/radeon/r520.c
+++ b/drivers/gpu/drm/radeon/r520.c
@@ -207,12 +207,10 @@ static int r520_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }
+
return 0;
 }

diff --git a/drivers/gpu/drm/radeon/r600.c 

[PATCH 03/24] drm/radeon: replace gpu_lockup with ring->ready flag

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

It makes no sense at all to have more than one flag.

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/r100.c  |1 -
 drivers/gpu/drm/radeon/r300.c  |1 -
 drivers/gpu/drm/radeon/radeon.h|1 -
 drivers/gpu/drm/radeon/radeon_device.c |1 -
 drivers/gpu/drm/radeon/radeon_fence.c  |   36 +++
 drivers/gpu/drm/radeon/rs600.c |1 -
 6 files changed, 13 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 9e69a95..01e597ad 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2293,7 +2293,6 @@ int r100_asic_reset(struct radeon_device *rdev)
if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) ||
G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) {
dev_err(rdev->dev, "failed to reset GPU\n");
-   rdev->gpu_lockup = true;
ret = -1;
} else
dev_info(rdev->dev, "GPU reset succeed\n");
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index c5237ab..40baaec 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -444,7 +444,6 @@ int r300_asic_reset(struct radeon_device *rdev)
/* Check if GPU is idle */
if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
dev_err(rdev->dev, "failed to reset GPU\n");
-   rdev->gpu_lockup = true;
ret = -1;
} else
dev_info(rdev->dev, "GPU reset succeed\n");
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index bea99e3..365334b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1529,7 +1529,6 @@ struct radeon_device {
struct radeon_mutex cs_mutex;
struct radeon_wbwb;
struct radeon_dummy_pagedummy_page;
-   boolgpu_lockup;
boolshutdown;
boolsuspend;
boolneed_dma32;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index ea7df16..eb63a06 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -714,7 +714,6 @@ int radeon_device_init(struct radeon_device *rdev,
rdev->is_atom_bios = false;
rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT;
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-   rdev->gpu_lockup = false;
rdev->accel_working = false;

DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 
0x%04X:0x%04X).\n",
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 79ce829..c0ec19d 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -71,14 +71,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
return 0;
}
fence->seq = atomic_add_return(1, >fence_drv[fence->ring].seq);
-   if (!rdev->ring[fence->ring].ready)
-   /* FIXME: cp is not running assume everythings is done right
-* away
-*/
-   radeon_fence_write(rdev, fence->seq, fence->ring);
-   else
-   radeon_fence_ring_emit(rdev, fence->ring, fence);
-
+   radeon_fence_ring_emit(rdev, fence->ring, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq);
fence->emitted = true;
list_move_tail(>list, >fence_drv[fence->ring].emitted);
@@ -191,9 +184,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence)
if (!fence)
return true;

-   if (fence->rdev->gpu_lockup)
-   return true;
-
write_lock_irqsave(>rdev->fence_lock, irq_flags);
signaled = fence->signaled;
/* if we are shuting down report all fence as signaled */
@@ -260,18 +250,16 @@ retry:
 */
if (seq == rdev->fence_drv[fence->ring].last_seq &&
radeon_ring_is_lockup(rdev, fence->ring, 
>ring[fence->ring])) {
+
/* good news we believe it's a lockup */
printk(KERN_WARNING "GPU lockup (waiting for 0x%08X 
last fence id 0x%08X)\n",
 fence->seq, seq);
-   /* FIXME: what should we do ? marking everyone
-* as signaled for now
-*/
-   rdev->gpu_lockup = true;
+
+   /* mark the ring as not ready any more */
+   rdev->ring[fence->ring].ready = false;
r = radeon_gpu_reset(rdev);
if (r)
 

[PATCH 02/24] drm/radeon: make radeon_gpu_is_lockup a per ring function

2012-04-25 Thread j.gli...@gmail.com
From: Christian K?nig 

Different rings have different criteria to test
if they are stuck.

v2: rebased on current drm-next

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon.h   |4 +-
 drivers/gpu/drm/radeon/radeon_asic.c  |   44 ++--
 drivers/gpu/drm/radeon/radeon_fence.c |2 +-
 3 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 138b952..bea99e3 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1144,7 +1144,6 @@ struct radeon_asic {
int (*resume)(struct radeon_device *rdev);
int (*suspend)(struct radeon_device *rdev);
void (*vga_set_state)(struct radeon_device *rdev, bool state);
-   bool (*gpu_is_lockup)(struct radeon_device *rdev, struct radeon_ring 
*cp);
int (*asic_reset)(struct radeon_device *rdev);
/* ioctl hw specific callback. Some hw might want to perform special
 * operation on specific ioctl. For instance on wait idle some hw
@@ -1173,6 +1172,7 @@ struct radeon_asic {
void (*ring_start)(struct radeon_device *rdev, struct 
radeon_ring *cp);
int (*ring_test)(struct radeon_device *rdev, struct radeon_ring 
*cp);
int (*ib_test)(struct radeon_device *rdev, struct radeon_ring 
*cp);
+   bool (*is_lockup)(struct radeon_device *rdev, struct 
radeon_ring *cp);
} ring[RADEON_NUM_RINGS];
/* irqs */
struct {
@@ -1730,7 +1730,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t 
v);
 #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
 #define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)].cs_parse((p))
 #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), 
(state))
-#define radeon_gpu_is_lockup(rdev, cp) (rdev)->asic->gpu_is_lockup((rdev), 
(cp))
 #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
 #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
 #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), 
(i), (p))
@@ -1739,6 +1738,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t 
v);
 #define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)].ib_test((rdev), 
(cp))
 #define radeon_ring_ib_execute(rdev, r, ib) 
(rdev)->asic->ring[(r)].ib_execute((rdev), (ib))
 #define radeon_ring_ib_parse(rdev, r, ib) 
(rdev)->asic->ring[(r)].ib_parse((rdev), (ib))
+#define radeon_ring_is_lockup(rdev, r, cp) 
(rdev)->asic->ring[(r)].is_lockup((rdev), (cp))
 #define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev))
 #define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev))
 #define radeon_get_vblank_counter(rdev, crtc) 
(rdev)->asic->display.get_vblank_counter((rdev), (crtc))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index be4dc2f..958b9ea 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -134,7 +134,6 @@ static struct radeon_asic r100_asic = {
.suspend = _suspend,
.resume = _resume,
.vga_set_state = _vga_set_state,
-   .gpu_is_lockup = _gpu_is_lockup,
.asic_reset = _asic_reset,
.ioctl_wait_idle = NULL,
.gui_idle = _gui_idle,
@@ -152,6 +151,7 @@ static struct radeon_asic r100_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -208,7 +208,6 @@ static struct radeon_asic r200_asic = {
.suspend = _suspend,
.resume = _resume,
.vga_set_state = _vga_set_state,
-   .gpu_is_lockup = _gpu_is_lockup,
.asic_reset = _asic_reset,
.ioctl_wait_idle = NULL,
.gui_idle = _gui_idle,
@@ -226,6 +225,7 @@ static struct radeon_asic r200_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -282,7 +282,6 @@ static struct radeon_asic r300_asic = {
.suspend = _suspend,
.resume = _resume,
.vga_set_state = _vga_set_state,
-   .gpu_is_lockup = _gpu_is_lockup,
.asic_reset = _asic_reset,
.ioctl_wait_idle = NULL,
.gui_idle = _gui_idle,
@@ -300,6 +299,7 @@ static struct radeon_asic r300_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -356,7 +356,6 @@ static struct radeon_asic r300_asic_pcie = {
.suspend = 

[PATCH 01/24] drm/radeon: remove fence/ring/ib debugfs files

2012-04-25 Thread j.gli...@gmail.com
From: Jerome Glisse 

Those file never were really helpfull in debuging.

Signed-off-by: Jerome Glisse 
---
 drivers/gpu/drm/radeon/r100.c |  186 -
 drivers/gpu/drm/radeon/r300.c |   50 -
 drivers/gpu/drm/radeon/r420.c |   45 
 drivers/gpu/drm/radeon/r520.c |1 -
 drivers/gpu/drm/radeon/r600.c |   35 --
 drivers/gpu/drm/radeon/radeon_asic.h  |5 -
 drivers/gpu/drm/radeon/radeon_fence.c |   47 
 drivers/gpu/drm/radeon/radeon_ring.c  |  107 ---
 drivers/gpu/drm/radeon/rs400.c|   88 
 drivers/gpu/drm/radeon/rs600.c|7 --
 drivers/gpu/drm/radeon/rs690.c|1 -
 drivers/gpu/drm/radeon/rv515.c|   77 --
 12 files changed, 0 insertions(+), 649 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index fe33d35..9e69a95 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1094,9 +1094,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned 
ring_size)
uint32_t tmp;
int r;

-   if (r100_debugfs_cp_init(rdev)) {
-   DRM_ERROR("Failed to register debugfs file for CP !\n");
-   }
if (!rdev->me_fw) {
r = r100_cp_init_microcode(rdev);
if (r) {
@@ -2604,178 +2601,6 @@ void r100_set_safe_registers(struct radeon_device *rdev)
}
 }

-/*
- * Debugfs info
- */
-#if defined(CONFIG_DEBUG_FS)
-static int r100_debugfs_rbbm_info(struct seq_file *m, void *data)
-{
-   struct drm_info_node *node = (struct drm_info_node *) m->private;
-   struct drm_device *dev = node->minor->dev;
-   struct radeon_device *rdev = dev->dev_private;
-   uint32_t reg, value;
-   unsigned i;
-
-   seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS));
-   seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C));
-   seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT));
-   for (i = 0; i < 64; i++) {
-   WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100);
-   reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2;
-   WREG32(RADEON_RBBM_CMDFIFO_ADDR, i);
-   value = RREG32(RADEON_RBBM_CMDFIFO_DATA);
-   seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value);
-   }
-   return 0;
-}
-
-static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data)
-{
-   struct drm_info_node *node = (struct drm_info_node *) m->private;
-   struct drm_device *dev = node->minor->dev;
-   struct radeon_device *rdev = dev->dev_private;
-   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
-   uint32_t rdp, wdp;
-   unsigned count, i, j;
-
-   radeon_ring_free_size(rdev, ring);
-   rdp = RREG32(RADEON_CP_RB_RPTR);
-   wdp = RREG32(RADEON_CP_RB_WPTR);
-   count = (rdp + ring->ring_size - wdp) & ring->ptr_mask;
-   seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT));
-   seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp);
-   seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp);
-   seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
-   seq_printf(m, "%u dwords in ring\n", count);
-   for (j = 0; j <= count; j++) {
-   i = (rdp + j) & ring->ptr_mask;
-   seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
-   }
-   return 0;
-}
-
-
-static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data)
-{
-   struct drm_info_node *node = (struct drm_info_node *) m->private;
-   struct drm_device *dev = node->minor->dev;
-   struct radeon_device *rdev = dev->dev_private;
-   uint32_t csq_stat, csq2_stat, tmp;
-   unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr;
-   unsigned i;
-
-   seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT));
-   seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE));
-   csq_stat = RREG32(RADEON_CP_CSQ_STAT);
-   csq2_stat = RREG32(RADEON_CP_CSQ2_STAT);
-   r_rptr = (csq_stat >> 0) & 0x3ff;
-   r_wptr = (csq_stat >> 10) & 0x3ff;
-   ib1_rptr = (csq_stat >> 20) & 0x3ff;
-   ib1_wptr = (csq2_stat >> 0) & 0x3ff;
-   ib2_rptr = (csq2_stat >> 10) & 0x3ff;
-   ib2_wptr = (csq2_stat >> 20) & 0x3ff;
-   seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat);
-   seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat);
-   seq_printf(m, "Ring rptr %u\n", r_rptr);
-   seq_printf(m, "Ring wptr %u\n", r_wptr);
-   seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr);
-   seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr);
-   seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr);
-   seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr);
-   /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms
-* 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */
-   seq_printf(m, "Ring 

Reworking of GPU reset logic + dumping

2012-04-25 Thread j.gli...@gmail.com
Patches also available at:
http://people.freedesktop.org/~glisse/debug/

So it's the Christian series minus all the debugfs related to
ring/ib/mc. The last patch add a new blob dumping facilities
that dump everythings (pm4, relocs table, bo content). It's
just a proof of concept to show what i meant because code
speaks more clearly on this kind of topic.

The blob format we dump could be different i want with a
simple binary dword format:
type, id, size, [data (present if size > 0)]

Note that the benefit (simpler code, less code) of dumping
current debugfs seems to me greater than their usefullness.

Cheers,
Jerome



Reworking of GPU reset logic

2012-04-25 Thread Christian König
On 21.04.2012 16:14, Jerome Glisse wrote:
> 2012/4/21 Christian K?nig:
>> On 20.04.2012 01:47, Jerome Glisse wrote:
>>> 2012/4/19 Christian K?nig:
 This includes mostly fixes for multi ring lockups and GPU resets, but it
 should general improve the behavior of the kernel mode driver in case
 something goes badly wrong.

 On the other hand it completely rewrites the IB pool and semaphore
 handling, so I think there are still a couple of problems in it.

 The first four patches were already send to the list, but the current set
 depends on them so I resend them again.

 Cheers,
 Christian.
>>> I did a quick review, it looks mostly good, but as it's sensitive code
>>> i would like to spend sometime on
>>> it. Probably next week. Note that i had some work on this area too, i
>>> mostly want to drop all the debugfs
>>> related to this and add some new more usefull (basicly something that
>>> allow you to read all the data
>>> needed to replay a locking up ib). I also was looking into Dave reset
>>> thread and your solution of moving
>>> reset in ioctl return path sounds good too but i need to convince my
>>> self that it encompass all possible
>>> case.
>>>
>>> Cheers,
>>> Jerome
>>>
>> After sleeping a night over it I already reworked the patch for improving
>> the SA performance, so please wait at least for v2 before taking a look at
>> it :)
>>
>> Regarding the debugging of lockups I had the following on my "in mind todo"
>> list:
>> 1. Rework the chip specific lockup detection code a bit more and probably
>> clean it up a bit.
>> 2. Make the timeout a module parameter, cause compute task sometimes block a
>> ring for more than 10 seconds.
>> 3. Keep track of the actually RPTR offset a fence is emitted to
>> 3. Keep track of all the BOs a IB is touching.
>> 4. Now if a lockup happens start with the last successfully signaled fence
>> and dump the ring content after that RPTR offset till the first not signaled
>> fence.
>> 5. Then if this fence references to an IB dump it's content and the BOs it
>> is touching.
>> 6. Dump everything on the ring after that fence until you reach the RPTR of
>> the next fence or the WPTR of the ring.
>> 7. If there is a next fence repeat the whole thing at number 5.
>>
>> If I'm not completely wrong that should give you practically every
>> information available, and we probably should put that behind another module
>> option, cause we are going to spam syslog pretty much here. Feel free to
>> add/modify the ideas on this list.
>>
>> Christian.
> What i have is similar, i am assuming only ib trigger lockup, before each ib
> emit to scratch reg ib offset in sa and ib size. For each ib keep bo list. On
> lockup allocate big memory to copy the whole ib and all the bo referenced
> by the ib (i am using my bof format as i already have userspace tools).
>
> Remove all the debugfs file. Just add a new one that gave you the first faulty
> ib. On read of this file kernel free the memory. Kernel should also free the
> memory after a while or better would be to enable the lockup copy only if
> some kernel radeon option is enabled.

Just resent my current patchset to the mailing list, it's not as 
complete as your solution, but seems to be a step into the right 
direction. So please take a look at them.

Being able to generate something like a "GPU crash dump" on lockup 
sounds like something very valuable to me, but I'm not sure if debugfs 
files are the right direction to go. Maybe something more like a module 
parameter containing a directory, and if set we dump all informations 
(including bo content) available in binary form (instead of the current 
human readable form of the debugfs files).

Anyway, the just send patchset solves the problem I'm currently looking 
into, and I'm running a bit out of time (again). So I don't know if I 
can complete that solution

Cheers,
Christian.


[PATCH 12/26] drm/radeon: rename fence_wait_last to fence_wait_empty

2012-04-25 Thread Michel Dänzer
On Mit, 2012-04-25 at 14:46 +0200, Christian K?nig wrote: 
> As discussed with Michel that name better
> describes the behavior of this function.
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Michel D?nzer 


-- 
Earthling Michel D?nzer   |   http://www.amd.com
Libre software enthusiast |  Debian, X and DRI developer


[PATCH 11/26] drm/radeon: return -ENOENT in fence_wait_next v2

2012-04-25 Thread Michel Dänzer
On Mit, 2012-04-25 at 14:46 +0200, Christian K?nig wrote: 
> We should signal the caller that we haven't waited at all.
> 
> v2: only change fence_wait_next not fence_wait_last.
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Michel D?nzer 


-- 
Earthling Michel D?nzer   |   http://www.amd.com
Libre software enthusiast |  Debian, X and DRI developer


Reworking of GPU reset logic

2012-04-25 Thread Christian König
On 23.04.2012 09:40, Michel D?nzer wrote:
> On Sam, 2012-04-21 at 11:42 +0200, Christian K?nig wrote:
>> Regarding the debugging of lockups I had the following on my "in mind
>> todo" list:
>> 1. Rework the chip specific lockup detection code a bit more and
>> probably clean it up a bit.
>> 2. Make the timeout a module parameter, cause compute task sometimes
>> block a ring for more than 10 seconds.
> A better solution for that would be to improve the detection of the GPU
> making progress, also for graphics operations. We should try to reduce
> the timeout rather than making it even larger.

Well, let's call it a more complete solution.

Since making the parameter configurable don't necessary means we are 
going to increase it. I usually set it to zero now, since that disables 
lockup detection at all and enables me to dig into the reason for 
something getting stuck.

Christian.


[PATCH 26/26] drm/radeon: add the ib content and relocs to the ring debugfs file

2012-04-25 Thread Christian König
Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_ring.c |   22 ++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 1c4348c..c563c25 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -481,6 +481,25 @@ void radeon_ring_fini(struct radeon_device *rdev, struct 
radeon_ring *ring)
  */
 #if defined(CONFIG_DEBUG_FS)

+static void radeon_ib_dump(struct seq_file *m, struct radeon_ib *ib)
+{
+   unsigned i;
+
+   seq_printf(m, "\n");
+   seq_printf(m, "\tIB relocs (%d)\n", ib->nrelocs);
+   for (i = 0; i < ib->nrelocs; ++i) {
+   struct radeon_bo *bo = ib->relocs[i].robj;
+   seq_printf(m, "\t%d: %9ld bytes @ 0x%09LX\n", i, 
+  radeon_bo_size(bo), radeon_bo_gpu_offset(bo));
+   }
+   seq_printf(m, "\n");
+   seq_printf(m, "\tIB size %05u dwords\n", ib->length_dw);
+   for (i = 0; i < ib->length_dw; ++i) {
+   seq_printf(m, "\t[%05u]=0x%08X\n", i, ib->ptr[i]);
+   }
+   seq_printf(m, "\n");
+}
+
 static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
 {
struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -522,6 +541,9 @@ static int radeon_debugfs_ring_info(struct seq_file *m, 
void *data)
fence = NULL;
}
for (j = 0; j <= count; j++) {
+   if (fence && fence->emitted_at == i && fence->ib) {
+   radeon_ib_dump(m, fence->ib);
+   }
seq_printf(m, "r[%04d]=0x%08x", i, ring->ring[i]);
if (i == ring->rptr) {
seq_printf(m, " <- RPTR ");
-- 
1.7.5.4



[PATCH 25/26] drm/radeon: keep the cs relocs inside the ib

2012-04-25 Thread Christian König
Free them wenn the ib is freed, another
step to better debugging.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h  |3 +++
 drivers/gpu/drm/radeon/radeon_cs.c   |   14 --
 drivers/gpu/drm/radeon/radeon_ring.c |3 +++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 21b9a75..6070c3e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -576,6 +576,7 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device 
*rdev, int crtc);
 /*
  * CP & rings.
  */
+struct radeon_cs_reloc;

 struct radeon_ib {
struct radeon_sa_bo sa_bo;
@@ -585,6 +586,8 @@ struct radeon_ib {
struct radeon_fence *fence;
unsignedvm_id;
boolis_const_ib;
+   unsignednrelocs;
+   struct radeon_cs_reloc  *relocs;
 };

 struct radeon_ring {
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index c3273b8..a3ce65a 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -313,7 +313,6 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser 
*parser, int error)
}
}
kfree(parser->track);
-   kfree(parser->relocs);
kfree(parser->relocs_ptr);
for (i = 0; i < parser->nchunks; i++) {
kfree(parser->chunks[i].kdata);
@@ -324,7 +323,18 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser 
*parser, int error)
}
kfree(parser->chunks);
kfree(parser->chunks_array);
-   radeon_ib_free(parser->rdev, >ib);
+
+   if (parser->ib) {
+   /* keep the relocs for debugging */
+   parser->ib->nrelocs = parser->nrelocs;
+   parser->ib->relocs = parser->relocs;
+
+   /* even if we locally free it the ib stays
+  alive until it is processed */
+   radeon_ib_free(parser->rdev, >ib);
+   } else {
+   kfree(parser->relocs);
+   }
 }

 static int radeon_cs_ib_chunk(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 992a615..1c4348c 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -97,6 +97,8 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
(*ib)->gpu_addr += (*ib)->sa_bo.offset;
(*ib)->vm_id = 0;
(*ib)->is_const_ib = false;
+   (*ib)->nrelocs = 0;
+   (*ib)->relocs = NULL;

return 0;
 }
@@ -118,6 +120,7 @@ void radeon_ib_free(struct radeon_device *rdev, struct 
radeon_ib **ib)
if (destroy) {
radeon_sa_bo_free(rdev, >sa_bo);
radeon_fence_unref(>fence);
+   kfree(tmp->relocs);
kfree(tmp);
}
 }
-- 
1.7.5.4



[PATCH 24/26] drm/radeon: extend ring debugfs files with fence info

2012-04-25 Thread Christian König
That should aid in debugging multi ring lockups.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |1 +
 drivers/gpu/drm/radeon/radeon_fence.c |1 +
 drivers/gpu/drm/radeon/radeon_ring.c  |   43 -
 3 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index b2d72e2..21b9a75 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -233,6 +233,7 @@ struct radeon_fence {
boolsignaled;
/* RB, DMA, etc. */
int ring;
+   unsignedemitted_at;
struct radeon_semaphore *semaphore;
struct radeon_ib*ib;
 };
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 09e13e3..f8bdef5 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -71,6 +71,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
return 0;
}
fence->seq = atomic_add_return(1, >fence_drv[fence->ring].seq);
+   fence->emitted_at = rdev->ring[fence->ring].wptr;
radeon_fence_ring_emit(rdev, fence->ring, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq);
fence->emitted = true;
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 4d1987d..992a615 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -485,8 +485,12 @@ static int radeon_debugfs_ring_info(struct seq_file *m, 
void *data)
struct radeon_device *rdev = dev->dev_private;
int ridx = *(int*)node->info_ent->data;
struct radeon_ring *ring = >ring[ridx];
+   struct radeon_fence *fence = NULL;
unsigned count, i, j;
+   unsigned long flags;

+   mutex_lock(>mutex);
+   read_lock_irqsave(>fence_lock, flags);
radeon_ring_free_size(rdev, ring);
count = (ring->ring_size / 4) - ring->ring_free_dw;
seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, 
RREG32(ring->wptr_reg));
@@ -496,10 +500,47 @@ static int radeon_debugfs_ring_info(struct seq_file *m, 
void *data)
seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
seq_printf(m, "%u dwords in ring\n", count);
i = ring->rptr;
+   if (!list_empty(>fence_drv[ridx].emitted)) {
+   fence = list_first_entry(>fence_drv[ridx].emitted, 
+struct radeon_fence, list);
+
+   if (fence->emitted_at < ring->rptr && (
+   ring->wptr >= ring->rptr || fence->emitted_at > 
ring->wptr)) {
+
+   /* if first emitted fence is before current
+  read pointer, then print that content also */
+   count = (fence->emitted_at + (ring->ring_size / 4));
+   count -= ring->wptr;
+   count &= ring->ptr_mask;
+   count = (ring->ring_size / 4) - count;
+   i = fence->emitted_at;
+   }
+   } else {
+   fence = NULL;
+   }
for (j = 0; j <= count; j++) {
-   seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
+   seq_printf(m, "r[%04d]=0x%08x", i, ring->ring[i]);
+   if (i == ring->rptr) {
+   seq_printf(m, " <- RPTR ");
+   }
+   if (fence && fence->emitted_at == i) {
+   seq_printf(m, " <- seq 0x%08x", fence->seq);
+   if (fence->semaphore) {
+   seq_printf(m, " sem @ 0x%09Lx ",
+  (long 
long)fence->semaphore->gpu_addr);
+   }
+   if (fence->list.next != >fence_drv[ridx].emitted) 
{
+   fence = list_entry(fence->list.next,
+  struct radeon_fence, list);
+   } else {
+   fence = NULL;
+   }
+   }
+   seq_printf(m, "\n");
i = (i + 1) & ring->ptr_mask;
}
+   read_unlock_irqrestore(>fence_lock, flags);
+   mutex_unlock(>mutex);
return 0;
 }

-- 
1.7.5.4



[PATCH 23/26] drm/radeon: add missing locking to fence debugfs function

2012-04-25 Thread Christian König
Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_fence.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 66e6ee0..09e13e3 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -492,8 +492,10 @@ static int radeon_debugfs_fence_info(struct seq_file *m, 
void *data)
struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_fence *fence;
+   unsigned long irq_flags;
int i;

+   read_lock_irqsave(>fence_lock, irq_flags);
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
if (!rdev->fence_drv[i].initialized)
continue;
@@ -508,6 +510,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, 
void *data)
   fence,  fence->seq);
}
}
+   read_unlock_irqrestore(>fence_lock, irq_flags);
return 0;
 }

-- 
1.7.5.4



[PATCH 22/26] drm/radeon: remove cayman_gpu_is_lockup

2012-04-25 Thread Christian König
Since it is now identical to evergreen_gpu_is_lockup.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/ni.c  |   19 ---
 drivers/gpu/drm/radeon/radeon_asic.c |   12 ++--
 drivers/gpu/drm/radeon/radeon_asic.h |1 -
 3 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 8a9c85d..107b217 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1392,25 +1392,6 @@ int cayman_cp_resume(struct radeon_device *rdev)
return 0;
 }

-bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-   u32 srbm_status;
-   u32 grbm_status;
-   u32 grbm_status_se0, grbm_status_se1;
-
-   srbm_status = RREG32(SRBM_STATUS);
-   grbm_status = RREG32(GRBM_STATUS);
-   grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
-   grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
-   if (!(grbm_status & GUI_ACTIVE)) {
-   radeon_ring_lockup_update(ring);
-   return false;
-   }
-   /* force CP activities */
-   radeon_ring_force_activity(rdev, ring);
-   return radeon_ring_test_lockup(rdev, ring);
-}
-
 static int cayman_gpu_soft_reset(struct radeon_device *rdev)
 {
struct evergreen_mc_save save;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index 5e5694e..f533df5 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1339,7 +1339,7 @@ static struct radeon_asic cayman_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP1_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1349,7 +1349,7 @@ static struct radeon_asic cayman_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP2_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1359,7 +1359,7 @@ static struct radeon_asic cayman_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -1433,7 +1433,7 @@ static struct radeon_asic trinity_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP1_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1443,7 +1443,7 @@ static struct radeon_asic trinity_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
},
[CAYMAN_RING_TYPE_CP2_INDEX] = {
.ib_execute = _ring_ib_execute,
@@ -1453,7 +1453,7 @@ static struct radeon_asic trinity_asic = {
.cs_parse = _cs_parse,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index 1e128e0..7830931 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -437,7 +437,6 @@ int cayman_init(struct radeon_device *rdev);
 void cayman_fini(struct radeon_device *rdev);
 int cayman_suspend(struct radeon_device *rdev);
 int cayman_resume(struct radeon_device *rdev);
-bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
 int cayman_asic_reset(struct radeon_device *rdev);
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int cayman_vm_init(struct radeon_device *rdev);
-- 
1.7.5.4



[PATCH 21/26] drm/radeon: remove r300_gpu_is_lockup

2012-04-25 Thread Christian König
Since it is now identical to r100_gpu_is_lockup.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/r300.c|   14 --
 drivers/gpu/drm/radeon/radeon_asic.c |   16 
 drivers/gpu/drm/radeon/radeon_asic.h |1 -
 3 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 04ec269..6419a59 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -377,20 +377,6 @@ void r300_gpu_init(struct radeon_device *rdev)
 rdev->num_gb_pipes, rdev->num_z_pipes);
 }

-bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-   u32 rbbm_status;
-
-   rbbm_status = RREG32(R_000E40_RBBM_STATUS);
-   if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
-   radeon_ring_lockup_update(ring);
-   return false;
-   }
-   /* force CP activities */
-   radeon_ring_force_activity(rdev, ring);
-   return radeon_ring_test_lockup(rdev, ring);
-}
-
 int r300_asic_reset(struct radeon_device *rdev)
 {
struct r100_mc_save save;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index 958b9ea..5e5694e 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -299,7 +299,7 @@ static struct radeon_asic r300_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -373,7 +373,7 @@ static struct radeon_asic r300_asic_pcie = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -447,7 +447,7 @@ static struct radeon_asic r420_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -521,7 +521,7 @@ static struct radeon_asic rs400_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -595,7 +595,7 @@ static struct radeon_asic rs600_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -669,7 +669,7 @@ static struct radeon_asic rs690_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -743,7 +743,7 @@ static struct radeon_asic rv515_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -817,7 +817,7 @@ static struct radeon_asic r520_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
-   .is_lockup = _gpu_is_lockup,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h 
b/drivers/gpu/drm/radeon/radeon_asic.h
index b0941f9..1e128e0 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -154,7 +154,6 @@ extern int r300_init(struct radeon_device *rdev);
 extern void r300_fini(struct radeon_device *rdev);
 extern int r300_suspend(struct radeon_device *rdev);
 extern int r300_resume(struct radeon_device *rdev);
-extern bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring 
*cp);
 extern int r300_asic_reset(struct radeon_device *rdev);
 extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring 
*ring);
 extern void r300_fence_ring_emit(struct radeon_device *rdev,
-- 
1.7.5.4



[PATCH 20/26] drm/radeon: make forcing ring activity a common function

2012-04-25 Thread Christian König
Nothing chipset or ring specific with it,
so also move it to radon_ring.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/evergreen.c   |   10 +-
 drivers/gpu/drm/radeon/ni.c  |   11 +--
 drivers/gpu/drm/radeon/r100.c|   10 +-
 drivers/gpu/drm/radeon/r300.c|   10 +-
 drivers/gpu/drm/radeon/r600.c|   10 +-
 drivers/gpu/drm/radeon/radeon.h  |1 +
 drivers/gpu/drm/radeon/radeon_ring.c |   16 
 drivers/gpu/drm/radeon/si.c  |   11 +--
 8 files changed, 23 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index e304858..7e7ac3d 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2424,7 +2424,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   int r;

srbm_status = RREG32(SRBM_STATUS);
grbm_status = RREG32(GRBM_STATUS);
@@ -2435,14 +2434,7 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   ring->rptr = RREG32(CP_RB_RPTR);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 4327b32..8a9c85d 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1397,7 +1397,6 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   int r;

srbm_status = RREG32(SRBM_STATUS);
grbm_status = RREG32(GRBM_STATUS);
@@ -1408,15 +1407,7 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   /* XXX deal with CP0,1,2 */
-   ring->rptr = RREG32(ring->rptr_reg);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 20bf498..217cdc2 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2162,7 +2162,6 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
 bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
u32 rbbm_status;
-   int r;

rbbm_status = RREG32(R_000E40_RBBM_STATUS);
if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
@@ -2170,14 +2169,7 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   ring->rptr = RREG32(ring->rptr_reg);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index e207664..04ec269 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -380,7 +380,6 @@ void r300_gpu_init(struct radeon_device *rdev)
 bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
u32 rbbm_status;
-   int r;

rbbm_status = RREG32(R_000E40_RBBM_STATUS);
if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
@@ -388,14 +387,7 @@ bool r300_gpu_is_lockup(struct radeon_device *rdev, struct 
radeon_ring *ring)
return false;
}
/* force CP activities */
-   r = radeon_ring_lock(rdev, ring, 2);
-   if (!r) {
-   /* PACKET2 NOP */
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_write(ring, 0x8000);
-   radeon_ring_unlock_commit(rdev, ring);
-   }
-   ring->rptr = RREG32(RADEON_CP_RB_RPTR);
+   radeon_ring_force_activity(rdev, ring);
return radeon_ring_test_lockup(rdev, ring);
 }

diff --git a/drivers/gpu/drm/radeon/r600.c 

[PATCH 19/26] drm/radeon: unlock the ring mutex while waiting for the next fence

2012-04-25 Thread Christian König
Fixing just another deadlock problem with gpu reset tests.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_ring.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 8add827..953592e 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -282,7 +282,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct 
radeon_ring *ring, unsi
if (ndw < ring->ring_free_dw) {
break;
}
+   mutex_unlock(>mutex);
r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring));
+   mutex_lock(>mutex);
if (r)
return r;
}
-- 
1.7.5.4



[PATCH 18/26] drm/radeon: make lockup timeout a module param

2012-04-25 Thread Christian König
Don't hard code the 10 seconds timeout. Compute jobs
can run much longer.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h  |1 +
 drivers/gpu/drm/radeon/radeon_drv.c  |4 
 drivers/gpu/drm/radeon/radeon_ring.c |2 +-
 3 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index ef71513..40976a4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -94,6 +94,7 @@ extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
 extern int radeon_pcie_gen2;
 extern int radeon_msi;
+extern int radeon_lockup_timeout;

 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index ef7bb3f..e62e56a 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -128,6 +128,7 @@ int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
 int radeon_msi = -1;
+int radeon_lockup_timeout = 1;

 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -177,6 +178,9 @@ module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
 MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(msi, radeon_msi, int, 0444);

+MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 1 = 10 
seconds, 0 = disable)");
+module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
drm_radeon_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 5fd683f..8add827 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -377,7 +377,7 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
return false;
}
elapsed = jiffies_to_msecs(cjiffies - ring->last_activity);
-   if (elapsed >= 1) {
+   if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) {
dev_err(rdev->dev, "GPU lockup CP stall for more than 
%lumsec\n", elapsed);
return true;
}
-- 
1.7.5.4



[PATCH 17/26] drm/radeon: move lockup detection code into radeon_ring.c

2012-04-25 Thread Christian König
It isn't chipset specific, so it makes no sense
to have that inside r100.c.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/evergreen.c   |5 +--
 drivers/gpu/drm/radeon/ni.c  |5 +--
 drivers/gpu/drm/radeon/r100.c|   57 +
 drivers/gpu/drm/radeon/r300.c|4 +-
 drivers/gpu/drm/radeon/r600.c|   10 +-
 drivers/gpu/drm/radeon/radeon.h  |   16 ++---
 drivers/gpu/drm/radeon/radeon_asic.h |5 ---
 drivers/gpu/drm/radeon/radeon_ring.c |   53 +++
 drivers/gpu/drm/radeon/si.c  |5 +--
 9 files changed, 69 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index 26848d6..e304858 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2424,7 +2424,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   struct r100_gpu_lockup *lockup = >config.evergreen.lockup;
int r;

srbm_status = RREG32(SRBM_STATUS);
@@ -2432,7 +2431,7 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
if (!(grbm_status & GUI_ACTIVE)) {
-   r100_gpu_lockup_update(lockup, ring);
+   radeon_ring_lockup_update(ring);
return false;
}
/* force CP activities */
@@ -2444,7 +2443,7 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *rin
radeon_ring_unlock_commit(rdev, ring);
}
ring->rptr = RREG32(CP_RB_RPTR);
-   return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+   return radeon_ring_test_lockup(rdev, ring);
 }

 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index c0b0956..4327b32 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1397,7 +1397,6 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
u32 srbm_status;
u32 grbm_status;
u32 grbm_status_se0, grbm_status_se1;
-   struct r100_gpu_lockup *lockup = >config.cayman.lockup;
int r;

srbm_status = RREG32(SRBM_STATUS);
@@ -1405,7 +1404,7 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
if (!(grbm_status & GUI_ACTIVE)) {
-   r100_gpu_lockup_update(lockup, ring);
+   radeon_ring_lockup_update(ring);
return false;
}
/* force CP activities */
@@ -1418,7 +1417,7 @@ bool cayman_gpu_is_lockup(struct radeon_device *rdev, 
struct radeon_ring *ring)
}
/* XXX deal with CP0,1,2 */
ring->rptr = RREG32(ring->rptr_reg);
-   return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+   return radeon_ring_test_lockup(rdev, ring);
 }

 static int cayman_gpu_soft_reset(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 62f9dab..20bf498 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2159,59 +2159,6 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
return -1;
 }

-void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_ring 
*ring)
-{
-   lockup->last_cp_rptr = ring->rptr;
-   lockup->last_jiffies = jiffies;
-}
-
-/**
- * r100_gpu_cp_is_lockup() - check if CP is lockup by recording information
- * @rdev:  radeon device structure
- * @lockup:r100_gpu_lockup structure holding CP lockup tracking 
informations
- * @cp:radeon_cp structure holding CP information
- *
- * We don't need to initialize the lockup tracking information as we will 
either
- * have CP rptr to a different value of jiffies wrap around which will force
- * initialization of the lockup tracking informations.
- *
- * A possible false positivie is if we get call after while and last_cp_rptr ==
- * the current CP rptr, even if it's unlikely it might happen. To avoid this
- * if the elapsed time since last call is bigger than 2 second than we return
- * false and update the tracking information. Due to this the caller must call
- * r100_gpu_cp_is_lockup several time in less than 2sec for lockup to be 
reported
- * the fencing code should be cautious about that.
- *
- * Caller should write to the ring to force CP to do something so we don't get
- * false positive when CP is just gived nothing to do.
- *
- **/
-bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup 
*lockup, struct radeon_ring *ring)
-{
-   unsigned long 

[PATCH 16/26] drm/radeon: remove recursive mutex implementation

2012-04-25 Thread Christian König
Not needed anymore.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|   44 +---
 drivers/gpu/drm/radeon/radeon_cs.c |   10 +++---
 drivers/gpu/drm/radeon/radeon_device.c |2 +-
 drivers/gpu/drm/radeon/radeon_gart.c   |   16 ++--
 drivers/gpu/drm/radeon/radeon_gem.c|4 +-
 5 files changed, 17 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 79a38da..43d0465 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -155,48 +155,6 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t 
*bios, int offset, int len)
 #endif
 bool radeon_get_bios(struct radeon_device *rdev);

-
-/*
- * Mutex which allows recursive locking from the same process.
- */
-struct radeon_mutex {
-   struct mutexmutex;
-   struct task_struct  *owner;
-   int level;
-};
-
-static inline void radeon_mutex_init(struct radeon_mutex *mutex)
-{
-   mutex_init(>mutex);
-   mutex->owner = NULL;
-   mutex->level = 0;
-}
-
-static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
-{
-   if (mutex_trylock(>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->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);
-}
-
-
 /*
  * Dummy page
  */
@@ -1506,7 +1464,7 @@ struct radeon_device {
struct radeon_gem   gem;
struct radeon_pmpm;
uint32_tbios_scratch[RADEON_BIOS_NUM_SCRATCH];
-   struct radeon_mutex cs_mutex;
+   struct mutexcs_mutex;
struct radeon_wbwb;
struct radeon_dummy_pagedummy_page;
boolshutdown;
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 02eee4b..c3273b8 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -512,9 +512,9 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
struct radeon_cs_parser parser;
int r;

-   radeon_mutex_lock(>cs_mutex);
+   mutex_lock(>cs_mutex);
if (!rdev->accel_working) {
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return -EBUSY;
}
/* initialize parser */
@@ -528,7 +528,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
DRM_ERROR("Failed to initialize parser !\n");
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return r;
}
r = radeon_cs_parser_relocs();
@@ -537,7 +537,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
DRM_ERROR("Failed to parse relocation %d!\n", r);
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return r;
}
r = radeon_cs_ib_chunk(rdev, );
@@ -551,7 +551,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
 out:
radeon_cs_parser_fini(, r);
r = radeon_cs_handle_lockup(rdev, r);
-   radeon_mutex_unlock(>cs_mutex);
+   mutex_unlock(>cs_mutex);
return r;
 }

diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 8a4a210..94f8561 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -722,7 +722,7 @@ int radeon_device_init(struct radeon_device *rdev,

/* mutex initialization are all done here so we
 * can recall function without having locking issues */
-   radeon_mutex_init(>cs_mutex);
+   mutex_init(>cs_mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(>ring[i].mutex);
mutex_init(>dc_hw_i2c_mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c 
b/drivers/gpu/drm/radeon/radeon_gart.c
index 220dbb8..b4a4982 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -356,13 +356,13 @@ int radeon_vm_manager_suspend(struct radeon_device *rdev)
 {
struct 

[PATCH 15/26] drm/radeon: rework recursive gpu reset handling

2012-04-25 Thread Christian König
Instead of all this humpy pumpy with recursive
mutex (which also fixes only halve of the problem)
move the actual gpu reset out of the fence code,
return -EDEADLK and then reset the gpu in the
calling ioctl function.

v2: Split removal of radeon_mutex into separate patch.
Return -EAGAIN if reset is successful.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_cs.c |   13 +
 drivers/gpu/drm/radeon/radeon_device.c |5 -
 drivers/gpu/drm/radeon/radeon_fence.c  |   10 +++---
 drivers/gpu/drm/radeon/radeon_gem.c|   16 
 4 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 24fb001..02eee4b 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -496,6 +496,16 @@ out:
return r;
 }

+static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r)
+{
+   if (r == -EDEADLK) {
+   r = radeon_gpu_reset(rdev);
+   if (!r)
+   r = -EAGAIN;
+   }
+   return r;
+}
+
 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
struct radeon_device *rdev = dev->dev_private;
@@ -517,6 +527,7 @@ 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(, r);
+   r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(>cs_mutex);
return r;
}
@@ -525,6 +536,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(, r);
+   r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(>cs_mutex);
return r;
}
@@ -538,6 +550,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
}
 out:
radeon_cs_parser_fini(, r);
+   r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(>cs_mutex);
return r;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 853e1cb..8a4a210 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -983,9 +983,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
int r;
int resched;

-   /* Prevent CS ioctl from interfering */
-   radeon_mutex_lock(>cs_mutex);
-
radeon_save_bios_scratch_regs(rdev);
/* block TTM */
resched = ttm_bo_lock_delayed_workqueue(>mman.bdev);
@@ -1000,8 +997,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
ttm_bo_unlock_delayed_workqueue(>mman.bdev, resched);
}

-   radeon_mutex_unlock(>cs_mutex);
-
if (r) {
/* bad news, how to tell it to userspace ? */
dev_info(rdev->dev, "GPU reset failed\n");
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 5bb1bc4d..66e6ee0 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -267,6 +267,8 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
/* change sequence value on all rings, so nobody else 
things there is a lockup */
for (i = 0; i < RADEON_NUM_RINGS; ++i)
rdev->fence_drv[i].last_seq -= 0x1;
+
+   rdev->fence_drv[fence->ring].last_activity = jiffies;
write_unlock_irqrestore(>fence_lock, irq_flags);

if (radeon_ring_is_lockup(rdev, fence->ring, 
>ring[fence->ring])) {
@@ -277,13 +279,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool 
intr)

/* mark the ring as not ready any more */
rdev->ring[fence->ring].ready = false;
-   r = radeon_gpu_reset(rdev);
-   if (r)
-   return r;
-
-   write_lock_irqsave(>fence_lock, 
irq_flags);
-   rdev->fence_drv[fence->ring].last_activity = 
jiffies;
-   write_unlock_irqrestore(>fence_lock, 
irq_flags);
+   return -EDEADLK;
}
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index c7008b5..e15cb1f 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -154,6 +154,17 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
radeon_bo_unreserve(rbo);
 }

+static int 

[PATCH 14/26] drm/radeon: fix a bug with the ring syncing code

2012-04-25 Thread Christian König
Rings need to lock in order, otherwise
the ring subsystem can deadlock.

v2: fix error handling and number of locked doublewords.
v3: stop creating unneeded semaphores.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |4 ++
 drivers/gpu/drm/radeon/radeon_cs.c|   35 ++
 drivers/gpu/drm/radeon/radeon_semaphore.c |   56 +
 drivers/gpu/drm/radeon/radeon_ttm.c   |   46 ++-
 4 files changed, 92 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index b946c96..79a38da 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -442,6 +442,10 @@ void radeon_semaphore_emit_signal(struct radeon_device 
*rdev, int ring,
  struct radeon_semaphore *semaphore);
 void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
struct radeon_semaphore *semaphore);
+int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+   struct radeon_semaphore *semaphore,
+   bool sync_to[RADEON_NUM_RINGS],
+   int dst_ring);
 void radeon_semaphore_free(struct radeon_device *rdev,
   struct radeon_semaphore *semaphore);

diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index e7b0b5d..24fb001 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -118,6 +118,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, 
u32 ring, s32 priority
 static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
 {
bool sync_to_ring[RADEON_NUM_RINGS] = { };
+   bool need_sync = false;
int i, r;

for (i = 0; i < p->nrelocs; i++) {
@@ -126,36 +127,24 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser 
*p)

if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) {
struct radeon_fence *fence = 
p->relocs[i].robj->tbo.sync_obj;
-   if (!radeon_fence_signaled(fence)) {
+   if (fence->ring != p->ring && 
!radeon_fence_signaled(fence)) {
sync_to_ring[fence->ring] = true;
+   need_sync = true;
}
}
}

-   for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-   /* no need to sync to our own or unused rings */
-   if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready)
-   continue;
-
-   if (!p->ib->fence->semaphore) {
-   r = radeon_semaphore_create(p->rdev, 
>ib->fence->semaphore);
-   if (r)
-   return r;
-   }
-
-   r = radeon_ring_lock(p->rdev, >rdev->ring[i], 3);
-   if (r)
-   return r;
-   radeon_semaphore_emit_signal(p->rdev, i, 
p->ib->fence->semaphore);
-   radeon_ring_unlock_commit(p->rdev, >rdev->ring[i]);
+   if (!need_sync) {
+   return 0;
+   }

-   r = radeon_ring_lock(p->rdev, >rdev->ring[p->ring], 3);
-   if (r)
-   return r;
-   radeon_semaphore_emit_wait(p->rdev, p->ring, 
p->ib->fence->semaphore);
-   radeon_ring_unlock_commit(p->rdev, >rdev->ring[p->ring]);
+   r = radeon_semaphore_create(p->rdev, >ib->fence->semaphore);
+   if (r) {
+   return r;
}
-   return 0;
+
+   return radeon_semaphore_sync_rings(p->rdev, p->ib->fence->semaphore,
+  sync_to_ring, p->ring);
 }

 int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c 
b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 3041776..644b1e3 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -75,6 +75,62 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, 
int ring,
radeon_semaphore_ring_emit(rdev, ring, >ring[ring], semaphore, 
true);
 }

+int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+   struct radeon_semaphore *semaphore,
+   bool sync_to[RADEON_NUM_RINGS],
+   int dst_ring)
+{
+   int i, r;
+
+   for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+   unsigned num_ops = i == dst_ring ? RADEON_NUM_RINGS : 1;
+
+   /* don't lock unused rings */
+   if (!sync_to[i] && i != dst_ring)
+   continue;
+
+   /* prevent GPU deadlocks */
+   if (!rdev->ring[i].ready) {
+   dev_err(rdev->dev, "Trying to sync to a disabled 
ring!");
+  

[PATCH 13/26] drm/radeon: rip out the ib pool

2012-04-25 Thread Christian König
It isn't necessary any more and the suballocator
seems to perform even better.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |   22 +--
 drivers/gpu/drm/radeon/radeon_device.c|1 -
 drivers/gpu/drm/radeon/radeon_fence.c |   44 +-
 drivers/gpu/drm/radeon/radeon_gart.c  |   12 +-
 drivers/gpu/drm/radeon/radeon_ring.c  |  240 
 drivers/gpu/drm/radeon/radeon_semaphore.c |6 +-
 6 files changed, 123 insertions(+), 202 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 944db04..b946c96 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -249,6 +249,8 @@ extern void evergreen_tiling_fields(unsigned tiling_flags, 
unsigned *bankw,
 /*
  * Fences.
  */
+struct radeon_ib;
+
 struct radeon_fence_driver {
uint32_tscratch_reg;
uint64_tgpu_addr;
@@ -259,7 +261,6 @@ struct radeon_fence_driver {
wait_queue_head_t   queue;
struct list_headcreated;
struct list_heademitted;
-   struct list_headsignaled;
boolinitialized;
 };

@@ -274,6 +275,7 @@ struct radeon_fence {
/* RB, DMA, etc. */
int ring;
struct radeon_semaphore *semaphore;
+   struct radeon_ib*ib;
 };

 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
@@ -289,6 +291,7 @@ int radeon_fence_wait_empty(struct radeon_device *rdev, int 
ring);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
+bool radeon_fence_set_associated_ib(struct radeon_fence *fence, struct 
radeon_ib *ib);

 /*
  * Tiling registers
@@ -612,7 +615,6 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device 
*rdev, int crtc);

 struct radeon_ib {
struct radeon_sa_bo sa_bo;
-   unsignedidx;
uint32_tlength_dw;
uint64_tgpu_addr;
uint32_t*ptr;
@@ -621,18 +623,6 @@ struct radeon_ib {
boolis_const_ib;
 };

-/*
- * locking -
- * mutex protects scheduled_ibs, ready, alloc_bm
- */
-struct radeon_ib_pool {
-   struct radeon_mutex mutex;
-   struct radeon_sa_managersa_manager;
-   struct radeon_ibibs[RADEON_IB_POOL_SIZE];
-   boolready;
-   unsignedhead_id;
-};
-
 struct radeon_ring {
struct radeon_bo*ring_obj;
volatile uint32_t   *ring;
@@ -773,7 +763,6 @@ struct si_rlc {
 int radeon_ib_get(struct radeon_device *rdev, int ring,
  struct radeon_ib **ib, unsigned size);
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
-bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
@@ -1506,7 +1495,8 @@ struct radeon_device {
rwlock_tfence_lock;
struct radeon_fence_driver  fence_drv[RADEON_NUM_RINGS];
struct radeon_ring  ring[RADEON_NUM_RINGS];
-   struct radeon_ib_pool   ib_pool;
+   boolib_pool_ready;
+   struct radeon_sa_managersa_manager;
struct radeon_irq   irq;
struct radeon_asic  *asic;
struct radeon_gem   gem;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 5966b35..853e1cb 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -723,7 +723,6 @@ int radeon_device_init(struct radeon_device *rdev,
/* mutex initialization are all done here so we
 * can recall function without having locking issues */
radeon_mutex_init(>cs_mutex);
-   radeon_mutex_init(>ib_pool.mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(>ring[i].mutex);
mutex_init(>dc_hw_i2c_mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 2d13843..5bb1bc4d 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -83,7 +83,8 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
return 0;
 }

-static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring)
+static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring,
+struct list_head 

[PATCH 12/26] drm/radeon: rename fence_wait_last to fence_wait_empty

2012-04-25 Thread Christian König
As discussed with Michel that name better
describes the behavior of this function.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|2 +-
 drivers/gpu/drm/radeon/radeon_device.c |2 +-
 drivers/gpu/drm/radeon/radeon_fence.c  |4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 9857c62..944db04 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -285,7 +285,7 @@ void radeon_fence_process(struct radeon_device *rdev, int 
ring);
 bool radeon_fence_signaled(struct radeon_fence *fence);
 int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
 int radeon_fence_wait_next(struct radeon_device *rdev, int ring);
-int radeon_fence_wait_last(struct radeon_device *rdev, int ring);
+int radeon_fence_wait_empty(struct radeon_device *rdev, int ring);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 8c49990..5966b35 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -913,7 +913,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t 
state)
radeon_bo_evict_vram(rdev);
/* wait for gpu to finish processing current batch */
for (i = 0; i < RADEON_NUM_RINGS; i++)
-   radeon_fence_wait_last(rdev, i);
+   radeon_fence_wait_empty(rdev, i);

radeon_save_bios_scratch_regs(rdev);

diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 2fbbc34..2d13843 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -297,7 +297,7 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int 
ring)
return r;
 }

-int radeon_fence_wait_last(struct radeon_device *rdev, int ring)
+int radeon_fence_wait_empty(struct radeon_device *rdev, int ring)
 {
unsigned long irq_flags;
struct radeon_fence *fence;
@@ -442,7 +442,7 @@ void radeon_fence_driver_fini(struct radeon_device *rdev)
for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
if (!rdev->fence_drv[ring].initialized)
continue;
-   radeon_fence_wait_last(rdev, ring);
+   radeon_fence_wait_empty(rdev, ring);
wake_up_all(>fence_drv[ring].queue);
write_lock_irqsave(>fence_lock, irq_flags);
radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
-- 
1.7.5.4



[PATCH 11/26] drm/radeon: return -ENOENT in fence_wait_next v2

2012-04-25 Thread Christian König
We should signal the caller that we haven't waited at all.

v2: only change fence_wait_next not fence_wait_last.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_fence.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 1a9765a..2fbbc34 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -286,7 +286,7 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int 
ring)
}
if (list_empty(>fence_drv[ring].emitted)) {
write_unlock_irqrestore(>fence_lock, irq_flags);
-   return 0;
+   return -ENOENT;
}
fence = list_entry(rdev->fence_drv[ring].emitted.next,
   struct radeon_fence, list);
-- 
1.7.5.4



[PATCH 10/26] drm/radeon: simplify semaphore handling

2012-04-25 Thread Christian König
Directly use the suballocator to get small chunks
of memory. It's equally fast and doesn't crash when
we encounter a GPU reset.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/evergreen.c|1 -
 drivers/gpu/drm/radeon/ni.c   |1 -
 drivers/gpu/drm/radeon/r600.c |1 -
 drivers/gpu/drm/radeon/radeon.h   |   29 +--
 drivers/gpu/drm/radeon/radeon_device.c|2 -
 drivers/gpu/drm/radeon/radeon_semaphore.c |  137 +
 drivers/gpu/drm/radeon/rv770.c|1 -
 drivers/gpu/drm/radeon/si.c   |1 -
 8 files changed, 26 insertions(+), 147 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index 8b7a01b..26848d6 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3559,7 +3559,6 @@ void evergreen_fini(struct radeon_device *rdev)
evergreen_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
-   radeon_semaphore_driver_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_agp_fini(rdev);
radeon_bo_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 0146428..c0b0956 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1773,7 +1773,6 @@ void cayman_fini(struct radeon_device *rdev)
cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
-   radeon_semaphore_driver_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index db9415a..659a09c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2672,7 +2672,6 @@ void r600_fini(struct radeon_device *rdev)
r600_vram_scratch_fini(rdev);
radeon_agp_fini(rdev);
radeon_gem_fini(rdev);
-   radeon_semaphore_driver_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e71dc67..9857c62 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -427,34 +427,12 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
 /*
  * Semaphores.
  */
-struct radeon_ring;
-
-#defineRADEON_SEMAPHORE_BO_SIZE256
-
-struct radeon_semaphore_driver {
-   rwlock_tlock;
-   struct list_headbo;
-};
-
-struct radeon_semaphore_bo;
-
-/* everything here is constant */
 struct radeon_semaphore {
-   struct list_headlist;
-   uint64_tgpu_addr;
-   uint32_t*cpu_ptr;
-   struct radeon_semaphore_bo  *bo;
-};
-
-struct radeon_semaphore_bo {
-   struct list_headlist;
-   struct radeon_ib*ib;
-   struct list_headfree;
-   struct radeon_semaphore semaphores[RADEON_SEMAPHORE_BO_SIZE/8];
-   unsignednused;
+   struct radeon_sa_bo sa_bo;
+   signed  waiters;
+   uint64_tgpu_addr;
 };

-void radeon_semaphore_driver_fini(struct radeon_device *rdev);
 int radeon_semaphore_create(struct radeon_device *rdev,
struct radeon_semaphore **semaphore);
 void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
@@ -1527,7 +1505,6 @@ struct radeon_device {
struct radeon_mman  mman;
rwlock_tfence_lock;
struct radeon_fence_driver  fence_drv[RADEON_NUM_RINGS];
-   struct radeon_semaphore_driver  semaphore_drv;
struct radeon_ring  ring[RADEON_NUM_RINGS];
struct radeon_ib_pool   ib_pool;
struct radeon_irq   irq;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index dedb398..8c49990 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -733,11 +733,9 @@ int radeon_device_init(struct radeon_device *rdev,
mutex_init(>pm.mutex);
mutex_init(>vram_mutex);
rwlock_init(>fence_lock);
-   rwlock_init(>semaphore_drv.lock);
INIT_LIST_HEAD(>gem.objects);
init_waitqueue_head(>irq.vblank_queue);
init_waitqueue_head(>irq.idle_queue);
-   INIT_LIST_HEAD(>semaphore_drv.bo);
/* initialize vm here */
rdev->vm_manager.use_bitmap = 1;
rdev->vm_manager.max_pfn = 1 << 20;
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c 
b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 61dd4e3..a8ad61a 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ 

[PATCH 09/26] drm/radeon: add biggest hole tracking and wakequeue to the sa v3

2012-04-25 Thread Christian König
With that in place clients are automatically blocking
until their memory request can be handled.

v2: block only if the memory request can't be satisfied
in the first try, the first version actually lacked
a night of sleep.

v3: make blocking optional, update comments and fix
another bug with biggest hole tracking.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|5 +-
 drivers/gpu/drm/radeon/radeon_gart.c   |2 +-
 drivers/gpu/drm/radeon/radeon_object.h |2 +-
 drivers/gpu/drm/radeon/radeon_ring.c   |   20 ++--
 drivers/gpu/drm/radeon/radeon_sa.c |  211 +++-
 5 files changed, 165 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 99b188a..e71dc67 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -381,17 +381,16 @@ struct radeon_bo_list {
  * alignment).
  */
 struct radeon_sa_manager {
-   spinlock_t  lock;
+   wait_queue_head_t   queue;
struct radeon_bo*bo;
struct list_headsa_bo;
unsignedsize;
+   struct list_head*biggest_hole;
uint64_tgpu_addr;
void*cpu_ptr;
uint32_tdomain;
 };

-struct radeon_sa_bo;
-
 /* sub-allocation buffer */
 struct radeon_sa_bo {
struct list_headlist;
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c 
b/drivers/gpu/drm/radeon/radeon_gart.c
index c58a036..7af4ff9 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -395,7 +395,7 @@ int radeon_vm_bind(struct radeon_device *rdev, struct 
radeon_vm *vm)
 retry:
r = radeon_sa_bo_new(rdev, >vm_manager.sa_manager, >sa_bo,
 RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8),
-RADEON_GPU_PAGE_SIZE);
+RADEON_GPU_PAGE_SIZE, false);
if (r) {
if (list_empty(>vm_manager.lru_vm)) {
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_object.h 
b/drivers/gpu/drm/radeon/radeon_object.h
index d9b9333..85f33d9 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -158,7 +158,7 @@ extern int radeon_sa_bo_manager_suspend(struct 
radeon_device *rdev,
 extern int radeon_sa_bo_new(struct radeon_device *rdev,
struct radeon_sa_manager *sa_manager,
struct radeon_sa_bo *sa_bo,
-   unsigned size, unsigned align);
+   unsigned size, unsigned align, bool block);
 extern void radeon_sa_bo_free(struct radeon_device *rdev,
  struct radeon_sa_bo *sa_bo);
 #if defined(CONFIG_DEBUG_FS)
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 1d9bce9..ccee74f 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -124,7 +124,7 @@ retry:
if (rdev->ib_pool.ibs[idx].fence == NULL) {
r = radeon_sa_bo_new(rdev, >ib_pool.sa_manager,
 >ib_pool.ibs[idx].sa_bo,
-size, 256);
+size, 256, false);
if (!r) {
*ib = >ib_pool.ibs[idx];
(*ib)->ptr = rdev->ib_pool.sa_manager.cpu_ptr;
@@ -205,10 +205,16 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct 
radeon_ib *ib)

 int radeon_ib_pool_init(struct radeon_device *rdev)
 {
-   struct radeon_sa_manager tmp;
int i, r;

-   r = radeon_sa_bo_manager_init(rdev, ,
+   radeon_mutex_lock(>ib_pool.mutex);
+   if (rdev->ib_pool.ready) {
+   return 0;
+   }
+   rdev->ib_pool.ready = true;
+   radeon_mutex_unlock(>ib_pool.mutex);
+
+   r = radeon_sa_bo_manager_init(rdev, >ib_pool.sa_manager,
  RADEON_IB_POOL_SIZE*64*1024,
  RADEON_GEM_DOMAIN_GTT);
if (r) {
@@ -216,14 +222,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
}

radeon_mutex_lock(>ib_pool.mutex);
-   if (rdev->ib_pool.ready) {
-   radeon_mutex_unlock(>ib_pool.mutex);
-   radeon_sa_bo_manager_fini(rdev, );
-   return 0;
-   }
-
-   rdev->ib_pool.sa_manager = tmp;
-   INIT_LIST_HEAD(>ib_pool.sa_manager.sa_bo);
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
rdev->ib_pool.ibs[i].fence = NULL;
rdev->ib_pool.ibs[i].idx = i;
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 013a787..92ab7b4 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ 

[PATCH 08/26] drm/radeon: add sub allocator debugfs file

2012-04-25 Thread Christian König
Dumping the current allocations.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_object.h |5 +
 drivers/gpu/drm/radeon/radeon_ring.c   |   22 ++
 drivers/gpu/drm/radeon/radeon_sa.c |   15 +++
 3 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_object.h 
b/drivers/gpu/drm/radeon/radeon_object.h
index f9104be..d9b9333 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -161,5 +161,10 @@ extern int radeon_sa_bo_new(struct radeon_device *rdev,
unsigned size, unsigned align);
 extern void radeon_sa_bo_free(struct radeon_device *rdev,
  struct radeon_sa_bo *sa_bo);
+#if defined(CONFIG_DEBUG_FS)
+extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
+struct seq_file *m);
+#endif
+

 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index 1b020ef..1d9bce9 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -529,6 +529,23 @@ static int radeon_debugfs_ib_info(struct seq_file *m, void 
*data)
 static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
 static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
 static unsigned radeon_debugfs_ib_idx[RADEON_IB_POOL_SIZE];
+
+static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
+{
+   struct drm_info_node *node = (struct drm_info_node *) m->private;
+   struct drm_device *dev = node->minor->dev;
+   struct radeon_device *rdev = dev->dev_private;
+
+   radeon_sa_bo_dump_debug_info(>ib_pool.sa_manager, m);
+
+   return 0;
+
+}
+
+static struct drm_info_list radeon_debugfs_sa_list[] = {
+{"radeon_sa_info", _debugfs_sa_info, 0, NULL},
+};
+
 #endif

 int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring 
*ring)
@@ -555,6 +572,11 @@ int radeon_debugfs_ib_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
unsigned i;
+   int r;
+
+   r = radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
+   if (r)
+   return r;

for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 4ce5c51..013a787 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -192,3 +192,18 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct 
radeon_sa_bo *sa_bo)
list_del_init(_bo->list);
spin_unlock_irqrestore(_bo->manager->lock, flags);
 }
+
+#if defined(CONFIG_DEBUG_FS)
+void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
+ struct seq_file *m)
+{
+   struct radeon_sa_bo *i;
+   unsigned long flags;
+
+   spin_lock_irqsave(_manager->lock, flags);
+   list_for_each_entry(i, _manager->sa_bo, list) {
+   seq_printf(m, "offset %08d: size %4d\n", i->offset, i->size);
+   }
+   spin_unlock_irqrestore(_manager->lock, flags);
+}
+#endif
-- 
1.7.5.4



[PATCH 07/26] drm/radeon: add proper locking to the SA v2

2012-04-25 Thread Christian König
Make the suballocator self containing to locking.

v2: split the bugfix into a seperate patch.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|1 +
 drivers/gpu/drm/radeon/radeon_sa.c |   17 +++--
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 92682b7..99b188a 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -381,6 +381,7 @@ struct radeon_bo_list {
  * alignment).
  */
 struct radeon_sa_manager {
+   spinlock_t  lock;
struct radeon_bo*bo;
struct list_headsa_bo;
unsignedsize;
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 8fbfe69..4ce5c51 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -37,6 +37,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev,
 {
int r;

+   spin_lock_init(_manager->lock);
sa_manager->bo = NULL;
sa_manager->size = size;
sa_manager->domain = domain;
@@ -136,18 +137,19 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
struct radeon_sa_bo *tmp;
struct list_head *head;
unsigned offset = 0, wasted = 0;
+   unsigned long flags;

BUG_ON(align > RADEON_GPU_PAGE_SIZE);
BUG_ON(size > sa_manager->size);
+   spin_lock_irqsave(_manager->lock, flags);

/* no one ? */
-   head = sa_manager->sa_bo.prev;
if (list_empty(_manager->sa_bo)) {
+   head = _manager->sa_bo;
goto out;
}

/* look for a hole big enough */
-   offset = 0;
list_for_each_entry(tmp, _manager->sa_bo, list) {
/* room before this object ? */
if (offset < tmp->offset && (tmp->offset - offset) >= size) {
@@ -157,9 +159,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
offset = tmp->offset + tmp->size;
wasted = offset % align;
if (wasted) {
-   wasted = align - wasted;
+   offset += align - wasted;
}
-   offset += wasted;
}
/* room at the end ? */
head = sa_manager->sa_bo.prev;
@@ -167,11 +168,11 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
offset = tmp->offset + tmp->size;
wasted = offset % align;
if (wasted) {
-   wasted = align - wasted;
+   offset += wasted = align - wasted;
}
-   offset += wasted;
if ((sa_manager->size - offset) < size) {
/* failed to find somethings big enough */
+   spin_unlock_irqrestore(_manager->lock, flags);
return -ENOMEM;
}

@@ -180,10 +181,14 @@ out:
sa_bo->offset = offset;
sa_bo->size = size;
list_add(_bo->list, head);
+   spin_unlock_irqrestore(_manager->lock, flags);
return 0;
 }

 void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo *sa_bo)
 {
+   unsigned long flags;
+   spin_lock_irqsave(_bo->manager->lock, flags);
list_del_init(_bo->list);
+   spin_unlock_irqrestore(_bo->manager->lock, flags);
 }
-- 
1.7.5.4



[PATCH 06/26] drm/radeon: fix a critical bug in the SA code

2012-04-25 Thread Christian König
Aligning offset can make it bigger than tmp->offset
leading to an overrun bug in the following subtraction.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_sa.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
index 4cce47e..8fbfe69 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -150,7 +150,7 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
offset = 0;
list_for_each_entry(tmp, _manager->sa_bo, list) {
/* room before this object ? */
-   if ((tmp->offset - offset) >= size) {
+   if (offset < tmp->offset && (tmp->offset - offset) >= size) {
head = tmp->list.prev;
goto out;
}
-- 
1.7.5.4



[PATCH 05/26] drm/radeon: rework gpu lockup detection and processing

2012-04-25 Thread Christian König
Previusly multiple rings could trigger multiple GPU
resets at the same time.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   |3 +-
 drivers/gpu/drm/radeon/radeon_fence.c |  146 +
 2 files changed, 75 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e237127..92682b7 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -255,8 +255,7 @@ struct radeon_fence_driver {
volatile uint32_t   *cpu_addr;
atomic_tseq;
uint32_tlast_seq;
-   unsigned long   last_jiffies;
-   unsigned long   last_timeout;
+   unsigned long   last_activity;
wait_queue_head_t   queue;
struct list_headcreated;
struct list_heademitted;
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 36c411f..1a9765a 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -74,6 +74,10 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
radeon_fence_ring_emit(rdev, fence->ring, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq);
fence->emitted = true;
+   /* are we the first fence on a previusly idle ring? */
+   if (list_empty(>fence_drv[fence->ring].emitted)) {
+   rdev->fence_drv[fence->ring].last_activity = jiffies;
+   }
list_move_tail(>list, >fence_drv[fence->ring].emitted);
write_unlock_irqrestore(>fence_lock, irq_flags);
return 0;
@@ -85,34 +89,14 @@ static bool radeon_fence_poll_locked(struct radeon_device 
*rdev, int ring)
struct list_head *i, *n;
uint32_t seq;
bool wake = false;
-   unsigned long cjiffies;

seq = radeon_fence_read(rdev, ring);
-   if (seq != rdev->fence_drv[ring].last_seq) {
-   rdev->fence_drv[ring].last_seq = seq;
-   rdev->fence_drv[ring].last_jiffies = jiffies;
-   rdev->fence_drv[ring].last_timeout = 
RADEON_FENCE_JIFFIES_TIMEOUT;
-   } else {
-   cjiffies = jiffies;
-   if (time_after(cjiffies, rdev->fence_drv[ring].last_jiffies)) {
-   cjiffies -= rdev->fence_drv[ring].last_jiffies;
-   if (time_after(rdev->fence_drv[ring].last_timeout, 
cjiffies)) {
-   /* update the timeout */
-   rdev->fence_drv[ring].last_timeout -= cjiffies;
-   } else {
-   /* the 500ms timeout is elapsed we should test
-* for GPU lockup
-*/
-   rdev->fence_drv[ring].last_timeout = 1;
-   }
-   } else {
-   /* wrap around update last jiffies, we will just wait
-* a little longer
-*/
-   rdev->fence_drv[ring].last_jiffies = cjiffies;
-   }
+   if (seq == rdev->fence_drv[ring].last_seq)
return false;
-   }
+
+   rdev->fence_drv[ring].last_seq = seq;
+   rdev->fence_drv[ring].last_activity = jiffies;
+
n = NULL;
list_for_each(i, >fence_drv[ring].emitted) {
fence = list_entry(i, struct radeon_fence, list);
@@ -207,66 +191,84 @@ int radeon_fence_wait(struct radeon_fence *fence, bool 
intr)
struct radeon_device *rdev;
unsigned long irq_flags, timeout;
u32 seq;
-   int r;
+   int i, r;
+   bool signaled;

if (fence == NULL) {
WARN(1, "Querying an invalid fence : %p !\n", fence);
-   return 0;
+   return -EINVAL;
}
+
rdev = fence->rdev;
-   if (radeon_fence_signaled(fence)) {
-   return 0;
-   }
-   timeout = rdev->fence_drv[fence->ring].last_timeout;
-retry:
-   /* save current sequence used to check for GPU lockup */
-   seq = rdev->fence_drv[fence->ring].last_seq;
-   trace_radeon_fence_wait_begin(rdev->ddev, seq);
-   if (intr) {
+   signaled = radeon_fence_signaled(fence);
+   while (!signaled) {
+   read_lock_irqsave(>fence_lock, irq_flags);
+   timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT;
+   if (time_after(rdev->fence_drv[fence->ring].last_activity, 
timeout)) {
+   /* the normal case, timeout is somewhere before 
last_activity */
+   timeout = rdev->fence_drv[fence->ring].last_activity - 
timeout;
+   } else {
+   /* either jiffies wrapped around, or no fence was 
signaled in the last 500ms
+   

[PATCH 04/26] drm/radeon: use central function for IB testing

2012-04-25 Thread Christian König
Removing all the different error messages and
having just one standard behaviour over all
chipset generations.

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/evergreen.c   |7 ++-
 drivers/gpu/drm/radeon/ni.c  |7 ++-
 drivers/gpu/drm/radeon/r100.c|7 ++-
 drivers/gpu/drm/radeon/r300.c|7 ++-
 drivers/gpu/drm/radeon/r420.c|7 ++-
 drivers/gpu/drm/radeon/r520.c|8 +++-
 drivers/gpu/drm/radeon/r600.c|7 ++-
 drivers/gpu/drm/radeon/radeon.h  |1 +
 drivers/gpu/drm/radeon/radeon_ring.c |   30 ++
 drivers/gpu/drm/radeon/rs400.c   |7 ++-
 drivers/gpu/drm/radeon/rs600.c   |7 ++-
 drivers/gpu/drm/radeon/rs690.c   |7 ++-
 drivers/gpu/drm/radeon/rv515.c   |8 +++-
 drivers/gpu/drm/radeon/rv770.c   |7 ++-
 14 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen.c 
b/drivers/gpu/drm/radeon/evergreen.c
index eed7ace..8b7a01b 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3376,12 +3376,9 @@ static int evergreen_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

r = r600_audio_init(rdev);
if (r) {
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index a48ca53..0146428 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1601,12 +1601,9 @@ static int cayman_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

r = radeon_vm_manager_start(rdev);
if (r)
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 4b677fc..62f9dab 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3968,12 +3968,9 @@ static int r100_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index a63f432..26e0db8 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -1417,12 +1417,9 @@ static int r300_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index f3fcaac..99137be 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -279,12 +279,9 @@ static int r420_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }

return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
index ebcc15b..b5cf837 100644
--- a/drivers/gpu/drm/radeon/r520.c
+++ b/drivers/gpu/drm/radeon/r520.c
@@ -207,12 +207,10 @@ static int r520_startup(struct radeon_device *rdev)
if (r)
return r;

-   r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, 
>ring[RADEON_RING_TYPE_GFX_INDEX]);
-   if (r) {
-   dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-   rdev->accel_working = false;
+   r = radeon_ib_ring_tests(rdev);
+   if (r)
return r;
-   }
+
return 0;
 }

diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index ba637d9..db9415a 100644
--- 

[PATCH 03/26] drm/radeon: register ring debugfs handlers on init

2012-04-25 Thread Christian König
Just register the debugfs files on init instead of
checking the chipset type multiple times.

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon_ring.c |   31 +++
 1 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_ring.c 
b/drivers/gpu/drm/radeon/radeon_ring.c
index cc33b3d..b6eb1d2 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -34,7 +34,7 @@
 #include "atom.h"

 int radeon_debugfs_ib_init(struct radeon_device *rdev);
-int radeon_debugfs_ring_init(struct radeon_device *rdev);
+int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring 
*ring);

 u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
 {
@@ -237,9 +237,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
if (radeon_debugfs_ib_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for IB !\n");
}
-   if (radeon_debugfs_ring_init(rdev)) {
-   DRM_ERROR("Failed to register debugfs file for rings !\n");
-   }
radeon_mutex_unlock(>ib_pool.mutex);
return 0;
 }
@@ -411,6 +408,9 @@ int radeon_ring_init(struct radeon_device *rdev, struct 
radeon_ring *ring, unsig
}
ring->ptr_mask = (ring->ring_size / 4) - 1;
ring->ring_free_dw = ring->ring_size / 4;
+   if (radeon_debugfs_ring_init(rdev, ring)) {
+   DRM_ERROR("Failed to register debugfs file for rings !\n");
+   }
return 0;
 }

@@ -501,17 +501,24 @@ static char 
radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
 static unsigned radeon_debugfs_ib_idx[RADEON_IB_POOL_SIZE];
 #endif

-int radeon_debugfs_ring_init(struct radeon_device *rdev)
+int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring 
*ring)
 {
 #if defined(CONFIG_DEBUG_FS)
-   if (rdev->family >= CHIP_CAYMAN)
-   return radeon_debugfs_add_files(rdev, 
radeon_debugfs_ring_info_list,
-   
ARRAY_SIZE(radeon_debugfs_ring_info_list));
-   else
-   return radeon_debugfs_add_files(rdev, 
radeon_debugfs_ring_info_list, 1);
-#else
-   return 0;
+   unsigned i;
+   for (i = 0; i < ARRAY_SIZE(radeon_debugfs_ring_info_list); ++i) {
+   struct drm_info_list *info = _debugfs_ring_info_list[i];
+   int ridx = *(int*)radeon_debugfs_ring_info_list[i].data;
+   unsigned r;
+
+   if (>ring[ridx] != ring)
+   continue;
+
+   r = radeon_debugfs_add_files(rdev, info, 1);
+   if (r)
+   return r;
+   }
 #endif
+   return 0;
 }

 int radeon_debugfs_ib_init(struct radeon_device *rdev)
-- 
1.7.5.4



[PATCH 02/26] drm/radeon: replace gpu_lockup with ring->ready flag

2012-04-25 Thread Christian König
It makes no sense at all to have more than one flag.

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/r100.c  |1 -
 drivers/gpu/drm/radeon/r300.c  |1 -
 drivers/gpu/drm/radeon/radeon.h|1 -
 drivers/gpu/drm/radeon/radeon_device.c |1 -
 drivers/gpu/drm/radeon/radeon_fence.c  |   36 +++
 drivers/gpu/drm/radeon/rs600.c |1 -
 6 files changed, 13 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index e11df77..4b677fc 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2300,7 +2300,6 @@ int r100_asic_reset(struct radeon_device *rdev)
if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) ||
G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) {
dev_err(rdev->dev, "failed to reset GPU\n");
-   rdev->gpu_lockup = true;
ret = -1;
} else
dev_info(rdev->dev, "GPU reset succeed\n");
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index fa14383..a63f432 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -449,7 +449,6 @@ int r300_asic_reset(struct radeon_device *rdev)
/* Check if GPU is idle */
if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
dev_err(rdev->dev, "failed to reset GPU\n");
-   rdev->gpu_lockup = true;
ret = -1;
} else
dev_info(rdev->dev, "GPU reset succeed\n");
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 1bcd2b3..bb08702 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1538,7 +1538,6 @@ struct radeon_device {
struct radeon_mutex cs_mutex;
struct radeon_wbwb;
struct radeon_dummy_pagedummy_page;
-   boolgpu_lockup;
boolshutdown;
boolsuspend;
boolneed_dma32;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 0fb4f89..dedb398 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -714,7 +714,6 @@ int radeon_device_init(struct radeon_device *rdev,
rdev->is_atom_bios = false;
rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT;
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-   rdev->gpu_lockup = false;
rdev->accel_working = false;

DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 
0x%04X:0x%04X).\n",
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 66b2229..36c411f 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -71,14 +71,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct 
radeon_fence *fence)
return 0;
}
fence->seq = atomic_add_return(1, >fence_drv[fence->ring].seq);
-   if (!rdev->ring[fence->ring].ready)
-   /* FIXME: cp is not running assume everythings is done right
-* away
-*/
-   radeon_fence_write(rdev, fence->seq, fence->ring);
-   else
-   radeon_fence_ring_emit(rdev, fence->ring, fence);
-
+   radeon_fence_ring_emit(rdev, fence->ring, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq);
fence->emitted = true;
list_move_tail(>list, >fence_drv[fence->ring].emitted);
@@ -191,9 +184,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence)
if (!fence)
return true;

-   if (fence->rdev->gpu_lockup)
-   return true;
-
write_lock_irqsave(>rdev->fence_lock, irq_flags);
signaled = fence->signaled;
/* if we are shuting down report all fence as signaled */
@@ -260,18 +250,16 @@ retry:
 */
if (seq == rdev->fence_drv[fence->ring].last_seq &&
radeon_ring_is_lockup(rdev, fence->ring, 
>ring[fence->ring])) {
+
/* good news we believe it's a lockup */
printk(KERN_WARNING "GPU lockup (waiting for 0x%08X 
last fence id 0x%08X)\n",
 fence->seq, seq);
-   /* FIXME: what should we do ? marking everyone
-* as signaled for now
-*/
-   rdev->gpu_lockup = true;
+
+   /* mark the ring as not ready any more */
+   rdev->ring[fence->ring].ready = false;
r = radeon_gpu_reset(rdev);
if (r)
return r;
-   

[PATCH 01/26] drm/radeon: make radeon_gpu_is_lockup a per ring function

2012-04-25 Thread Christian König
Different rings have different criteria to test
if they are stuck.

v2: rebased on current drm-next

Signed-off-by: Christian K?nig 
Reviewed-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon.h   |4 +-
 drivers/gpu/drm/radeon/radeon_asic.c  |   44 ++--
 drivers/gpu/drm/radeon/radeon_fence.c |2 +-
 3 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 566ca3b..1bcd2b3 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1153,7 +1153,6 @@ struct radeon_asic {
int (*resume)(struct radeon_device *rdev);
int (*suspend)(struct radeon_device *rdev);
void (*vga_set_state)(struct radeon_device *rdev, bool state);
-   bool (*gpu_is_lockup)(struct radeon_device *rdev, struct radeon_ring 
*cp);
int (*asic_reset)(struct radeon_device *rdev);
/* ioctl hw specific callback. Some hw might want to perform special
 * operation on specific ioctl. For instance on wait idle some hw
@@ -1182,6 +1181,7 @@ struct radeon_asic {
void (*ring_start)(struct radeon_device *rdev, struct 
radeon_ring *cp);
int (*ring_test)(struct radeon_device *rdev, struct radeon_ring 
*cp);
int (*ib_test)(struct radeon_device *rdev, struct radeon_ring 
*cp);
+   bool (*is_lockup)(struct radeon_device *rdev, struct 
radeon_ring *cp);
} ring[RADEON_NUM_RINGS];
/* irqs */
struct {
@@ -1739,7 +1739,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t 
v);
 #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
 #define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)].cs_parse((p))
 #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), 
(state))
-#define radeon_gpu_is_lockup(rdev, cp) (rdev)->asic->gpu_is_lockup((rdev), 
(cp))
 #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
 #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
 #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), 
(i), (p))
@@ -1748,6 +1747,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t 
v);
 #define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)].ib_test((rdev), 
(cp))
 #define radeon_ring_ib_execute(rdev, r, ib) 
(rdev)->asic->ring[(r)].ib_execute((rdev), (ib))
 #define radeon_ring_ib_parse(rdev, r, ib) 
(rdev)->asic->ring[(r)].ib_parse((rdev), (ib))
+#define radeon_ring_is_lockup(rdev, r, cp) 
(rdev)->asic->ring[(r)].is_lockup((rdev), (cp))
 #define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev))
 #define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev))
 #define radeon_get_vblank_counter(rdev, crtc) 
(rdev)->asic->display.get_vblank_counter((rdev), (crtc))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c 
b/drivers/gpu/drm/radeon/radeon_asic.c
index be4dc2f..958b9ea 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -134,7 +134,6 @@ static struct radeon_asic r100_asic = {
.suspend = _suspend,
.resume = _resume,
.vga_set_state = _vga_set_state,
-   .gpu_is_lockup = _gpu_is_lockup,
.asic_reset = _asic_reset,
.ioctl_wait_idle = NULL,
.gui_idle = _gui_idle,
@@ -152,6 +151,7 @@ static struct radeon_asic r100_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -208,7 +208,6 @@ static struct radeon_asic r200_asic = {
.suspend = _suspend,
.resume = _resume,
.vga_set_state = _vga_set_state,
-   .gpu_is_lockup = _gpu_is_lockup,
.asic_reset = _asic_reset,
.ioctl_wait_idle = NULL,
.gui_idle = _gui_idle,
@@ -226,6 +225,7 @@ static struct radeon_asic r200_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -282,7 +282,6 @@ static struct radeon_asic r300_asic = {
.suspend = _suspend,
.resume = _resume,
.vga_set_state = _vga_set_state,
-   .gpu_is_lockup = _gpu_is_lockup,
.asic_reset = _asic_reset,
.ioctl_wait_idle = NULL,
.gui_idle = _gui_idle,
@@ -300,6 +299,7 @@ static struct radeon_asic r300_asic = {
.ring_start = _ring_start,
.ring_test = _ring_test,
.ib_test = _ib_test,
+   .is_lockup = _gpu_is_lockup,
}
},
.irq = {
@@ -356,7 +356,6 @@ static struct radeon_asic r300_asic_pcie = {
.suspend = _suspend,
.resume = _resume,

Reworking of GPU reset logic

2012-04-25 Thread Christian König
Second round of patchset.

Thanks for all the comments and/or bug reports, allot of patches are now v2/v3 
and should get another look. Every regression known so far should be fixed with 
them now.
Additionally to the patches that where already included in the last set there 
are 8 new ones which are also reset, lockup and debugging related.

As always comments and bug-reports are very welcome,
Christian.



[PATCH 12/12] gma500: Set the mapping mask

2012-04-25 Thread Alan Cox
From: Alan Cox 

Some boards such as the Intel D2700MUD allow you to have over 4GB of RAM.
The GTT on the PVR based devices is 32bit however. Hugh Dickins points out
that we should therefore be setting the mapping gfp mask.

This is not the whole fix for the problem. Some further shmem patches will
be needed to deal with the corner cases.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/gem.c |2 ++
 drivers/gpu/drm/gma500/gtt.c |4 
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index 9fbb868..fc7d144 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -124,6 +124,8 @@ static int psb_gem_create(struct drm_file *file,
dev_err(dev->dev, "GEM init failed for %lld\n", size);
return -ENOMEM;
}
+   /* Limit the object to 32bit mappings */
+   mapping_set_gfp_mask(r->gem.filp->f_mapping, GFP_KERNEL | __GFP_DMA32);
/* Give the object a handle so we can carry it more easily */
ret = drm_gem_handle_create(file, >gem, );
if (ret) {
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index db2e823..54e5c9e 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -39,6 +39,10 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int 
type)
 {
uint32_t mask = PSB_PTE_VALID;

+   /* Ensure we explode rather than put an invalid low mapping of
+  a high mapping page into the gtt */
+   BUG_ON(pfn & ~(0x >> PAGE_SHIFT));
+
if (type & PSB_MMU_CACHED_MEMORY)
mask |= PSB_PTE_CACHED;
if (type & PSB_MMU_RO_MEMORY)



[PATCH 11/12] gma500: Add the base elements of CDV hotplug support

2012-04-25 Thread Alan Cox
From: Alan Cox 

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/cdv_device.c|   41 ++--
 drivers/gpu/drm/gma500/psb_drv.h   |5 
 drivers/gpu/drm/gma500/psb_intel_reg.h |5 +++-
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_device.c 
b/drivers/gpu/drm/gma500/cdv_device.c
index 5cc06a8..62f9b73 100644
--- a/drivers/gpu/drm/gma500/cdv_device.c
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -462,13 +462,48 @@ static void cdv_get_core_freq(struct drm_device *dev)
}
 }

+static void cdv_hotplug_work_func(struct work_struct *work)
+{
+struct drm_psb_private *dev_priv = container_of(work, struct 
drm_psb_private,
+   hotplug_work);  
   
+struct drm_device *dev = dev_priv->dev;
+
+/* Just fire off a uevent and let userspace tell us what to do */
+drm_helper_hpd_irq_event(dev);
+}   
+
+/* The core driver has received a hotplug IRQ. We are in IRQ context
+   so extract the needed information and kick off queued processing */
+   
+static int cdv_hotplug_event(struct drm_device *dev)
+{
+   struct drm_psb_private *dev_priv = dev->dev_private;
+   schedule_work(_priv->hotplug_work);
+   REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+   return 1;
+}
+
+static void cdv_hotplug_enable(struct drm_device *dev, bool on)
+{
+   if (on) {
+   u32 hotplug = REG_READ(PORT_HOTPLUG_EN);
+   hotplug |= HDMIB_HOTPLUG_INT_EN | HDMIC_HOTPLUG_INT_EN |
+  HDMID_HOTPLUG_INT_EN | CRT_HOTPLUG_INT_EN;
+   REG_WRITE(PORT_HOTPLUG_EN, hotplug);
+   }  else {
+   REG_WRITE(PORT_HOTPLUG_EN, 0);
+   REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+   }   
+}
+
 static int cdv_chip_setup(struct drm_device *dev)
 {
+   struct drm_psb_private *dev_priv = dev->dev_private;
+   INIT_WORK(_priv->hotplug_work, cdv_hotplug_work_func);
cdv_get_core_freq(dev);
gma_intel_opregion_init(dev);
psb_intel_init_bios(dev);
-   REG_WRITE(PORT_HOTPLUG_EN, 0);
-   REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+   cdv_hotplug_enable(dev, false);
return 0;
 }

@@ -489,6 +524,8 @@ const struct psb_ops cdv_chip_ops = {
.crtc_funcs = _intel_crtc_funcs,

.output_init = cdv_output_init,
+   .hotplug = cdv_hotplug_event,
+   .hotplug_enable = cdv_hotplug_enable,

 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
.backlight_init = cdv_backlight_init,
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index ab483c3..d3528a6 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -626,6 +626,11 @@ struct drm_psb_private {
uint32_t msi_addr;
uint32_t msi_data;

+   /*
+* Hotplug handling
+*/
+
+   struct work_struct hotplug_work;

/*
 * LID-Switch
diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h 
b/drivers/gpu/drm/gma500/psb_intel_reg.h
index cbd8aee..519a9cd 100644
--- a/drivers/gpu/drm/gma500/psb_intel_reg.h
+++ b/drivers/gpu/drm/gma500/psb_intel_reg.h
@@ -219,7 +219,7 @@
 #define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24)   /* i915 */
 #define DPLLB_LVDS_P2_CLOCK_DIV_7  (1 << 24)   /* i915 */
 #define DPLL_P2_CLOCK_DIV_MASK 0x0300  /* i915 */
-#define DPLL_FPA01_P1_POST_DIV_MASK0x00ff  /* i915 */
+#define DPLL_FPA0h1_P1_POST_DIV_MASK   0x00ff  /* i915 */
 #define DPLL_LOCK  (1 << 15)   /* CDV */

 /*
@@ -346,6 +346,9 @@
 #define FP_M2_DIV_SHIFT0

 #define PORT_HOTPLUG_EN0x61110
+#define HDMIB_HOTPLUG_INT_EN   (1 << 29)
+#define HDMIC_HOTPLUG_INT_EN   (1 << 28)
+#define HDMID_HOTPLUG_INT_EN   (1 << 27)
 #define SDVOB_HOTPLUG_INT_EN   (1 << 26)
 #define SDVOC_HOTPLUG_INT_EN   (1 << 25)
 #define TV_HOTPLUG_INT_EN  (1 << 18)



[PATCH 10/12] gma500: Add ops for hotplug support.

2012-04-25 Thread Alan Cox
From: Alan Cox 

This provides the needed callback hooks to add hotplug display support to
the GMA36x0 devices. 

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/psb_drv.h |3 +++
 drivers/gpu/drm/gma500/psb_irq.c |   30 +++---
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 6235499..ab483c3 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -130,6 +130,7 @@ enum {
 #define _PSB_VSYNC_PIPEA_FLAG(1<<7)
 #define _MDFLD_MIPIA_FLAG(1<<16)
 #define _MDFLD_MIPIC_FLAG(1<<17)
+#define _PSB_IRQ_DISP_HOTSYNC(1<<17)
 #define _PSB_IRQ_SGX_FLAG(1<<18)
 #define _PSB_IRQ_MSVDX_FLAG  (1<<19)
 #define _LNC_IRQ_TOPAZ_FLAG  (1<<20)
@@ -703,6 +704,8 @@ struct psb_ops {

/* Display management hooks */
int (*output_init)(struct drm_device *dev);
+   int (*hotplug)(struct drm_device *dev);
+   void (*hotplug_enable)(struct drm_device *dev, bool on);
/* Power management hooks */
void (*init_pm)(struct drm_device *dev);
int (*save_regs)(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 1869586..2fcdffd 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -199,11 +199,9 @@ static void psb_vdc_interrupt(struct drm_device *dev, 
uint32_t vdc_stat)

 irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 {
-   struct drm_device *dev = (struct drm_device *) arg;
-   struct drm_psb_private *dev_priv =
-   (struct drm_psb_private *) dev->dev_private;
-
-   uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
+   struct drm_device *dev = arg;
+   struct drm_psb_private *dev_priv = dev->dev_private;
+   uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0;
int handled = 0;

spin_lock(_priv->irqmask_lock);
@@ -220,6 +218,8 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)

if (vdc_stat & _PSB_IRQ_SGX_FLAG)
sgx_int = 1;
+   if (vdc_stat & _PSB_IRQ_DISP_HOTSYNC)
+   hotplug_int = 1;

vdc_stat &= dev_priv->vdc_irq_mask;
spin_unlock(_priv->irqmask_lock);
@@ -241,6 +241,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
handled = 1;
}

+   /* Note: this bit has other meanings on some devices, so we will
+  need to address that later if it ever matters */
+   if (hotplug_int && dev_priv->ops->hotplug) {
+   handled = dev_priv->ops->hotplug(dev);
+   REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+   }
+
PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
(void) PSB_RVDC32(PSB_INT_IDENTITY_R);
DRM_READMEMORYBARRIER();
@@ -273,6 +280,10 @@ void psb_irq_preinstall(struct drm_device *dev)
dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
*/

+   /* Revisit this area - want per device masks ? */
+   if (dev_priv->ops->hotplug)
+   dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC;
+
/* This register is safe even if display island is off */
PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
spin_unlock_irqrestore(_priv->irqmask_lock, irqflags);
@@ -305,18 +316,23 @@ int psb_irq_postinstall(struct drm_device *dev)
else
psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);

+   if (dev_priv->ops->hotplug_enable)
+   dev_priv->ops->hotplug_enable(dev, true);
+
spin_unlock_irqrestore(_priv->irqmask_lock, irqflags);
return 0;
 }

 void psb_irq_uninstall(struct drm_device *dev)
 {
-   struct drm_psb_private *dev_priv =
-   (struct drm_psb_private *) dev->dev_private;
+   struct drm_psb_private *dev_priv = dev->dev_private;
unsigned long irqflags;

spin_lock_irqsave(_priv->irqmask_lock, irqflags);

+   if (dev_priv->ops->hotplug_enable)
+   dev_priv->ops->hotplug_enable(dev, false);
+
PSB_WVDC32(0x, PSB_HWSTAM);

if (dev->vblank_enabled[0])



[PATCH 09/12] cdv: continue synching up with updated reference code

2012-04-25 Thread Alan Cox
From: Alan Cox 

In particular clean up the errata handling and correct the crtc masks. We do
this a bit differently using our device abstraction for neatness.

This doesn't address the ACPI opregion and hotplug plumbing, nor the IRQ related
changes that will need. It touches on backlight init but the full backlight
support is not in this change set.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/cdv_device.c|   20 +
 drivers/gpu/drm/gma500/cdv_intel_crt.c |   20 +++--
 drivers/gpu/drm/gma500/cdv_intel_display.c |   61 
 drivers/gpu/drm/gma500/cdv_intel_lvds.c|   17 
 drivers/gpu/drm/gma500/framebuffer.c   |   13 ++
 drivers/gpu/drm/gma500/mdfld_device.c  |2 +
 drivers/gpu/drm/gma500/oaktrail_device.c   |2 +
 drivers/gpu/drm/gma500/psb_device.c|2 +
 drivers/gpu/drm/gma500/psb_drv.h   |4 ++
 drivers/gpu/drm/gma500/psb_intel_reg.h |4 ++
 10 files changed, 89 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_device.c 
b/drivers/gpu/drm/gma500/cdv_device.c
index a54cc73..5cc06a8 100644
--- a/drivers/gpu/drm/gma500/cdv_device.c
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -49,6 +49,9 @@ static void cdv_disable_vga(struct drm_device *dev)
 static int cdv_output_init(struct drm_device *dev)
 {
struct drm_psb_private *dev_priv = dev->dev_private;
+
+   drm_mode_create_scaling_mode_property(dev);
+
cdv_disable_vga(dev);

cdv_intel_crt_init(dev, _priv->mode_dev);
@@ -238,6 +241,18 @@ static void cdv_init_pm(struct drm_device *dev)
dev_err(dev->dev, "GPU: power management timed out.\n");
 }

+static void cdv_errata(struct drm_device *dev)
+{
+   /* Disable bonus launch.
+*  CPU and GPU competes for memory and display misses updates and 
flickers.
+*  Worst with dual core, dual displays.
+*
+*  Fixes were done to Win 7 gfx driver to disable a feature called 
Bonus
+*  Launch to work around the issue, by degrading performance.
+*/
+CDV_MSG_WRITE32(3, 0x30, 0x08027108);
+}
+
 /**
  * cdv_save_display_registers  -   save registers lost on suspend
  * @dev: our DRM device
@@ -355,7 +370,7 @@ static int cdv_restore_display_registers(struct drm_device 
*dev)
REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR);

/* Fix arbitration bug */
-   CDV_MSG_WRITE32(3, 0x30, 0x08027108);
+   cdv_errata(dev);

drm_mode_config_reset(dev);

@@ -464,8 +479,11 @@ const struct psb_ops cdv_chip_ops = {
.accel_2d = 0,
.pipes = 2,
.crtcs = 2,
+   .hdmi_mask = (1 << 0) | (1 << 1),
+   .lvds_mask = (1 << 1),
.sgx_offset = MRST_SGX_OFFSET,
.chip_setup = cdv_chip_setup,
+   .errata = cdv_errata,

.crtc_helper = _intel_helper_funcs,
.crtc_funcs = _intel_crtc_funcs,
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c 
b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 1a82843..1874220 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -78,9 +78,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector 
*connector,
if (mode->clock > 355000)
return MODE_CLOCK_HIGH;

-   if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
-   return MODE_PANEL;
-
return MODE_OK;
 }

@@ -148,13 +145,7 @@ static bool cdv_intel_crt_detect_hotplug(struct 
drm_connector *connector,
struct drm_device *dev = connector->dev;
u32 hotplug_en;
int i, tries = 0, ret = false;
-   u32 adpa_orig;
-
-   /* disable the DAC when doing the hotplug detection */
-
-   adpa_orig = REG_READ(ADPA);
-
-   REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
+   u32 orig;

/*
 * On a CDV thep, CRT detect sequence need to be done twice
@@ -162,7 +153,7 @@ static bool cdv_intel_crt_detect_hotplug(struct 
drm_connector *connector,
 */
tries = 2;

-   hotplug_en = REG_READ(PORT_HOTPLUG_EN);
+   orig = hotplug_en = REG_READ(PORT_HOTPLUG_EN);
hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;

@@ -187,8 +178,11 @@ static bool cdv_intel_crt_detect_hotplug(struct 
drm_connector *connector,
CRT_HOTPLUG_MONITOR_NONE)
ret = true;

-   /* Restore the saved ADPA */
-   REG_WRITE(ADPA, adpa_orig);
+/* clear the interrupt we just generated, if any */
+   REG_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
+
+   /* and put the bits back */
+   REG_WRITE(PORT_HOTPLUG_EN, orig);
return ret;
 }

diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c 
b/drivers/gpu/drm/gma500/cdv_intel_display.c
index 07b37f5..2fab778 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -226,13 +226,13 @@ 

[PATCH 08/12] gma500: Clean up weirdness in the cdv mode test code

2012-04-25 Thread Alan Cox
From: Alan Cox 

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/cdv_intel_crt.c |4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c 
b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 1de27c7..1a82843 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -67,7 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, 
int mode)
 static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
 {
-   int max_clock = 0;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;

@@ -76,8 +75,7 @@ static int cdv_intel_crt_mode_valid(struct drm_connector 
*connector,
return MODE_CLOCK_LOW;

/* The max clock for CDV is 355 instead of 400 */
-   max_clock = 355000;
-   if (mode->clock > max_clock)
+   if (mode->clock > 355000)
return MODE_CLOCK_HIGH;

if (mode->hdisplay > 1680 || mode->vdisplay > 1050)



[PATCH 07/12] gma500: support 1080p

2012-04-25 Thread Alan Cox
From: Alan Cox 

The problem in console mode is lack of linear memory. We can solve that by
dropping to 16bpp. The mode setting X server will allocate its own GEM
framebuffer in 32bpp and all will be well.

We could just do 16bpp anyway but that would be a regression on the lower
modes as many distributions don't yet ship the generic mode setting KMS
drivers.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/cdv_intel_crt.c  |6 --
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c |7 ---
 drivers/gpu/drm/gma500/framebuffer.c|   16 
 drivers/gpu/drm/gma500/oaktrail_hdmi.c  |6 --
 drivers/gpu/drm/gma500/psb_intel_sdvo.c |6 --
 5 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c 
b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index a71a6cd..1de27c7 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -67,7 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, 
int mode)
 static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
 {
-   struct drm_psb_private *dev_priv = connector->dev->dev_private;
int max_clock = 0;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -84,11 +83,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector 
*connector,
if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
return MODE_PANEL;

-   /* We assume worst case scenario of 32 bpp here, since we don't know */
-   if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
-   dev_priv->vram_stolen_size)
-   return MODE_MEM;
-
return MODE_OK;
 }

diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c 
b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 8d52695..88b59d4 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -242,8 +242,6 @@ static int cdv_hdmi_get_modes(struct drm_connector 
*connector)
 static int cdv_hdmi_mode_valid(struct drm_connector *connector,
 struct drm_display_mode *mode)
 {
-   struct drm_psb_private *dev_priv = connector->dev->dev_private;
-
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
if (mode->clock < 2)
@@ -257,11 +255,6 @@ static int cdv_hdmi_mode_valid(struct drm_connector 
*connector,
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
return MODE_NO_INTERLACE;

-   /* We assume worst case scenario of 32 bpp here, since we don't know */
-   if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
-   dev_priv->vram_stolen_size)
-   return MODE_MEM;
-
return MODE_OK;
 }

diff --git a/drivers/gpu/drm/gma500/framebuffer.c 
b/drivers/gpu/drm/gma500/framebuffer.c
index 8ea202f..c2cf6bf 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -543,9 +543,25 @@ static int psbfb_probe(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
 {
struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
+   struct drm_device *dev = psb_fbdev->psb_fb_helper.dev;
+   struct drm_psb_private *dev_priv = dev->dev_private;
int new_fb = 0;
+   int bytespp;
int ret;

+   bytespp = sizes->surface_bpp / 8;
+   if (bytespp == 3)   /* no 24bit packed */
+   bytespp = 4;
+
+   /* If the mode will not fit in 32bit then switch to 16bit to get
+  a console on full resolution. The X mode setting server will
+  allocate its own 32bit GEM framebuffer */
+   if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height >
+   dev_priv->vram_stolen_size) {
+sizes->surface_bpp = 16;
+sizes->surface_depth = 16;
+}
+
if (!helper->fb) {
ret = psbfb_create(psb_fbdev, sizes);
if (ret)
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c 
b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index f8b367b..2595660 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -179,7 +179,6 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, 
int mode)
 static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
 {
-   struct drm_psb_private *dev_priv = connector->dev->dev_private;
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
if (mode->clock < 2)
@@ -188,11 +187,6 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector 
*connector,
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;

-   /* We assume worst case scenario of 32 bpp here, since we don't know 

[PATCH 06/12] gma500: panel presence check

2012-04-25 Thread Alan Cox
From: Alan Cox 

Introduce a panel presence check for Cedartrail. Non netbook devices don't
necessarily have a panel attached.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/cdv_intel_lvds.c |   57 +++
 1 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c 
b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 8359c1a..c87b179 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -556,6 +556,56 @@ const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
.destroy = cdv_intel_lvds_enc_destroy,
 };

+/*
+ * Enumerate the child dev array parsed from VBT to check whether
+ * the LVDS is present.
+ * If it is present, return 1.
+ * If it is not present, return false.
+ * If no child dev is parsed from VBT, it assumes that the LVDS is present.
+ */
+static bool lvds_is_present_in_vbt(struct drm_device *dev,
+  u8 *i2c_pin)
+{
+   struct drm_psb_private *dev_priv = dev->dev_private;
+   int i;
+
+   if (!dev_priv->child_dev_num)
+   return true;
+
+   for (i = 0; i < dev_priv->child_dev_num; i++) {
+   struct child_device_config *child = dev_priv->child_dev + i;
+
+   /* If the device type is not LFP, continue.
+* We have to check both the new identifiers as well as the
+* old for compatibility with some BIOSes.
+*/
+   if (child->device_type != DEVICE_TYPE_INT_LFP &&
+   child->device_type != DEVICE_TYPE_LFP)
+   continue;
+
+   if (child->i2c_pin)
+   *i2c_pin = child->i2c_pin;
+
+   /* However, we cannot trust the BIOS writers to populate
+* the VBT correctly.  Since LVDS requires additional
+* information from AIM blocks, a non-zero addin offset is
+* a good indicator that the LVDS is actually present.
+*/
+   if (child->addin_offset)
+   return true;
+
+   /* But even then some BIOS writers perform some black magic
+* and instantiate the device without reference to any
+* additional data.  Trust that if the VBT was written into
+* the OpRegion then they have validated the LVDS's existence.
+*/
+   if (dev_priv->opregion.vbt)
+   return true;
+   }
+
+   return false;
+}
+
 /**
  * cdv_intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -576,6 +626,13 @@ void cdv_intel_lvds_init(struct drm_device *dev,
struct drm_psb_private *dev_priv = dev->dev_private;
u32 lvds;
int pipe;
+   u8 pin;
+
+   pin = GMBUS_PORT_PANEL;
+   if (!lvds_is_present_in_vbt(dev, )) {
+   DRM_DEBUG_KMS("LVDS is not present in VBT\n");
+   return;
+   }

psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder),
GFP_KERNEL);



[PATCH 05/12] gma500: intel_bios updates

2012-04-25 Thread Alan Cox
From: Alan Cox 

Pull in various i915 bits that we will need to begin tackling the LVDS detect
and ACPI events. We try and drift towards the i915 version of the code with
the long term goal that at least some of it can one day be unified.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/intel_bios.c |  232 ---
 drivers/gpu/drm/gma500/intel_bios.h |  122 +++-
 drivers/gpu/drm/gma500/intel_opregion.c |  117 ++--
 drivers/gpu/drm/gma500/psb_drv.h|4 +
 4 files changed, 438 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/gma500/intel_bios.c 
b/drivers/gpu/drm/gma500/intel_bios.c
index 51ea6df..479e449 100644
--- a/drivers/gpu/drm/gma500/intel_bios.c
+++ b/drivers/gpu/drm/gma500/intel_bios.c
@@ -26,6 +26,8 @@
 #include "psb_intel_reg.h"
 #include "intel_bios.h"

+#defineSLAVE_ADDR1 0x70
+#defineSLAVE_ADDR2 0x72

 static void *find_section(struct bdb_header *bdb, int section_id)
 {
@@ -52,6 +54,16 @@ static void *find_section(struct bdb_header *bdb, int 
section_id)
return NULL;
 }

+static u16
+get_blocksize(void *p)
+{
+   u16 *block_ptr, block_size;
+
+   block_ptr = (u16 *)((char *)p - 2);
+   block_size = *block_ptr;
+   return block_size;
+}
+
 static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
struct lvds_dvo_timing *dvo_timing)
 {
@@ -75,6 +87,16 @@ static void fill_detail_timing_data(struct drm_display_mode 
*panel_fixed_mode,
panel_fixed_mode->clock = dvo_timing->clock * 10;
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;

+   if (dvo_timing->hsync_positive)
+   panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+   else
+   panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+   if (dvo_timing->vsync_positive)
+   panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
+   else
+   panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
/* Some VBTs have bogus h/vtotal values */
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -218,6 +240,97 @@ static void parse_general_features(struct drm_psb_private 
*dev_priv,
 }

 static void
+parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
+ struct bdb_header *bdb)
+{
+   struct sdvo_device_mapping *p_mapping;
+   struct bdb_general_definitions *p_defs;
+   struct child_device_config *p_child;
+   int i, child_device_num, count;
+   u16 block_size;
+
+   p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+   if (!p_defs) {
+   DRM_DEBUG_KMS("No general definition block is found, unable to 
construct sdvo mapping.\n");
+   return;
+   }
+   /* judge whether the size of child device meets the requirements.
+* If the child device size obtained from general definition block
+* is different with sizeof(struct child_device_config), skip the
+* parsing of sdvo device info
+*/
+   if (p_defs->child_dev_size != sizeof(*p_child)) {
+   /* different child dev size . Ignore it */
+   DRM_DEBUG_KMS("different child size is found. Invalid.\n");
+   return;
+   }
+   /* get the block size of general definitions */
+   block_size = get_blocksize(p_defs);
+   /* get the number of child device */
+   child_device_num = (block_size - sizeof(*p_defs)) /
+   sizeof(*p_child);
+   count = 0;
+   for (i = 0; i < child_device_num; i++) {
+   p_child = &(p_defs->devices[i]);
+   if (!p_child->device_type) {
+   /* skip the device block if device type is invalid */
+   continue;
+   }
+   if (p_child->slave_addr != SLAVE_ADDR1 &&
+   p_child->slave_addr != SLAVE_ADDR2) {
+   /*
+* If the slave address is neither 0x70 nor 0x72,
+* it is not a SDVO device. Skip it.
+*/
+   continue;
+   }
+   if (p_child->dvo_port != DEVICE_PORT_DVOB &&
+   p_child->dvo_port != DEVICE_PORT_DVOC) {
+   /* skip the incorrect SDVO port */
+   DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
+   continue;
+   }
+   DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
+   " %s port\n",
+   p_child->slave_addr,
+   (p_child->dvo_port == DEVICE_PORT_DVOB) ?
+   "SDVOB" : "SDVOC");
+   p_mapping = 

[PATCH 04/12] gma500: mark framebuffer pages write combining

2012-04-25 Thread Alan Cox
From: Alan Cox 

We don't want them uncached, combining will do nicely and fixes the performance
problem with the generic modesetting X server.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/gtt.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index c6465b4..db2e823 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -93,7 +93,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct 
gtt_range *r)
pages = r->pages;

/* Make sure changes are visible to the GPU */
-   set_pages_array_uc(pages, r->npage);
+   set_pages_array_wc(pages, r->npage);

/* Write our page entries into the GTT itself */
for (i = r->roll; i < r->npage; i++) {



[PATCH 03/12] gma500: Update the Cedarview clock handling

2012-04-25 Thread Alan Cox
From: Alan Cox 


---

 drivers/gpu/drm/gma500/cdv_intel_display.c |  331 +++-
 drivers/gpu/drm/gma500/psb_intel_drv.h |3 
 drivers/gpu/drm/gma500/psb_intel_reg.h |   25 ++
 3 files changed, 294 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c 
b/drivers/gpu/drm/gma500/cdv_intel_display.c
index be84559..07b37f5 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -216,7 +216,7 @@ static void cdv_sb_reset(struct drm_device *dev)
  */
 static int
 cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
-  struct cdv_intel_clock_t *clock)
+  struct cdv_intel_clock_t *clock, bool is_lvds)
 {
struct psb_intel_crtc *psb_crtc =
to_psb_intel_crtc(crtc);
@@ -224,6 +224,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct 
drm_crtc *crtc,
u32 m, n_vco, p;
int ret = 0;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+   int ref_sfr = (pipe == 0) ? SB_REF_DPLLA : SB_REF_DPLLB;
u32 ref_value;

cdv_sb_reset(dev);
@@ -241,6 +242,35 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct 
drm_crtc *crtc,
/* We don't know what the other fields of these regs are, so
 * leave them in place.
 */
+   /* 
+* The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk
+* for the pipe A/B. Display spec 1.06 has wrong definition.
+* Correct definition is like below:
+*
+* refclka mean use clock from same PLL
+*
+* if DPLLA sets 01 and DPLLB sets 01, they use clock from their pll
+*
+* if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA
+*
+*/  
+   ret = cdv_sb_read(dev, ref_sfr, _value);
+   if (ret)
+   return ret;
+   ref_value &= ~(REF_CLK_MASK);
+
+   /* use DPLL_A for pipeB on CRT/HDMI */
+   if (pipe == 1 && !is_lvds) {
+   DRM_DEBUG_KMS("use DPLLA for pipe B\n");
+   ref_value |= REF_CLK_DPLLA;
+   } else {
+   DRM_DEBUG_KMS("use their DPLL for pipe A/B\n");
+   ref_value |= REF_CLK_DPLL;
+   }
+   ret = cdv_sb_write(dev, ref_sfr, ref_value);
+   if (ret)
+   return ret;
+
ret = cdv_sb_read(dev, SB_M(pipe), );
if (ret)
return ret;
@@ -308,7 +338,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct 
drm_crtc *crtc,
return ret;

/* always Program the Lane Register for the Pipe A*/
-   if (pipe == 0) {
+/* if (pipe == 0) */ {
/* Program the Lane0/1 for HDMI B */
u32 lane_reg, lane_value;

@@ -553,6 +583,200 @@ psb_intel_pipe_set_base_exit:
return ret;
 }

+#defineFIFO_PIPEA  (1 << 0)
+#defineFIFO_PIPEB  (1 << 1)
+
+static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
+{
+   struct drm_crtc *crtc;
+   struct drm_psb_private *dev_priv = dev->dev_private;
+   struct psb_intel_crtc *psb_intel_crtc = NULL;
+
+   crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+   psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+   if (crtc->fb == NULL || !psb_intel_crtc->active)
+   return false;
+   return true;
+}
+
+static bool cdv_intel_single_pipe_active (struct drm_device *dev)
+{
+   uint32_t pipe_enabled = 0;
+
+   if (cdv_intel_pipe_enabled(dev, 0))
+   pipe_enabled |= FIFO_PIPEA;
+
+   if (cdv_intel_pipe_enabled(dev, 1))
+   pipe_enabled |= FIFO_PIPEB;
+
+
+   DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled);
+
+   if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB)
+   return true;
+   else
+   return false;
+}
+
+static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc)
+{
+   struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+   struct drm_mode_config *mode_config = >mode_config;
+   struct drm_connector *connector;
+
+   if (psb_intel_crtc->pipe != 1)
+   return false;
+
+   list_for_each_entry(connector, _config->connector_list, head) {
+   struct psb_intel_encoder *psb_intel_encoder =
+   psb_intel_attached_encoder(connector);
+
+   if (!connector->encoder
+   || connector->encoder->crtc != crtc)
+   continue;
+
+   if (psb_intel_encoder->type == INTEL_OUTPUT_LVDS)
+   return true;
+   }
+
+   return false;
+}
+
+static void cdv_intel_disable_self_refresh (struct drm_device *dev)
+{
+   if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) {
+
+   /* Disable self-refresh before adjust WM */
+   

[PATCH 02/12] gma500: read the PLL bits

2012-04-25 Thread Alan Cox
From: Alan Cox 

We need to pull more stuff from the VBT in order to configure the clocking
correctly in all cases. Add the relevant bits from the other CDV driver work.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/intel_bios.c |   18 
 drivers/gpu/drm/gma500/intel_bios.h |   39 +++
 drivers/gpu/drm/gma500/psb_drv.h|2 ++
 3 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/gma500/intel_bios.c 
b/drivers/gpu/drm/gma500/intel_bios.c
index d4d0c5b..51ea6df 100644
--- a/drivers/gpu/drm/gma500/intel_bios.c
+++ b/drivers/gpu/drm/gma500/intel_bios.c
@@ -217,6 +217,23 @@ static void parse_general_features(struct drm_psb_private 
*dev_priv,
}
 }

+static void
+parse_driver_features(struct drm_psb_private *dev_priv,
+ struct bdb_header *bdb)
+{
+   struct bdb_driver_features *driver;
+
+   driver = find_section(bdb, BDB_DRIVER_FEATURES);
+   if (!driver)
+   return;
+
+   /* This bit means to use 96Mhz for DPLL_A or not */
+   if (driver->primary_lfp_id)
+   dev_priv->dplla_96mhz = true;
+   else
+   dev_priv->dplla_96mhz = false;
+}
+
 /**
  * psb_intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -263,6 +280,7 @@ bool psb_intel_init_bios(struct drm_device *dev)

/* Grab useful general definitions */
parse_general_features(dev_priv, bdb);
+   parse_driver_features(dev_priv, bdb);
parse_lfp_panel_data(dev_priv, bdb);
parse_sdvo_panel_data(dev_priv, bdb);
parse_backlight_data(dev_priv, bdb);
diff --git a/drivers/gpu/drm/gma500/intel_bios.h 
b/drivers/gpu/drm/gma500/intel_bios.h
index 70f1bf0..c67979e 100644
--- a/drivers/gpu/drm/gma500/intel_bios.h
+++ b/drivers/gpu/drm/gma500/intel_bios.h
@@ -302,6 +302,45 @@ struct bdb_sdvo_lvds_options {
u8 panel_misc_bits_4;
 } __attribute__((packed));

+struct bdb_driver_features {
+   u8 boot_dev_algorithm:1;
+   u8 block_display_switch:1;
+   u8 allow_display_switch:1;
+   u8 hotplug_dvo:1;
+   u8 dual_view_zoom:1;
+   u8 int15h_hook:1;
+   u8 sprite_in_clone:1;
+   u8 primary_lfp_id:1;
+
+   u16 boot_mode_x;
+   u16 boot_mode_y;
+   u8 boot_mode_bpp;
+   u8 boot_mode_refresh;
+
+   u16 enable_lfp_primary:1;
+   u16 selective_mode_pruning:1;
+   u16 dual_frequency:1;
+   u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
+   u16 nt_clone_support:1;
+   u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+   u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
+   u16 cui_aspect_scaling:1;
+   u16 preserve_aspect_ratio:1;
+   u16 sdvo_device_power_down:1;
+   u16 crt_hotplug:1;
+   u16 lvds_config:2;
+   u16 tv_hotplug:1;
+   u16 hdmi_config:2;
+
+   u8 static_display:1;
+   u8 reserved2:7;
+   u16 legacy_crt_max_x;
+   u16 legacy_crt_max_y;
+   u8 legacy_crt_max_refresh;
+
+   u8 hdmi_termination;
+   u8 custom_vbt_version;
+} __attribute__((packed));

 extern bool psb_intel_init_bios(struct drm_device *dev);
 extern void psb_intel_destroy_bios(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 40ce2c9..4c50969 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -669,6 +669,8 @@ struct drm_psb_private {
u32 dspcntr[3];

int mdfld_panel_id;
+
+   bool dplla_96mhz;   /* DPLL data from the VBT */
 };





[PATCH 01/12] gma500: Fix leak of uncached page

2012-04-25 Thread Alan Cox
From: Alan Cox 

This was reported a long time ago (and I apologize to whoever it was that
reported it as I've lost the original report).

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/psb_drv.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 09af2ff..45bd0c7 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -246,6 +246,7 @@ static int psb_driver_unload(struct drm_device *dev)
}
psb_gtt_takedown(dev);
if (dev_priv->scratch_page) {
+   set_pages_wb(dev_priv->scratch_page, 1);
__free_page(dev_priv->scratch_page);
dev_priv->scratch_page = NULL;
}



[PATCH 00/12] GMA500 updates take 2

2012-04-25 Thread Alan Cox

This version drops the backlight patch while I figure how it breaks some
systems. It adds the now fixed hotplug monitor code.

---

Alan Cox (12):
  gma500: Set the mapping mask
  gma500: Add the base elements of CDV hotplug support
  gma500: Add ops for hotplug support.
  cdv: continue synching up with updated reference code
  gma500: Clean up weirdness in the cdv mode test code
  gma500: support 1080p
  gma500: panel presence check
  gma500: intel_bios updates
  gma500: mark framebuffer pages write combining
  gma500: Update the Cedarview clock handling
  gma500: read the PLL bits
  gma500: Fix leak of uncached page


 drivers/gpu/drm/gma500/cdv_device.c|   61 
 drivers/gpu/drm/gma500/cdv_intel_crt.c |   30 +-
 drivers/gpu/drm/gma500/cdv_intel_display.c |  390 +---
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c|7 -
 drivers/gpu/drm/gma500/cdv_intel_lvds.c|   74 +
 drivers/gpu/drm/gma500/framebuffer.c   |   29 ++
 drivers/gpu/drm/gma500/gem.c   |2 
 drivers/gpu/drm/gma500/gtt.c   |6 
 drivers/gpu/drm/gma500/intel_bios.c|  250 +-
 drivers/gpu/drm/gma500/intel_bios.h|  161 +++-
 drivers/gpu/drm/gma500/intel_opregion.c|  117 
 drivers/gpu/drm/gma500/mdfld_device.c  |2 
 drivers/gpu/drm/gma500/oaktrail_device.c   |2 
 drivers/gpu/drm/gma500/oaktrail_hdmi.c |6 
 drivers/gpu/drm/gma500/psb_device.c|2 
 drivers/gpu/drm/gma500/psb_drv.c   |1 
 drivers/gpu/drm/gma500/psb_drv.h   |   18 +
 drivers/gpu/drm/gma500/psb_intel_drv.h |3 
 drivers/gpu/drm/gma500/psb_intel_reg.h |   34 ++
 drivers/gpu/drm/gma500/psb_intel_sdvo.c|6 
 drivers/gpu/drm/gma500/psb_irq.c   |   30 ++
 21 files changed, 1035 insertions(+), 196 deletions(-)

-- 
Signature


[PATCH 3/3] gma500: don't register the ACPI video bus

2012-04-25 Thread Alan Cox
From: Alan Cox 

We are not yet ready for this and it makes a mess on some devices.

Signed-off-by: Alan Cox 
---

 drivers/gpu/drm/gma500/psb_drv.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index c34adf9..09af2ff 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -349,7 +349,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned 
long chipset)
PSB_WSGX32(0x3000, PSB_CR_BIF_3D_REQ_BASE);

 /* igd_opregion_init(_priv->opregion_dev); */
-   acpi_video_register();
+/* acpi_video_register(); */
if (dev_priv->lid_state)
psb_lid_timer_init(dev_priv);




[PATCH 2/3] acpi_video: Intel video is not always i915

2012-04-25 Thread Alan Cox
From: Alan Cox 

Stop it poking at random registers on the i740 cards that may be out there
still.

As per Matthew's feedback remove the conditional checks and never enable the
opregion handling unless an appropriate driver has been loaded.

Signed-off-by: Alan Cox 
---

 drivers/acpi/video.c |   20 +++-
 1 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 66e8f73..609262d 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1743,10 +1743,18 @@ static int acpi_video_bus_remove(struct acpi_device 
*device, int type)
return 0;
 }

+static int __init is_i740(struct pci_dev *dev)
+{
+   if (dev->device == 0x00D1)
+   return 1;
+   if (dev->device == 0x7000)
+   return 1;
+   return 0;
+}
+
 static int __init intel_opregion_present(void)
 {
-   int i915 = 0;
-#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
+   int opregion = 0;
struct pci_dev *dev = NULL;
u32 address;

@@ -1755,13 +1763,15 @@ static int __init intel_opregion_present(void)
continue;
if (dev->vendor != PCI_VENDOR_ID_INTEL)
continue;
+   /* We don't want to poke around undefined i740 registers */
+   if (is_i740(dev))
+   continue;
pci_read_config_dword(dev, 0xfc, );
if (!address)
continue;
-   i915 = 1;
+   opregion = 1;
}
-#endif
-   return i915;
+   return opregion;
 }

 int acpi_video_register(void)



[PATCH 1/3] acpi_video: fix leaking PCI references

2012-04-25 Thread Alan Cox
From: Alan Cox 

Signed-off-by: Alan Cox 
---

 drivers/acpi/video.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 9577b6f..66e8f73 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1745,6 +1745,7 @@ static int acpi_video_bus_remove(struct acpi_device 
*device, int type)

 static int __init intel_opregion_present(void)
 {
+   int i915 = 0;
 #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
struct pci_dev *dev = NULL;
u32 address;
@@ -1757,10 +1758,10 @@ static int __init intel_opregion_present(void)
pci_read_config_dword(dev, 0xfc, );
if (!address)
continue;
-   return 1;
+   i915 = 1;
}
 #endif
-   return 0;
+   return i915;
 }

 int acpi_video_register(void)



Reworking of GPU reset logic

2012-04-25 Thread Dave Airlie
2012/4/25 Christian K?nig :
> On 21.04.2012 16:14, Jerome Glisse wrote:
>>
>> 2012/4/21 Christian K?nig:
>>>
>>> On 20.04.2012 01:47, Jerome Glisse wrote:

 2012/4/19 Christian K?nig:
>
> This includes mostly fixes for multi ring lockups and GPU resets, but
> it
> should general improve the behavior of the kernel mode driver in case
> something goes badly wrong.
>
> On the other hand it completely rewrites the IB pool and semaphore
> handling, so I think there are still a couple of problems in it.
>
> The first four patches were already send to the list, but the current
> set
> depends on them so I resend them again.
>
> Cheers,
> Christian.

 I did a quick review, it looks mostly good, but as it's sensitive code
 i would like to spend sometime on
 it. Probably next week. Note that i had some work on this area too, i
 mostly want to drop all the debugfs
 related to this and add some new more usefull (basicly something that
 allow you to read all the data
 needed to replay a locking up ib). I also was looking into Dave reset
 thread and your solution of moving
 reset in ioctl return path sounds good too but i need to convince my
 self that it encompass all possible
 case.

 Cheers,
 Jerome

>>> After sleeping a night over it I already reworked the patch for improving
>>> the SA performance, so please wait at least for v2 before taking a look
>>> at
>>> it :)
>>>
>>> Regarding the debugging of lockups I had the following on my "in mind
>>> todo"
>>> list:
>>> 1. Rework the chip specific lockup detection code a bit more and probably
>>> clean it up a bit.
>>> 2. Make the timeout a module parameter, cause compute task sometimes
>>> block a
>>> ring for more than 10 seconds.
>>> 3. Keep track of the actually RPTR offset a fence is emitted to
>>> 3. Keep track of all the BOs a IB is touching.
>>> 4. Now if a lockup happens start with the last successfully signaled
>>> fence
>>> and dump the ring content after that RPTR offset till the first not
>>> signaled
>>> fence.
>>> 5. Then if this fence references to an IB dump it's content and the BOs
>>> it
>>> is touching.
>>> 6. Dump everything on the ring after that fence until you reach the RPTR
>>> of
>>> the next fence or the WPTR of the ring.
>>> 7. If there is a next fence repeat the whole thing at number 5.
>>>
>>> If I'm not completely wrong that should give you practically every
>>> information available, and we probably should put that behind another
>>> module
>>> option, cause we are going to spam syslog pretty much here. Feel free to
>>> add/modify the ideas on this list.
>>>
>>> Christian.
>>
>> What i have is similar, i am assuming only ib trigger lockup, before each
>> ib
>> emit to scratch reg ib offset in sa and ib size. For each ib keep bo list.
>> On
>> lockup allocate big memory to copy the whole ib and all the bo referenced
>> by the ib (i am using my bof format as i already have userspace tools).
>>
>> Remove all the debugfs file. Just add a new one that gave you the first
>> faulty
>> ib. On read of this file kernel free the memory. Kernel should also free
>> the
>> memory after a while or better would be to enable the lockup copy only if
>> some kernel radeon option is enabled.
>
>
> Just resent my current patchset to the mailing list, it's not as complete as
> your solution, but seems to be a step into the right direction. So please
> take a look at them.
>
> Being able to generate something like a "GPU crash dump" on lockup sounds
> like something very valuable to me, but I'm not sure if debugfs files are
> the right direction to go. Maybe something more like a module parameter
> containing a directory, and if set we dump all informations (including bo
> content) available in binary form (instead of the current human readable
> form of the debugfs files).

Do what intel driver does, create a versioned binary debugfs file with
all the error state in it for a lockup,
store only one of these at a time, run a userspace tool to dump it out
into something you can
upload or just cat the file and upload it.

You don't want the kernel writing to dirs on disk under any circumstances

Dave.


[PATCH 2/3] acpi_video: Intel video is not always i915

2012-04-25 Thread Alan Cox
On Wed, 25 Apr 2012 13:40:18 +0100
Matthew Garrett  wrote:

> On Wed, Apr 25, 2012 at 01:24:38PM +0100, Alan Cox wrote:
> 
> > Because as I said before there are two drivers involved and you may only
> > have one compiled into your kernel. If you have
> > 
> > CONFIG_DRM_GMA500=y
> > CONFIG_DRM_I915=n
> > 
> > you want the acpi stuff to autoregister even if an i915 is found, but not
> > if a GMA500 is found. Ditto the reverse.
> 
> No you don't - there's various platforms that will hang if you do that. 
> It's necessary to make sure that the DIDL fields are set up before 
> calling any ACPI video functions on opregion hardware.

Then the existing driver code is already broken, because it ifdefs out
the check if i915 is not compiled for the kernel.

Alan


[PATCH 2/3] acpi_video: Intel video is not always i915

2012-04-25 Thread Matthew Garrett
On Wed, Apr 25, 2012 at 01:49:40PM +0100, Alan Cox wrote:
> On Wed, 25 Apr 2012 13:40:18 +0100
> Matthew Garrett  wrote:
> > No you don't - there's various platforms that will hang if you do that. 
> > It's necessary to make sure that the DIDL fields are set up before 
> > calling any ACPI video functions on opregion hardware.
> 
> Then the existing driver code is already broken, because it ifdefs out
> the check if i915 is not compiled for the kernel.

Yes, that does seem broken. I'm fine with just removing the #ifdefs and 
adding the i740 check.

-- 
Matthew Garrett | mjg59 at srcf.ucam.org


extra mainly non working modes with drm-core next

2012-04-25 Thread Andy Furniss
I guess the extra modes with the new code in drm-core-next are crucial 
for some, but it does generate a lot of extra non working modes for me.

With the previous behavior xrandr would list modes that all worked - 
although there are a few new ones that work on my monitor there are a 
lot that don't and for my TV I don't think any new one works.

I see from xorg log that the old DDC gethered modes are still listed - 
maybe if all these extra modes are needed/not being listed in error a 
new xrandr option to list "safe" modes or one to list the new modes with 
safe being default would be more user friendly.

Attached are xrandr --verbose before and after in case anyone is interested.

DVI-0 is a plasma 1920x1080 TV via hdmi (dvi adapter)

DVI-1 is a lcd 1920x1080 120Hz monitor.



-- next part --
Screen 0: minimum 320 x 200, current 1920 x 2160, maximum 8192 x 8192
DVI-0 connected 1920x1080+0+1080 (0x165) normal (normal left inverted right x 
axis y axis) 698mm x 392mm
Identifier: 0x51
Timestamp:  453168
Subpixel:   horizontal rgb
Gamma:  1.0:1.0:1.0
Brightness: 1.0
Clones:
CRTC:   1
CRTCs:  0 1
Transform:  1.00 0.00 0.00
0.00 1.00 0.00
0.00 0.00 1.00
   filter: 
EDID:
000034a9a6a001010101
0014010380780adaffa3584aa229
17494b0001010101010101010101
010101010101023a80d072382d40102c
4580ba88211e023a801871382d40
582c4500ba88211e00fc0050
616e61736f6e69632d54560a00fd
00173d0f440f000a20202020202001d1
02032672509f90140520130412031102
16071506012309070168030c003000b8
260fe3051f01011d80d0721c1620102c
2580ba88219e011d8018711c1620
582c2500ba88219e011d00bc52d0
1e20b8285540ba88211e011d0072
51d01e206e285500ba88211e
00a1
load detection: 1 (0x0001)  range:  (0,1)
underscan vborder: 0 (0x)   range:  (0,128)
underscan hborder: 0 (0x)   range:  (0,128)
underscan:  off
supported: off  on   auto
coherent: 1 (0x0001)range:  (0,1)
  1920x1080 (0x165)  148.5MHz +HSync +VSync *current +preferred
h: width  1920 start 2448 end 2492 total 2640 skew0 clock   56.2KHz
v: height 1080 start 1084 end 1089 total 1125   clock   50.0Hz
  1920x1080 (0x54)  148.5MHz +HSync +VSync
h: width  1920 start 2008 end 2052 total 2200 skew0 clock   67.5KHz
v: height 1080 start 1084 end 1089 total 1125   clock   60.0Hz
  1920x1080 (0x166)   74.2MHz +HSync +VSync
h: width  1920 start 2558 end 2602 total 2750 skew0 clock   27.0KHz
v: height 1080 start 1084 end 1089 total 1125   clock   24.0Hz
  1920x1080 (0x167)   74.2MHz +HSync +VSync Interlace
h: width  1920 start 2008 end 2052 total 2200 skew0 clock   33.8KHz
v: height 1080 start 1084 end 1094 total 1125   clock   30.0Hz
  1920x1080 (0x168)   74.2MHz +HSync +VSync Interlace
h: width  1920 start 2448 end 2492 total 2640 skew0 clock   28.1KHz
v: height 1080 start 1084 end 1094 total 1125   clock   25.0Hz
  1280x720 (0x169)   74.2MHz +HSync +VSync
h: width  1280 start 1390 end 1430 total 1650 skew0 clock   45.0KHz
v: height  720 start  725 end  730 total  750   clock   60.0Hz
  1280x720 (0x16a)   74.2MHz +HSync +VSync
h: width  1280 start 1720 end 1760 total 1980 skew0 clock   37.5KHz
v: height  720 start  725 end  730 total  750   clock   50.0Hz
  1440x576 (0x16b)   27.0MHz -HSync -VSync Interlace
h: width  1440 start 1464 end 1590 total 1728 skew0 clock   15.6KHz
v: height  576 start  580 end  586 total  625   clock   25.0Hz
  1440x480 (0x16c)   27.0MHz -HSync -VSync Interlace
h: width  1440 start 1478 end 1602 total 1716 skew0 clock   15.7KHz
v: height  480 start  488 end  494 total  525   clock   30.0Hz
  720x576 (0x16d)   27.0MHz -HSync -VSync
h: width   720 start  732 end  796 total  864 skew0 clock   31.2KHz
v: height  576 start  581 end  586 total  625   clock   50.0Hz
  720x480 (0x16e)   27.0MHz -HSync -VSync
h: width   720 start  736 end  798 total  858 skew0 clock   31.5KHz
v: height  480 start  489 end  495 total  525   clock   59.9Hz
  640x480 (0x16f)   25.2MHz -HSync -VSync
h: width   640 start  656 end  752 total  800 skew0 clock   31.5KHz
v: height  480 start  490 end  492 total  525   clock   59.9Hz

[Bug 45018] [bisected] rendering regression since added support for virtual address space on cayman v11

2012-04-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=45018

--- Comment #46 from Alex Deucher  2012-04-25 06:41:45 PDT 
---
Does this kernel patch help?
http://lists.freedesktop.org/archives/dri-devel/2012-April/022037.html

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH 2/3] acpi_video: Intel video is not always i915

2012-04-25 Thread Matthew Garrett
On Wed, Apr 25, 2012 at 01:24:38PM +0100, Alan Cox wrote:

> Because as I said before there are two drivers involved and you may only
> have one compiled into your kernel. If you have
> 
> CONFIG_DRM_GMA500=y
> CONFIG_DRM_I915=n
> 
> you want the acpi stuff to autoregister even if an i915 is found, but not
> if a GMA500 is found. Ditto the reverse.

No you don't - there's various platforms that will hang if you do that. 
It's necessary to make sure that the DIDL fields are set up before 
calling any ACPI video functions on opregion hardware.

-- 
Matthew Garrett | mjg59 at srcf.ucam.org


[PATCH 2/3] acpi_video: Intel video is not always i915

2012-04-25 Thread Alan Cox
On Wed, 25 Apr 2012 12:31:52 +0100
Matthew Garrett  wrote:

> On Wed, Apr 25, 2012 at 11:27:11AM +0100, Alan Cox wrote:
> > On Tue, 24 Apr 2012 23:30:22 +0100
> > Matthew Garrett  wrote:
> > > Right now you seem to set opregion unconditionally on PVR, which seems 
> > > to be equivalent to the 0xfc check that was there before - I can 
> > > understand excluding i740, but the PVR check could be left with the gen 
> > > hardware one?
> > 
> > Not really - they are two drivers. If you build with i915 and not GMA500
> > you need the opregion for one and the acpi fallback for the other, and
> > vice versa. So we have to check both CONFIG_xxx macro sets.
> > 
> > Right now GMA500 needs the ACPI video stuff never to be enabled on some
> > machines. Until we've got full opregion support in the driver that won't
> > change.
> 
> opregion always seems to be set to 1 if is_gma_pvr() is true, which 
> means we'll now never bind the acpi video driver on PVR hardware. If 
> that's what you want, why distinguish between PVR and GEN?

Because as I said before there are two drivers involved and you may only
have one compiled into your kernel. If you have

CONFIG_DRM_GMA500=y
CONFIG_DRM_I915=n

you want the acpi stuff to autoregister even if an i915 is found, but not
if a GMA500 is found. Ditto the reverse.

Alan


[RFC v2 2/5] tps6586x: Add device tree support

2012-04-25 Thread Thierry Reding
* Mark Brown wrote:
> On Wed, Apr 25, 2012 at 12:41:47PM +0200, Thierry Reding wrote:
> 
> > After taking a closer look I don't think Rhyland's patch is very useful for
> > this driver. I need to lookup the platform ID by regulator name anyway so
> > using the new code is actually more work and requires a second table that
> > lists the regulator names only.
> 
> Why do you need the plaform ID, and if it is needed could we work out a
> way to make the generic code do that lookup for you (since presumably
> other drivers will have the same requirement)?  If you can't use the
> generic code it seems like the fix is to enhance the generic code and
> I'd expect that something not requiring the platform ID would just be
> able to igore that information if the generic code could look it up.

Basically the platform ID is used by the regulator driver to differentiate
between the different types of regulators. I could imagine a more advanced
setup to do the matching, along the lines of OF device matching and platform
device matching, where an entry in the table has both a name and an
associated "driver data" field.

For instance we could have a new structure:

struct regulator_lookup_data {
const char *name;
unsigned long driver_data;
struct regulator_init_data *init_data;
struct device_node *of_node;
};

static struct regulator_lookup_data tps6586x_lookup[] = {
{ .name = "sm0", .driver_data = TPS6586X_ID_SM_0 },
{ .name = "sm1", .driver_data = TPS6586X_ID_SM_1 },
...
};

And pass that into of_find_regulator_init_data_from_device():

of_find_regulator_init_data_from_device(>dev, regulators,
tps6586x_lookup,
ARRAY_SIZE(tps6586x_lookup));

Upon return, the tps6586x_lookup table will have the init_data and of_node
fields filled with the data parsed from the DT. Then we can simply iterate
over all entries and add the corresponding regulators.

This is somewhat ugly because of_find_regulator_init_data_from_device() would
modify the same data structure for potentially different devices. This should
be okay because the driver core takes care of serializing device probing
(unless I am mistaken). Alternatively we could make the function return a
copy of the regulator_lookup_data structure with the additional fields filled
in.

Thierry
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120425/1ad4520a/attachment.pgp>


[Nouveau] [RFC PATCH 5/5] drm/nouveau: gpu lockup recovery

2012-04-25 Thread Christoph Bumiller
On 04/23/2012 06:32 PM, Marcin Slusarz wrote:
> You can run fs-discard-exit-2 test first - for me it causes instant GPU 
> lockup.
> 

That's because it's designed (but not supposed) to do that, it also
locks up with the blob, it's a harmless shader infinite loop.

(May be a bug in the MPs or a wrong setting somewhere, but they don't
pop the control flow stack if all but killed pixels of a partially
killed quad remain on the current execution path).

Activated the watchdog on nv50 now, too, if you want to produce the
lockup with current mesa git run with NOUVEAU_SHADER_WATCHDOG=0 (yes
when we use COMPUTE it will have to be deactivated as well).

> Marcin
> ___
> Nouveau mailing list
> Nouveau at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/nouveau
> 



[RFC v2 2/5] tps6586x: Add device tree support

2012-04-25 Thread Thierry Reding
* Thierry Reding wrote:
> * Mark Brown wrote:
> > On Wed, Apr 25, 2012 at 11:44:59AM +0200, Thierry Reding wrote:
> > > This commit adds device tree support for the TPS6586x regulator.
> > > 
> > > Signed-off-by: Thierry Reding 
> > 
> > This looks basically good from a quick scan through but the pattern of
> > looking up regulator nodes by name is very common so should be factored
> > out - I made a similar comment in response to a recent patch from
> > Rhyland Klein and earlier today he posted a patch "regulator: add
> > generic of node parsing for regulators" which does just that.  Can you
> > please redo this on top of his code?  I'll probably apply it later
> > today, though I didn't properly read the code yet.
> 
> I'll take a look.

After taking a closer look I don't think Rhyland's patch is very useful for
this driver. I need to lookup the platform ID by regulator name anyway so
using the new code is actually more work and requires a second table that
lists the regulator names only.

Thierry
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120425/b8dcc329/attachment.pgp>


[PATCH 2/3] acpi_video: Intel video is not always i915

2012-04-25 Thread Matthew Garrett
On Wed, Apr 25, 2012 at 11:27:11AM +0100, Alan Cox wrote:
> On Tue, 24 Apr 2012 23:30:22 +0100
> Matthew Garrett  wrote:
> > Right now you seem to set opregion unconditionally on PVR, which seems 
> > to be equivalent to the 0xfc check that was there before - I can 
> > understand excluding i740, but the PVR check could be left with the gen 
> > hardware one?
> 
> Not really - they are two drivers. If you build with i915 and not GMA500
> you need the opregion for one and the acpi fallback for the other, and
> vice versa. So we have to check both CONFIG_xxx macro sets.
> 
> Right now GMA500 needs the ACPI video stuff never to be enabled on some
> machines. Until we've got full opregion support in the driver that won't
> change.

opregion always seems to be set to 1 if is_gma_pvr() is true, which 
means we'll now never bind the acpi video driver on PVR hardware. If 
that's what you want, why distinguish between PVR and GEN?

-- 
Matthew Garrett | mjg59 at srcf.ucam.org


[Bug 49140] New: r600_state_common.c:761:r600_draw_vbo: Assertion `0' failed

2012-04-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=49140

 Bug #: 49140
   Summary: r600_state_common.c:761:r600_draw_vbo: Assertion `0'
failed
Classification: Unclassified
   Product: Mesa
   Version: git
  Platform: All
OS/Version: Linux (All)
Status: NEW
  Severity: normal
  Priority: medium
 Component: Drivers/Gallium/r600
AssignedTo: dri-devel at lists.freedesktop.org
ReportedBy: bgz.marko at gmail.com


Created attachment 60568
  --> https://bugs.freedesktop.org/attachment.cgi?id=60568
R600_DUMP_SHADERS

Hello,

I have an application using a rather complex shader with some branching -
while/if. Applications fails with r600 driver giving the following error:

EE r600_shader.c:140 r600_pipe_shader_create - translation from TGSI failed !
r600_state_common.c:761:r600_draw_vbo: Assertion `0' failed.

It seems something goes wrong in the branching section, since it works if I
comment it. The same shader works fine using either LIBGL_ALWAYS_SOFTWARE=1 or
fglrx. Also, I can remember working it fine with some older revision of R600,
unfortunately I don't know which one exactly.

I have attached R600_DUMP_SHADERS output. If needed I can also provide links to
source code or any other data that may be helpful in debugging.

Some relevant parts of glxinfo:

OpenGL vendor string: X.Org
OpenGL renderer string: Gallium 0.4 on AMD RV770
OpenGL version string: 2.1 Mesa 8.1-devel (git-1a33c1b precise-oibaf-ppa)

Best regards,
Marko

-- 
Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email
--- You are receiving this mail because: ---
You are the assignee for the bug.


[PATCH 26/26] drm/radeon: add the ib content and relocs to the ring debugfs file

2012-04-25 Thread Jerome Glisse
2012/4/25 Christian K?nig :
> On 25.04.2012 16:36, Jerome Glisse wrote:
>>
>> NAK i would rather have a full dump as i described. I can do a patch
>> for that if you want.
>>
> I don't stick with those files neither, just wanted to restore the same
> functionality as we had before.
>
> Just finished a conference call with Alex and the rest of the team, and Alex
> suggested that we stick with the AMD internal binary format for crash dumps.
> With that we could reuse the AMD internal tools, but the obvious downside is
> that those aren't available to you (for example).
>
> We should sync with Alex how that format looks like, and if we
> could/should/whatever move the driver to wards it.
>
> Cheers,
> Christian.
>
> PS: I'm not at home this evening, so please answer on my AMD mail address
> also.


I don't know the AMD format, what i propose is take the easier format
for kernel side.
If it's not amd we can do a tools to convert from blob to amd in userspace.

blob format is something like:
u32 type
u32 id
u32 size (dword aligned)
data (dword aligned)

So it's very primitive. I am finishing patch to do that will send it shortly.

Cheers,
Jerome


[RFC v2 2/5] tps6586x: Add device tree support

2012-04-25 Thread Mark Brown
On Wed, Apr 25, 2012 at 12:41:47PM +0200, Thierry Reding wrote:

> After taking a closer look I don't think Rhyland's patch is very useful for
> this driver. I need to lookup the platform ID by regulator name anyway so
> using the new code is actually more work and requires a second table that
> lists the regulator names only.

Why do you need the plaform ID, and if it is needed could we work out a
way to make the generic code do that lookup for you (since presumably
other drivers will have the same requirement)?  If you can't use the
generic code it seems like the fix is to enhance the generic code and
I'd expect that something not requiring the platform ID would just be
able to igore that information if the generic code could look it up.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20120425/86f40812/attachment.pgp>


[RFC v2 5/5] drm: Add NVIDIA Tegra support

2012-04-25 Thread Thierry Reding
This commit adds a very basic DRM driver for NVIDIA Tegra SoCs. It
currently has rudimentary GEM support and can run a console on the
framebuffer as well as X using the xf86-video-modesetting driver. Only
the RGB output is supported.

HDMI support was taken from NVIDIA's Linux kernel tree but it doesn't
quite work. EDID data can be retrieved but the output doesn't properly
activate the connected TV.

The DSI and TVO outputs and the HOST1X driver are just stubs that setup
the corresponding resources but don't do anything useful yet.

Signed-off-by: Thierry Reding 
---
 .../devicetree/bindings/gpu/drm/tegra.txt  |  125 +++
 arch/arm/mach-tegra/board-dt-tegra20.c |   14 +
 arch/arm/mach-tegra/include/mach/iomap.h   |6 +
 arch/arm/mach-tegra/tegra2_clocks.c|   19 +-
 drivers/gpu/drm/Kconfig|2 +
 drivers/gpu/drm/Makefile   |1 +
 drivers/gpu/drm/tegra/Kconfig  |   19 +
 drivers/gpu/drm/tegra/Makefile |7 +
 drivers/gpu/drm/tegra/tegra-dc.c   |  630 +
 drivers/gpu/drm/tegra/tegra-dc.h   |  245 +
 drivers/gpu/drm/tegra/tegra-drv.c  |  600 
 drivers/gpu/drm/tegra/tegra-drv.h  |  201 
 drivers/gpu/drm/tegra/tegra-dsi.c  |  145 +++
 drivers/gpu/drm/tegra/tegra-encon.c|  406 
 drivers/gpu/drm/tegra/tegra-fb.c   |  355 +++
 drivers/gpu/drm/tegra/tegra-gem.c  |  425 +
 drivers/gpu/drm/tegra/tegra-hdmi.c |  994 
 drivers/gpu/drm/tegra/tegra-hdmi.h |  462 +
 drivers/gpu/drm/tegra/tegra-host1x.c   |   90 ++
 drivers/gpu/drm/tegra/tegra-rgb.c  |  148 +++
 drivers/gpu/drm/tegra/tegra-tvo.c  |  152 +++
 include/drm/tegra_drm.h|   40 +
 22 files changed, 5075 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpu/drm/tegra.txt
 create mode 100644 drivers/gpu/drm/tegra/Kconfig
 create mode 100644 drivers/gpu/drm/tegra/Makefile
 create mode 100644 drivers/gpu/drm/tegra/tegra-dc.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-dc.h
 create mode 100644 drivers/gpu/drm/tegra/tegra-drv.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-drv.h
 create mode 100644 drivers/gpu/drm/tegra/tegra-dsi.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-encon.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-fb.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-gem.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-hdmi.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-hdmi.h
 create mode 100644 drivers/gpu/drm/tegra/tegra-host1x.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-rgb.c
 create mode 100644 drivers/gpu/drm/tegra/tegra-tvo.c
 create mode 100644 include/drm/tegra_drm.h

diff --git a/Documentation/devicetree/bindings/gpu/drm/tegra.txt 
b/Documentation/devicetree/bindings/gpu/drm/tegra.txt
new file mode 100644
index 000..6c23155
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/drm/tegra.txt
@@ -0,0 +1,125 @@
+Example:
+
+/memreserve/ 0x0e00 0x0200;
+
+...
+
+/ {
+   ...
+
+   /* host1x */
+   host1x: host1x at 5000 {
+   compatible = "nvidia,tegra20-host1x";
+   reg = <0x5000 0x00024000>;
+   interrupts = <0 64 0x04   /* cop syncpt */
+ 0 65 0x04   /* mpcore syncpt */
+ 0 66 0x04   /* cop general */
+ 0 67 0x04>; /* mpcore general */
+   };
+
+   /* video-encoding/decoding */
+   mpe at 5404 {
+   reg = <0x5404 0x0004>;
+   interrupts = <0 68 0x04>;
+   };
+
+   /* video input */
+   vi at 5408 {
+   reg = <0x5408 0x0004>;
+   interrupts = <0 69 0x04>;
+   };
+
+   /* EPP */
+   epp at 540c {
+   reg = <0x540c 0x0004>;
+   interrupts = <0 70 0x04>;
+   };
+
+   /* ISP */
+   isp at 5410 {
+   reg = <0x5410 0x0004>;
+   interrupts = <0 71 0x04>;
+   };
+
+   /* 2D engine */
+   gr2d at 5414 {
+   reg = <0x5414 0x0004>;
+   interrupts = <0 72 0x04>;
+   };
+
+   /* 3D engine */
+   gr3d at 5418 {
+   reg = <0x5418 0x0004>;
+   };
+
+   /* display controllers */
+   disp1: dc at 5420 {
+   compatible = "nvidia,tegra20-dc";
+   reg = <0x5420 0x0004>;
+   interrupts = <0 73 0x04>;
+   };
+
+   disp2: dc at 5424 {
+   compatible = "nvidia,tegra20-dc";
+   reg = <0x5424 0x0004>;
+   interrupts = <0 74 0x04>;
+

  1   2   3   >