aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_fbcon.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-10-05 02:41:29 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 00:04:20 -0500
commitceed5f30bf0f515b52246230e5faacf89983fd8f (patch)
tree4d38b61dea52bad27e0421d25c8a2d8690de6a75 /drivers/gpu/drm/nouveau/nouveau_fbcon.c
parent7c74cbd01b2698583fb74ebdfcd7ef4c768e6346 (diff)
drm/nouveau: disallow fbcon accel if running in interrupt context
A future commit will add locking to the DRM's channel, and there's numerous problems that come up if we allow printk from an interrupt context to be accelerated. It seems saner to just disallow it completely. As a nice side-effect, all the "to accel or not to accel" logic gets moved out of the chipset-specific code. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fbcon.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c137
1 files changed, 101 insertions, 36 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 02a4d1fd4845..22e83adcc930 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -49,6 +49,90 @@
49#include "nouveau_fbcon.h" 49#include "nouveau_fbcon.h"
50#include "nouveau_dma.h" 50#include "nouveau_dma.h"
51 51
52static void
53nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
54{
55 struct nouveau_fbdev *nfbdev = info->par;
56 struct drm_device *dev = nfbdev->dev;
57 struct drm_nouveau_private *dev_priv = dev->dev_private;
58 int ret;
59
60 if (info->state != FBINFO_STATE_RUNNING)
61 return;
62
63 ret = -ENODEV;
64 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED)) {
65 if (dev_priv->card_type < NV_50)
66 ret = nv04_fbcon_fillrect(info, rect);
67 else
68 if (dev_priv->card_type < NV_C0)
69 ret = nv50_fbcon_fillrect(info, rect);
70 }
71
72 if (ret == 0)
73 return;
74
75 if (ret != -ENODEV)
76 nouveau_fbcon_gpu_lockup(info);
77 cfb_fillrect(info, rect);
78}
79
80static void
81nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
82{
83 struct nouveau_fbdev *nfbdev = info->par;
84 struct drm_device *dev = nfbdev->dev;
85 struct drm_nouveau_private *dev_priv = dev->dev_private;
86 int ret;
87
88 if (info->state != FBINFO_STATE_RUNNING)
89 return;
90
91 ret = -ENODEV;
92 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED)) {
93 if (dev_priv->card_type < NV_50)
94 ret = nv04_fbcon_copyarea(info, image);
95 else
96 if (dev_priv->card_type < NV_C0)
97 ret = nv50_fbcon_copyarea(info, image);
98 }
99
100 if (ret == 0)
101 return;
102
103 if (ret != -ENODEV)
104 nouveau_fbcon_gpu_lockup(info);
105 cfb_copyarea(info, image);
106}
107
108static void
109nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
110{
111 struct nouveau_fbdev *nfbdev = info->par;
112 struct drm_device *dev = nfbdev->dev;
113 struct drm_nouveau_private *dev_priv = dev->dev_private;
114 int ret;
115
116 if (info->state != FBINFO_STATE_RUNNING)
117 return;
118
119 ret = -ENODEV;
120 if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED)) {
121 if (dev_priv->card_type < NV_50)
122 ret = nv04_fbcon_imageblit(info, image);
123 else
124 if (dev_priv->card_type < NV_C0)
125 ret = nv50_fbcon_imageblit(info, image);
126 }
127
128 if (ret == 0)
129 return;
130
131 if (ret != -ENODEV)
132 nouveau_fbcon_gpu_lockup(info);
133 cfb_imageblit(info, image);
134}
135
52static int 136static int
53nouveau_fbcon_sync(struct fb_info *info) 137nouveau_fbcon_sync(struct fb_info *info)
54{ 138{
@@ -97,24 +181,9 @@ static struct fb_ops nouveau_fbcon_ops = {
97 .owner = THIS_MODULE, 181 .owner = THIS_MODULE,
98 .fb_check_var = drm_fb_helper_check_var, 182 .fb_check_var = drm_fb_helper_check_var,
99 .fb_set_par = drm_fb_helper_set_par, 183 .fb_set_par = drm_fb_helper_set_par,
100 .fb_fillrect = cfb_fillrect, 184 .fb_fillrect = nouveau_fbcon_fillrect,
101 .fb_copyarea = cfb_copyarea, 185 .fb_copyarea = nouveau_fbcon_copyarea,
102 .fb_imageblit = cfb_imageblit, 186 .fb_imageblit = nouveau_fbcon_imageblit,
103 .fb_sync = nouveau_fbcon_sync,
104 .fb_pan_display = drm_fb_helper_pan_display,
105 .fb_blank = drm_fb_helper_blank,
106 .fb_setcmap = drm_fb_helper_setcmap,
107 .fb_debug_enter = drm_fb_helper_debug_enter,
108 .fb_debug_leave = drm_fb_helper_debug_leave,
109};
110
111static struct fb_ops nv04_fbcon_ops = {
112 .owner = THIS_MODULE,
113 .fb_check_var = drm_fb_helper_check_var,
114 .fb_set_par = drm_fb_helper_set_par,
115 .fb_fillrect = nv04_fbcon_fillrect,
116 .fb_copyarea = nv04_fbcon_copyarea,
117 .fb_imageblit = nv04_fbcon_imageblit,
118 .fb_sync = nouveau_fbcon_sync, 187 .fb_sync = nouveau_fbcon_sync,
119 .fb_pan_display = drm_fb_helper_pan_display, 188 .fb_pan_display = drm_fb_helper_pan_display,
120 .fb_blank = drm_fb_helper_blank, 189 .fb_blank = drm_fb_helper_blank,
@@ -123,14 +192,13 @@ static struct fb_ops nv04_fbcon_ops = {
123 .fb_debug_leave = drm_fb_helper_debug_leave, 192 .fb_debug_leave = drm_fb_helper_debug_leave,
124}; 193};
125 194
126static struct fb_ops nv50_fbcon_ops = { 195static struct fb_ops nouveau_fbcon_sw_ops = {
127 .owner = THIS_MODULE, 196 .owner = THIS_MODULE,
128 .fb_check_var = drm_fb_helper_check_var, 197 .fb_check_var = drm_fb_helper_check_var,
129 .fb_set_par = drm_fb_helper_set_par, 198 .fb_set_par = drm_fb_helper_set_par,
130 .fb_fillrect = nv50_fbcon_fillrect, 199 .fb_fillrect = cfb_fillrect,
131 .fb_copyarea = nv50_fbcon_copyarea, 200 .fb_copyarea = cfb_copyarea,
132 .fb_imageblit = nv50_fbcon_imageblit, 201 .fb_imageblit = cfb_imageblit,
133 .fb_sync = nouveau_fbcon_sync,
134 .fb_pan_display = drm_fb_helper_pan_display, 202 .fb_pan_display = drm_fb_helper_pan_display,
135 .fb_blank = drm_fb_helper_blank, 203 .fb_blank = drm_fb_helper_blank,
136 .fb_setcmap = drm_fb_helper_setcmap, 204 .fb_setcmap = drm_fb_helper_setcmap,
@@ -257,7 +325,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
257 FBINFO_HWACCEL_FILLRECT | 325 FBINFO_HWACCEL_FILLRECT |
258 FBINFO_HWACCEL_IMAGEBLIT; 326 FBINFO_HWACCEL_IMAGEBLIT;
259 info->flags |= FBINFO_CAN_FORCE_OUTPUT; 327 info->flags |= FBINFO_CAN_FORCE_OUTPUT;
260 info->fbops = &nouveau_fbcon_ops; 328 info->fbops = &nouveau_fbcon_sw_ops;
261 info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - 329 info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
262 dev_priv->vm_vram_base; 330 dev_priv->vm_vram_base;
263 info->fix.smem_len = size; 331 info->fix.smem_len = size;
@@ -286,18 +354,15 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
286 info->pixmap.scan_align = 1; 354 info->pixmap.scan_align = 1;
287 355
288 if (dev_priv->channel && !nouveau_nofbaccel) { 356 if (dev_priv->channel && !nouveau_nofbaccel) {
289 switch (dev_priv->card_type) { 357 ret = -ENODEV;
290 case NV_C0: 358 if (dev_priv->card_type < NV_50)
291 break; 359 ret = nv04_fbcon_accel_init(info);
292 case NV_50: 360 else
293 nv50_fbcon_accel_init(info); 361 if (dev_priv->card_type < NV_C0)
294 info->fbops = &nv50_fbcon_ops; 362 ret = nv50_fbcon_accel_init(info);
295 break; 363
296 default: 364 if (ret == 0)
297 nv04_fbcon_accel_init(info); 365 info->fbops = &nouveau_fbcon_ops;
298 info->fbops = &nv04_fbcon_ops;
299 break;
300 };
301 } 366 }
302 367
303 nouveau_fbcon_zfill(dev, nfbdev); 368 nouveau_fbcon_zfill(dev, nfbdev);