From aaefcd4284a5399641ed02ac3e696b5e50ce185e Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Tue, 6 Mar 2012 10:44:40 +0000
Subject: drm/radeon: deal with errors from framebuffer init path.
Git-commit: aaefcd4284a5399641ed02ac3e696b5e50ce185e
Patch-mainline: v3.3-rc7

We've been getting occasional oops running a 32-bit kernel on a certain
system in our RHEL test hw. It appears that we fail to get sufficent ioremap
space for the framebuffer, and this leads to an oops.

This patch should fix the oops and leave a message in the logs we can
check for.

A future fix would probably to resize the console to a size that we can
ioremap.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Acked-by: Michal Srb <msrb@suse.com>
---
 drivers/gpu/drm/radeon/radeon_display.c |   18 +++++++++++++++---
 drivers/gpu/drm/radeon/radeon_fb.c      |   11 ++++++++++-
 drivers/gpu/drm/radeon/radeon_mode.h    |    2 +-
 3 files changed, 26 insertions(+), 5 deletions(-)

Index: linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_display.c
===================================================================
--- linux-3.0-SLE11-SP3.orig/drivers/gpu/drm/radeon/radeon_display.c
+++ linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_display.c
@@ -1078,15 +1078,21 @@ static const struct drm_framebuffer_func
 	.create_handle = radeon_user_framebuffer_create_handle,
 };
 
-void
+int
 radeon_framebuffer_init(struct drm_device *dev,
 			struct radeon_framebuffer *rfb,
 			struct drm_mode_fb_cmd2 *mode_cmd,
 			struct drm_gem_object *obj)
 {
+	int ret;
 	rfb->obj = obj;
-	drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs);
+	ret = drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs);
+	if (ret) {
+		rfb->obj = NULL;
+		return ret;
+	}
 	drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd);
+	return 0;
 }
 
 static struct drm_framebuffer *
@@ -1096,6 +1102,7 @@ radeon_user_framebuffer_create(struct dr
 {
 	struct drm_gem_object *obj;
 	struct radeon_framebuffer *radeon_fb;
+	int ret;
 
 	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
 	if (obj ==  NULL) {
@@ -1110,7 +1117,12 @@ radeon_user_framebuffer_create(struct dr
 		return ERR_PTR(-ENOMEM);
 	}
 
-	radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
+	ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
+	if (ret) {
+		kfree(radeon_fb);
+		drm_gem_object_unreference_unlocked(obj);
+		return NULL;
+	}
 
 	return &radeon_fb->base;
 }
Index: linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_fb.c
===================================================================
--- linux-3.0-SLE11-SP3.orig/drivers/gpu/drm/radeon/radeon_fb.c
+++ linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_fb.c
@@ -209,6 +209,11 @@ static int radeonfb_create(struct radeon
 							  sizes->surface_depth);
 
 	ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
+	if (ret) {
+		DRM_ERROR("failed to create fbcon object %d\n", ret);
+		return ret;
+	}
+
 	rbo = gem_to_radeon_bo(gobj);
 
 	/* okay we have an object now allocate the framebuffer */
@@ -220,7 +225,11 @@ static int radeonfb_create(struct radeon
 
 	info->par = rfbdev;
 
-	radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
+	ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
+	if (ret) {
+		DRM_ERROR("failed to initalise framebuffer %d\n", ret);
+		goto out_unref;
+	}
 
 	fb = &rfbdev->rfb.base;
 
Index: linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_mode.h
===================================================================
--- linux-3.0-SLE11-SP3.orig/drivers/gpu/drm/radeon/radeon_mode.h
+++ linux-3.0-SLE11-SP3/drivers/gpu/drm/radeon/radeon_mode.h
@@ -649,7 +649,7 @@ extern void radeon_crtc_fb_gamma_set(str
 				     u16 blue, int regno);
 extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 				     u16 *blue, int regno);
-void radeon_framebuffer_init(struct drm_device *dev,
+int radeon_framebuffer_init(struct drm_device *dev,
 			     struct radeon_framebuffer *rfb,
 			     struct drm_mode_fb_cmd2 *mode_cmd,
 			     struct drm_gem_object *obj);
