2009-06-22 16:24:43

by Jerome Glisse

[permalink] [raw]
Subject: [PATCH 1/2] radeon: fix radeon kms framebuffer device

smem.start is a physical address which kernel can remap to access
video memory of the fb buffer. We now pin the fb buffer into vram
by doing so we are loosing vram but fbdev need to be reworked to
allow change in framebuffer address.

Signed-off-by: Jerome Glisse <[email protected]>
---
drivers/gpu/drm/radeon/radeon_device.c | 4 ----
drivers/gpu/drm/radeon/radeon_fb.c | 27 +++++++++++++++++++--------
drivers/gpu/drm/radeon/radeon_object.c | 30 ------------------------------
3 files changed, 19 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index f30aa72..3f48a57 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -496,7 +496,6 @@ int radeon_device_init(struct radeon_device *rdev,
radeon_errata(rdev);
/* Initialize scratch registers */
radeon_scratch_init(rdev);
-
/* TODO: disable VGA need to use VGA request */
/* BIOS*/
if (!radeon_get_bios(rdev)) {
@@ -604,9 +603,6 @@ int radeon_device_init(struct radeon_device *rdev,
if (r) {
return r;
}
- if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) {
- rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private;
- }
if (!ret) {
DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
}
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index fa86d39..0998708 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -478,14 +478,16 @@ int radeonfb_create(struct radeon_device *rdev,
{
struct fb_info *info;
struct radeon_fb_device *rfbdev;
- struct drm_framebuffer *fb;
+ struct drm_framebuffer *fb = NULL;
struct radeon_framebuffer *rfb;
struct drm_mode_fb_cmd mode_cmd;
struct drm_gem_object *gobj = NULL;
struct radeon_object *robj = NULL;
struct device *device = &rdev->pdev->dev;
int size, aligned_size, ret;
+ u64 fb_gpuaddr;
void *fbptr = NULL;
+ unsigned long tmp;

mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
@@ -498,11 +500,12 @@ int radeonfb_create(struct radeon_device *rdev,
aligned_size = ALIGN(size, PAGE_SIZE);

ret = radeon_gem_object_create(rdev, aligned_size, 0,
- RADEON_GEM_DOMAIN_VRAM,
- false, ttm_bo_type_kernel,
- false, &gobj);
+ RADEON_GEM_DOMAIN_VRAM,
+ false, ttm_bo_type_kernel,
+ false, &gobj);
if (ret) {
- printk(KERN_ERR "failed to allocate framebuffer\n");
+ printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
+ surface_width, surface_height);
ret = -ENOMEM;
goto out;
}
@@ -515,12 +518,19 @@ int radeonfb_create(struct radeon_device *rdev,
ret = -ENOMEM;
goto out_unref;
}
+ ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
+ if (ret) {
+ printk(KERN_ERR "failed to pin framebuffer\n");
+ ret = -ENOMEM;
+ goto out_unref;
+ }

list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);

rfb = to_radeon_framebuffer(fb);
*rfb_p = rfb;
rdev->fbdev_rfb = rfb;
+ rdev->fbdev_robj = robj;

info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
if (info == NULL) {
@@ -546,8 +556,8 @@ int radeonfb_create(struct radeon_device *rdev,
info->flags = FBINFO_DEFAULT;
info->fbops = &radeonfb_ops;
info->fix.line_length = fb->pitch;
- info->screen_base = fbptr;
- info->fix.smem_start = (unsigned long)fbptr;
+ tmp = fb_gpuaddr - rdev->mc.vram_location;
+ info->fix.smem_start = rdev->mc.aper_base + tmp;
info->fix.smem_len = size;
info->screen_base = fbptr;
info->screen_size = size;
@@ -644,7 +654,7 @@ out_unref:
if (robj) {
radeon_object_kunmap(robj);
}
- if (ret) {
+ if (fb && ret) {
list_del(&fb->filp_head);
drm_gem_object_unreference(gobj);
drm_framebuffer_cleanup(fb);
@@ -813,6 +823,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
robj = rfb->obj->driver_private;
unregister_framebuffer(info);
radeon_object_kunmap(robj);
+ radeon_object_unpin(robj);
framebuffer_release(info);
}

diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 983e8df..bac0d06 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -223,7 +223,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
{
uint32_t flags;
uint32_t tmp;
- void *fbptr;
int r;

flags = radeon_object_flags_from_domain(domain);
@@ -242,10 +241,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
DRM_ERROR("radeon: failed to reserve object for pinning it.\n");
return r;
}
- if (robj->rdev->fbdev_robj == robj) {
- mutex_lock(&robj->rdev->fbdev_info->lock);
- radeon_object_kunmap(robj);
- }
tmp = robj->tobj.mem.placement;
ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM);
robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING;
@@ -261,23 +256,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
DRM_ERROR("radeon: failed to pin object.\n");
}
radeon_object_unreserve(robj);
- if (robj->rdev->fbdev_robj == robj) {
- if (!r) {
- r = radeon_object_kmap(robj, &fbptr);
- }
- if (!r) {
- robj->rdev->fbdev_info->screen_base = fbptr;
- robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr;
- }
- mutex_unlock(&robj->rdev->fbdev_info->lock);
- }
return r;
}

void radeon_object_unpin(struct radeon_object *robj)
{
uint32_t flags;
- void *fbptr;
int r;

spin_lock(&robj->tobj.lock);
@@ -297,10 +281,6 @@ void radeon_object_unpin(struct radeon_object *robj)
DRM_ERROR("radeon: failed to reserve object for unpinning it.\n");
return;
}
- if (robj->rdev->fbdev_robj == robj) {
- mutex_lock(&robj->rdev->fbdev_info->lock);
- radeon_object_kunmap(robj);
- }
flags = robj->tobj.mem.placement;
robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT;
r = ttm_buffer_object_validate(&robj->tobj,
@@ -310,16 +290,6 @@ void radeon_object_unpin(struct radeon_object *robj)
DRM_ERROR("radeon: failed to unpin buffer.\n");
}
radeon_object_unreserve(robj);
- if (robj->rdev->fbdev_robj == robj) {
- if (!r) {
- r = radeon_object_kmap(robj, &fbptr);
- }
- if (!r) {
- robj->rdev->fbdev_info->screen_base = fbptr;
- robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr;
- }
- mutex_unlock(&robj->rdev->fbdev_info->lock);
- }
}

int radeon_object_wait(struct radeon_object *robj)
--
1.6.2.2


2009-06-23 02:39:30

by Andrew Lutomirski

[permalink] [raw]
Subject: Re: [PATCH 1/2] radeon: fix radeon kms framebuffer device

Jerome Glisse wrote:
> smem.start is a physical address which kernel can remap to access
> video memory of the fb buffer. We now pin the fb buffer into vram
> by doing so we are loosing vram but fbdev need to be reworked to
> allow change in framebuffer address.

I tested this (and the corresponding 2/2 initialization order, but with
radeon as a module), and plymouth seems to be fully functional
(graphical boot, password prompt, etc).

(The driver set the wrong mode, but that's a different issue.)

Thanks!

Tested-by: Andy Lutomirski <[email protected]>

2009-06-23 13:13:14

by Andrew Lutomirski

[permalink] [raw]
Subject: Re: [PATCH 1/2] radeon: fix radeon kms framebuffer device

Andy Lutomirski wrote:
> Jerome Glisse wrote:
>> smem.start is a physical address which kernel can remap to access
>> video memory of the fb buffer. We now pin the fb buffer into vram
>> by doing so we are loosing vram but fbdev need to be reworked to
>> allow change in framebuffer address.
>
> I tested this (and the corresponding 2/2 initialization order, but
> with radeon as a module), and plymouth seems to be fully functional
> (graphical boot, password prompt, etc).
>
> (The driver set the wrong mode, but that's a different issue.)
>
> Thanks!
>
> Tested-by: Andy Lutomirski <[email protected]>
>
Got an oops after awhile:

BUG: Bad page state in process gpg-agent pfn:37dd5
page:ffffea0000c38698 flags:200000000050000c count:0 mapcount:0
mapping:(null) index:7fd35e311
Pid: 3131, comm: gpg-agent Not tainted 2.6.30 #5
Call Trace:
[<ffffffff810bc99b>] bad_page+0x115/0x13e
[<ffffffff810bcbd3>] free_pages_check+0x3c/0x6d
[<ffffffff810bde8f>] free_hot_cold_page+0x4e/0x151
[<ffffffff810bdfce>] __pagevec_free+0x3c/0x65
[<ffffffff810c1c82>] release_pages+0x1a5/0x1cb
[<ffffffff810de357>] free_pages_and_swap_cache+0x6d/0x9e
[<ffffffff810d584b>] tlb_finish_mmu+0x41/0x63
[<ffffffff810d5b3f>] exit_mmap+0xfb/0x138
[<ffffffff8104beae>] mmput+0x55/0xc1
[<ffffffff81050626>] exit_mm+0x10e/0x12f
[<ffffffff8105226f>] do_exit+0x1b4/0x6a8
[<ffffffff8106c6b0>] ? up_read+0x1c/0x32
[<ffffffff810527e2>] do_group_exit+0x7f/0xac
[<ffffffff81052834>] sys_exit_group+0x25/0x3d
[<ffffffff8100beab>] system_call_fastpath+0x16/0x1b

I don't know if this is related to the drm changes.

Back to 2.6.29 for me :) (I actually use this machine, so I'd rather
not run kernels that cause random corruption.)

--Andy

2009-06-23 13:36:24

by Jerome Glisse

[permalink] [raw]
Subject: Re: [PATCH 1/2] radeon: fix radeon kms framebuffer device

On Tue, 2009-06-23 at 09:12 -0400, Andy Lutomirski wrote:
> Andy Lutomirski wrote:
> > Jerome Glisse wrote:
> >> smem.start is a physical address which kernel can remap to access
> >> video memory of the fb buffer. We now pin the fb buffer into vram
> >> by doing so we are loosing vram but fbdev need to be reworked to
> >> allow change in framebuffer address.
> >
> > I tested this (and the corresponding 2/2 initialization order, but
> > with radeon as a module), and plymouth seems to be fully functional
> > (graphical boot, password prompt, etc).
> >
> > (The driver set the wrong mode, but that's a different issue.)
> >
> > Thanks!
> >
> > Tested-by: Andy Lutomirski <[email protected]>
> >
> Got an oops after awhile:
>
> BUG: Bad page state in process gpg-agent pfn:37dd5
> page:ffffea0000c38698 flags:200000000050000c count:0 mapcount:0
> mapping:(null) index:7fd35e311
> Pid: 3131, comm: gpg-agent Not tainted 2.6.30 #5
> Call Trace:
> [<ffffffff810bc99b>] bad_page+0x115/0x13e
> [<ffffffff810bcbd3>] free_pages_check+0x3c/0x6d
> [<ffffffff810bde8f>] free_hot_cold_page+0x4e/0x151
> [<ffffffff810bdfce>] __pagevec_free+0x3c/0x65
> [<ffffffff810c1c82>] release_pages+0x1a5/0x1cb
> [<ffffffff810de357>] free_pages_and_swap_cache+0x6d/0x9e
> [<ffffffff810d584b>] tlb_finish_mmu+0x41/0x63
> [<ffffffff810d5b3f>] exit_mmap+0xfb/0x138
> [<ffffffff8104beae>] mmput+0x55/0xc1
> [<ffffffff81050626>] exit_mm+0x10e/0x12f
> [<ffffffff8105226f>] do_exit+0x1b4/0x6a8
> [<ffffffff8106c6b0>] ? up_read+0x1c/0x32
> [<ffffffff810527e2>] do_group_exit+0x7f/0xac
> [<ffffffff81052834>] sys_exit_group+0x25/0x3d
> [<ffffffff8100beab>] system_call_fastpath+0x16/0x1b
>
> I don't know if this is related to the drm changes.
>
> Back to 2.6.29 for me :) (I actually use this machine, so I'd rather
> not run kernels that cause random corruption.)
>
> --Andy

Could you get a trace using Linus pte check patch he posted earlier
on the other thread ?

Jerome

2009-06-24 05:26:40

by Andrew Lutomirski

[permalink] [raw]
Subject: Re: [PATCH 1/2] radeon: fix radeon kms framebuffer device

On Tue, Jun 23, 2009 at 9:35 AM, Jerome Glisse<[email protected]> wrote:
> On Tue, 2009-06-23 at 09:12 -0400, Andy Lutomirski wrote:
>> Andy Lutomirski wrote:
>> > Jerome Glisse wrote:
>> >> smem.start is a physical address which kernel can remap to access
>> >> video memory of the fb buffer. We now pin the fb buffer into vram
>> >> by doing so we are loosing vram but fbdev need to be reworked to
>> >> allow change in framebuffer address.
>> >
>> > I tested this (and the corresponding 2/2 initialization order, but
>> > with radeon as a module), and plymouth seems to be fully functional
>> > (graphical boot, password prompt, etc).
>> >
>> > (The driver set the wrong mode, but that's a different issue.)
>> >
>> > Thanks!
>> >
>> > Tested-by: Andy Lutomirski <[email protected]>
>> >
>> Got an oops after awhile:
>>
>> BUG: Bad page state in process gpg-agent ?pfn:37dd5
>> page:ffffea0000c38698 flags:200000000050000c count:0 mapcount:0
>> mapping:(null) index:7fd35e311
>> Pid: 3131, comm: gpg-agent Not tainted 2.6.30 #5
>> Call Trace:
>> ?[<ffffffff810bc99b>] bad_page+0x115/0x13e
>> ?[<ffffffff810bcbd3>] free_pages_check+0x3c/0x6d
>> ?[<ffffffff810bde8f>] free_hot_cold_page+0x4e/0x151
>> ?[<ffffffff810bdfce>] __pagevec_free+0x3c/0x65
>> ?[<ffffffff810c1c82>] release_pages+0x1a5/0x1cb
>> ?[<ffffffff810de357>] free_pages_and_swap_cache+0x6d/0x9e
>> ?[<ffffffff810d584b>] tlb_finish_mmu+0x41/0x63
>> ?[<ffffffff810d5b3f>] exit_mmap+0xfb/0x138
>> ?[<ffffffff8104beae>] mmput+0x55/0xc1
>> ?[<ffffffff81050626>] exit_mm+0x10e/0x12f
>> ?[<ffffffff8105226f>] do_exit+0x1b4/0x6a8
>> ?[<ffffffff8106c6b0>] ? up_read+0x1c/0x32
>> ?[<ffffffff810527e2>] do_group_exit+0x7f/0xac
>> ?[<ffffffff81052834>] sys_exit_group+0x25/0x3d
>> ?[<ffffffff8100beab>] system_call_fastpath+0x16/0x1b
>>
>> I don't know if this is related to the drm changes.
>>
>> Back to 2.6.29 for me :) ?(I actually use this machine, so I'd rather
>> not run kernels that cause random corruption.)
>>
>> --Andy
>
> Could you get a trace using Linus pte check patch he posted earlier
> on the other thread ?

It didn't trigger Linus' warning.

I was also able to trigger this bug with modesetting turned off on the
kernel command line by switching VTs.

--Andy

>
> Jerome
>
>