aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
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
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')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c137
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h12
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c68
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c69
4 files changed, 153 insertions, 133 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);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index e7e12684c37e..6b933f2c3a5b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -40,13 +40,13 @@ struct nouveau_fbdev {
40 40
41void nouveau_fbcon_restore(void); 41void nouveau_fbcon_restore(void);
42 42
43void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); 43int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
44void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); 44int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
45void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); 45int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
46int nv04_fbcon_accel_init(struct fb_info *info); 46int nv04_fbcon_accel_init(struct fb_info *info);
47void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); 47int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
48void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); 48int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
49void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); 49int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
50int nv50_fbcon_accel_init(struct fb_info *info); 50int nv50_fbcon_accel_init(struct fb_info *info);
51 51
52void nouveau_fbcon_gpu_lockup(struct fb_info *info); 52void nouveau_fbcon_gpu_lockup(struct fb_info *info);
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index 33e4c9388bc1..a32804e7d202 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -28,52 +28,39 @@
28#include "nouveau_ramht.h" 28#include "nouveau_ramht.h"
29#include "nouveau_fbcon.h" 29#include "nouveau_fbcon.h"
30 30
31void 31int
32nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) 32nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
33{ 33{
34 struct nouveau_fbdev *nfbdev = info->par; 34 struct nouveau_fbdev *nfbdev = info->par;
35 struct drm_device *dev = nfbdev->dev; 35 struct drm_device *dev = nfbdev->dev;
36 struct drm_nouveau_private *dev_priv = dev->dev_private; 36 struct drm_nouveau_private *dev_priv = dev->dev_private;
37 struct nouveau_channel *chan = dev_priv->channel; 37 struct nouveau_channel *chan = dev_priv->channel;
38 int ret;
38 39
39 if (info->state != FBINFO_STATE_RUNNING) 40 ret = RING_SPACE(chan, 4);
40 return; 41 if (ret)
41 42 return ret;
42 if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) {
43 nouveau_fbcon_gpu_lockup(info);
44 }
45
46 if (info->flags & FBINFO_HWACCEL_DISABLED) {
47 cfb_copyarea(info, region);
48 return;
49 }
50 43
51 BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); 44 BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3);
52 OUT_RING(chan, (region->sy << 16) | region->sx); 45 OUT_RING(chan, (region->sy << 16) | region->sx);
53 OUT_RING(chan, (region->dy << 16) | region->dx); 46 OUT_RING(chan, (region->dy << 16) | region->dx);
54 OUT_RING(chan, (region->height << 16) | region->width); 47 OUT_RING(chan, (region->height << 16) | region->width);
55 FIRE_RING(chan); 48 FIRE_RING(chan);
49 return 0;
56} 50}
57 51
58void 52int
59nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 53nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
60{ 54{
61 struct nouveau_fbdev *nfbdev = info->par; 55 struct nouveau_fbdev *nfbdev = info->par;
62 struct drm_device *dev = nfbdev->dev; 56 struct drm_device *dev = nfbdev->dev;
63 struct drm_nouveau_private *dev_priv = dev->dev_private; 57 struct drm_nouveau_private *dev_priv = dev->dev_private;
64 struct nouveau_channel *chan = dev_priv->channel; 58 struct nouveau_channel *chan = dev_priv->channel;
59 int ret;
65 60
66 if (info->state != FBINFO_STATE_RUNNING) 61 ret = RING_SPACE(chan, 7);
67 return; 62 if (ret)
68 63 return ret;
69 if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
70 nouveau_fbcon_gpu_lockup(info);
71 }
72
73 if (info->flags & FBINFO_HWACCEL_DISABLED) {
74 cfb_fillrect(info, rect);
75 return;
76 }
77 64
78 BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); 65 BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
79 OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); 66 OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
@@ -87,9 +74,10 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
87 OUT_RING(chan, (rect->dx << 16) | rect->dy); 74 OUT_RING(chan, (rect->dx << 16) | rect->dy);
88 OUT_RING(chan, (rect->width << 16) | rect->height); 75 OUT_RING(chan, (rect->width << 16) | rect->height);
89 FIRE_RING(chan); 76 FIRE_RING(chan);
77 return 0;
90} 78}
91 79
92void 80int
93nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) 81nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
94{ 82{
95 struct nouveau_fbdev *nfbdev = info->par; 83 struct nouveau_fbdev *nfbdev = info->par;
@@ -101,23 +89,14 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
101 uint32_t dsize; 89 uint32_t dsize;
102 uint32_t width; 90 uint32_t width;
103 uint32_t *data = (uint32_t *)image->data; 91 uint32_t *data = (uint32_t *)image->data;
92 int ret;
104 93
105 if (info->state != FBINFO_STATE_RUNNING) 94 if (image->depth != 1)
106 return; 95 return -ENODEV;
107
108 if (image->depth != 1) {
109 cfb_imageblit(info, image);
110 return;
111 }
112
113 if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) {
114 nouveau_fbcon_gpu_lockup(info);
115 }
116 96
117 if (info->flags & FBINFO_HWACCEL_DISABLED) { 97 ret = RING_SPACE(chan, 8);
118 cfb_imageblit(info, image); 98 if (ret)
119 return; 99 return ret;
120 }
121 100
122 width = ALIGN(image->width, 8); 101 width = ALIGN(image->width, 8);
123 dsize = ALIGN(width * image->height, 32) >> 5; 102 dsize = ALIGN(width * image->height, 32) >> 5;
@@ -144,11 +123,9 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
144 while (dsize) { 123 while (dsize) {
145 int iter_len = dsize > 128 ? 128 : dsize; 124 int iter_len = dsize > 128 ? 128 : dsize;
146 125
147 if (RING_SPACE(chan, iter_len + 1)) { 126 ret = RING_SPACE(chan, iter_len + 1);
148 nouveau_fbcon_gpu_lockup(info); 127 if (ret)
149 cfb_imageblit(info, image); 128 return ret;
150 return;
151 }
152 129
153 BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); 130 BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len);
154 OUT_RINGp(chan, data, iter_len); 131 OUT_RINGp(chan, data, iter_len);
@@ -157,6 +134,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
157 } 134 }
158 135
159 FIRE_RING(chan); 136 FIRE_RING(chan);
137 return 0;
160} 138}
161 139
162static int 140static int
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 6dcf048eddbc..6edf9dca35ca 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -4,26 +4,18 @@
4#include "nouveau_ramht.h" 4#include "nouveau_ramht.h"
5#include "nouveau_fbcon.h" 5#include "nouveau_fbcon.h"
6 6
7void 7int
8nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 8nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
9{ 9{
10 struct nouveau_fbdev *nfbdev = info->par; 10 struct nouveau_fbdev *nfbdev = info->par;
11 struct drm_device *dev = nfbdev->dev; 11 struct drm_device *dev = nfbdev->dev;
12 struct drm_nouveau_private *dev_priv = dev->dev_private; 12 struct drm_nouveau_private *dev_priv = dev->dev_private;
13 struct nouveau_channel *chan = dev_priv->channel; 13 struct nouveau_channel *chan = dev_priv->channel;
14 int ret;
14 15
15 if (info->state != FBINFO_STATE_RUNNING) 16 ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11);
16 return; 17 if (ret)
17 18 return ret;
18 if (!(info->flags & FBINFO_HWACCEL_DISABLED) &&
19 RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) {
20 nouveau_fbcon_gpu_lockup(info);
21 }
22
23 if (info->flags & FBINFO_HWACCEL_DISABLED) {
24 cfb_fillrect(info, rect);
25 return;
26 }
27 19
28 if (rect->rop != ROP_COPY) { 20 if (rect->rop != ROP_COPY) {
29 BEGIN_RING(chan, NvSub2D, 0x02ac, 1); 21 BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
@@ -45,27 +37,21 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
45 OUT_RING(chan, 3); 37 OUT_RING(chan, 3);
46 } 38 }
47 FIRE_RING(chan); 39 FIRE_RING(chan);
40 return 0;
48} 41}
49 42
50void 43int
51nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) 44nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
52{ 45{
53 struct nouveau_fbdev *nfbdev = info->par; 46 struct nouveau_fbdev *nfbdev = info->par;
54 struct drm_device *dev = nfbdev->dev; 47 struct drm_device *dev = nfbdev->dev;
55 struct drm_nouveau_private *dev_priv = dev->dev_private; 48 struct drm_nouveau_private *dev_priv = dev->dev_private;
56 struct nouveau_channel *chan = dev_priv->channel; 49 struct nouveau_channel *chan = dev_priv->channel;
50 int ret;
57 51
58 if (info->state != FBINFO_STATE_RUNNING) 52 ret = RING_SPACE(chan, 12);
59 return; 53 if (ret)
60 54 return ret;
61 if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) {
62 nouveau_fbcon_gpu_lockup(info);
63 }
64
65 if (info->flags & FBINFO_HWACCEL_DISABLED) {
66 cfb_copyarea(info, region);
67 return;
68 }
69 55
70 BEGIN_RING(chan, NvSub2D, 0x0110, 1); 56 BEGIN_RING(chan, NvSub2D, 0x0110, 1);
71 OUT_RING(chan, 0); 57 OUT_RING(chan, 0);
@@ -80,9 +66,10 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
80 OUT_RING(chan, 0); 66 OUT_RING(chan, 0);
81 OUT_RING(chan, region->sy); 67 OUT_RING(chan, region->sy);
82 FIRE_RING(chan); 68 FIRE_RING(chan);
69 return 0;
83} 70}
84 71
85void 72int
86nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) 73nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
87{ 74{
88 struct nouveau_fbdev *nfbdev = info->par; 75 struct nouveau_fbdev *nfbdev = info->par;
@@ -92,23 +79,14 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
92 uint32_t width, dwords, *data = (uint32_t *)image->data; 79 uint32_t width, dwords, *data = (uint32_t *)image->data;
93 uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); 80 uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
94 uint32_t *palette = info->pseudo_palette; 81 uint32_t *palette = info->pseudo_palette;
82 int ret;
95 83
96 if (info->state != FBINFO_STATE_RUNNING) 84 if (image->depth != 1)
97 return; 85 return -ENODEV;
98
99 if (image->depth != 1) {
100 cfb_imageblit(info, image);
101 return;
102 }
103
104 if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) {
105 nouveau_fbcon_gpu_lockup(info);
106 }
107 86
108 if (info->flags & FBINFO_HWACCEL_DISABLED) { 87 ret = RING_SPACE(chan, 11);
109 cfb_imageblit(info, image); 88 if (ret)
110 return; 89 return ret;
111 }
112 90
113 width = ALIGN(image->width, 32); 91 width = ALIGN(image->width, 32);
114 dwords = (width * image->height) >> 5; 92 dwords = (width * image->height) >> 5;
@@ -134,11 +112,9 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
134 while (dwords) { 112 while (dwords) {
135 int push = dwords > 2047 ? 2047 : dwords; 113 int push = dwords > 2047 ? 2047 : dwords;
136 114
137 if (RING_SPACE(chan, push + 1)) { 115 ret = RING_SPACE(chan, push + 1);
138 nouveau_fbcon_gpu_lockup(info); 116 if (ret)
139 cfb_imageblit(info, image); 117 return ret;
140 return;
141 }
142 118
143 dwords -= push; 119 dwords -= push;
144 120
@@ -148,6 +124,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
148 } 124 }
149 125
150 FIRE_RING(chan); 126 FIRE_RING(chan);
127 return 0;
151} 128}
152 129
153int 130int