aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv50_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/nv50_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/nv50_fbcon.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c69
1 files changed, 23 insertions, 46 deletions
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