aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-21 02:59:07 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-21 02:59:07 -0500
commitee2fae03d68e702866a8661fbee7ff2f2f3754d7 (patch)
tree4afb2ab7126d2acb6104fd5b1736b9190775070d
parente4ddc9cc62b40a8b08d02379064d5d8fd78e98bc (diff)
parentf9841a8d6018f8bcba77e75c9e368d94f1f22933 (diff)
Merge branch 'drm-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6: drm: Stop defining pci_pretty_name drm: r128: comment aligment with drm git drm: make kernel context switch same as for drm git tree. drm: fixup comment header style drm: savage: compat fix from drm git. drm: Unify radeon offset checking. i915_vblank_tasklet: Try harder to avoid tearing. DRM: handle pci_enable_device failure drm: fix return value check
-rw-r--r--drivers/char/drm/drmP.h7
-rw-r--r--drivers/char/drm/drm_lock.c2
-rw-r--r--drivers/char/drm/drm_stub.c12
-rw-r--r--drivers/char/drm/drm_sysfs.c8
-rw-r--r--drivers/char/drm/i915_irq.c199
-rw-r--r--drivers/char/drm/r128_drm.h3
-rw-r--r--drivers/char/drm/r128_drv.h3
-rw-r--r--drivers/char/drm/r128_state.c3
-rw-r--r--drivers/char/drm/r300_cmdbuf.c32
-rw-r--r--drivers/char/drm/radeon_drv.h15
-rw-r--r--drivers/char/drm/radeon_irq.c4
-rw-r--r--drivers/char/drm/radeon_mem.c4
-rw-r--r--drivers/char/drm/radeon_state.c13
-rw-r--r--drivers/char/drm/savage_bci.c4
14 files changed, 190 insertions, 119 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 0bbb04f2390f..6dcdceb81203 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -561,8 +561,7 @@ struct drm_driver {
561 int (*context_dtor) (struct drm_device * dev, int context); 561 int (*context_dtor) (struct drm_device * dev, int context);
562 int (*kernel_context_switch) (struct drm_device * dev, int old, 562 int (*kernel_context_switch) (struct drm_device * dev, int old,
563 int new); 563 int new);
564 void (*kernel_context_switch_unlock) (struct drm_device * dev, 564 void (*kernel_context_switch_unlock) (struct drm_device * dev);
565 drm_lock_t *lock);
566 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); 565 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
567 int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence); 566 int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
568 int (*dri_library_name) (struct drm_device *dev, char *buf); 567 int (*dri_library_name) (struct drm_device *dev, char *buf);
@@ -1143,9 +1142,5 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area);
1143extern unsigned long drm_core_get_map_ofs(drm_map_t * map); 1142extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
1144extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); 1143extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
1145 1144
1146#ifndef pci_pretty_name
1147#define pci_pretty_name(dev) ""
1148#endif
1149
1150#endif /* __KERNEL__ */ 1145#endif /* __KERNEL__ */
1151#endif 1146#endif
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index 116ed0f2ac09..e9993ba461a2 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -182,7 +182,7 @@ int drm_unlock(struct inode *inode, struct file *filp,
182 * modules but is required by the Sparc driver. 182 * modules but is required by the Sparc driver.
183 */ 183 */
184 if (dev->driver->kernel_context_switch_unlock) 184 if (dev->driver->kernel_context_switch_unlock)
185 dev->driver->kernel_context_switch_unlock(dev, &lock); 185 dev->driver->kernel_context_switch_unlock(dev);
186 else { 186 else {
187 drm_lock_transfer(dev, &dev->lock.hw_lock->lock, 187 drm_lock_transfer(dev, &dev->lock.hw_lock->lock,
188 DRM_KERNEL_CONTEXT); 188 DRM_KERNEL_CONTEXT);
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 5fd6dc0870cf..120d10256feb 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -211,14 +211,16 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
211 if (!dev) 211 if (!dev)
212 return -ENOMEM; 212 return -ENOMEM;
213 213
214 pci_enable_device(pdev); 214 ret = pci_enable_device(pdev);
215 if (ret)
216 goto err_g1;
215 217
216 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { 218 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
217 printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); 219 printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
218 goto err_g1; 220 goto err_g2;
219 } 221 }
220 if ((ret = drm_get_head(dev, &dev->primary))) 222 if ((ret = drm_get_head(dev, &dev->primary)))
221 goto err_g1; 223 goto err_g2;
222 224
223 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", 225 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
224 driver->name, driver->major, driver->minor, driver->patchlevel, 226 driver->name, driver->major, driver->minor, driver->patchlevel,
@@ -226,7 +228,9 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
226 228
227 return 0; 229 return 0;
228 230
229 err_g1: 231err_g2:
232 pci_disable_device(pdev);
233err_g1:
230 drm_free(dev, sizeof(*dev), DRM_MEM_STUB); 234 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
231 return ret; 235 return ret;
232} 236}
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index ba4b8de83cf0..cc8e2ebe128c 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -45,8 +45,8 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
45 int err; 45 int err;
46 46
47 class = class_create(owner, name); 47 class = class_create(owner, name);
48 if (!class) { 48 if (IS_ERR(class)) {
49 err = -ENOMEM; 49 err = PTR_ERR(class);
50 goto err_out; 50 goto err_out;
51 } 51 }
52 52
@@ -113,8 +113,8 @@ struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
113 MKDEV(DRM_MAJOR, head->minor), 113 MKDEV(DRM_MAJOR, head->minor),
114 &(head->dev->pdev)->dev, 114 &(head->dev->pdev)->dev,
115 "card%d", head->minor); 115 "card%d", head->minor);
116 if (!class_dev) { 116 if (IS_ERR(class_dev)) {
117 err = -ENOMEM; 117 err = PTR_ERR(class_dev);
118 goto err_out; 118 goto err_out;
119 } 119 }
120 120
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index e5463b111fc0..e2c4b3a41b1e 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -46,88 +46,167 @@ static void i915_vblank_tasklet(drm_device_t *dev)
46{ 46{
47 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 47 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
48 unsigned long irqflags; 48 unsigned long irqflags;
49 struct list_head *list, *tmp; 49 struct list_head *list, *tmp, hits, *hit;
50 int nhits, nrects, slice[2], upper[2], lower[2], i;
51 unsigned counter[2] = { atomic_read(&dev->vbl_received),
52 atomic_read(&dev->vbl_received2) };
53 drm_drawable_info_t *drw;
54 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
55 u32 cpp = dev_priv->cpp;
56 u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
57 XY_SRC_COPY_BLT_WRITE_ALPHA |
58 XY_SRC_COPY_BLT_WRITE_RGB)
59 : XY_SRC_COPY_BLT_CMD;
60 u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
61 (cpp << 23) | (1 << 24);
62 RING_LOCALS;
50 63
51 DRM_DEBUG("\n"); 64 DRM_DEBUG("\n");
52 65
66 INIT_LIST_HEAD(&hits);
67
68 nhits = nrects = 0;
69
53 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 70 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
54 71
72 /* Find buffer swaps scheduled for this vertical blank */
55 list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { 73 list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
56 drm_i915_vbl_swap_t *vbl_swap = 74 drm_i915_vbl_swap_t *vbl_swap =
57 list_entry(list, drm_i915_vbl_swap_t, head); 75 list_entry(list, drm_i915_vbl_swap_t, head);
58 atomic_t *counter = vbl_swap->pipe ? &dev->vbl_received2 :
59 &dev->vbl_received;
60
61 if ((atomic_read(counter) - vbl_swap->sequence) <= (1<<23)) {
62 drm_drawable_info_t *drw;
63
64 spin_unlock(&dev_priv->swaps_lock);
65
66 spin_lock(&dev->drw_lock);
67
68 drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
69
70 if (drw) {
71 int i, num_rects = drw->num_rects;
72 drm_clip_rect_t *rect = drw->rects;
73 drm_i915_sarea_t *sarea_priv =
74 dev_priv->sarea_priv;
75 u32 cpp = dev_priv->cpp;
76 u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
77 XY_SRC_COPY_BLT_WRITE_ALPHA |
78 XY_SRC_COPY_BLT_WRITE_RGB)
79 : XY_SRC_COPY_BLT_CMD;
80 u32 pitchropcpp = (sarea_priv->pitch * cpp) |
81 (0xcc << 16) | (cpp << 23) |
82 (1 << 24);
83 RING_LOCALS;
84
85 i915_kernel_lost_context(dev);
86
87 BEGIN_LP_RING(6);
88
89 OUT_RING(GFX_OP_DRAWRECT_INFO);
90 OUT_RING(0);
91 OUT_RING(0);
92 OUT_RING(sarea_priv->width |
93 sarea_priv->height << 16);
94 OUT_RING(sarea_priv->width |
95 sarea_priv->height << 16);
96 OUT_RING(0);
97 76
98 ADVANCE_LP_RING(); 77 if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
78 continue;
79
80 list_del(list);
81 dev_priv->swaps_pending--;
99 82
100 sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; 83 spin_unlock(&dev_priv->swaps_lock);
84 spin_lock(&dev->drw_lock);
101 85
102 for (i = 0; i < num_rects; i++, rect++) { 86 drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
103 BEGIN_LP_RING(8); 87
88 if (!drw) {
89 spin_unlock(&dev->drw_lock);
90 drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
91 spin_lock(&dev_priv->swaps_lock);
92 continue;
93 }
104 94
105 OUT_RING(cmd); 95 list_for_each(hit, &hits) {
106 OUT_RING(pitchropcpp); 96 drm_i915_vbl_swap_t *swap_cmp =
107 OUT_RING((rect->y1 << 16) | rect->x1); 97 list_entry(hit, drm_i915_vbl_swap_t, head);
108 OUT_RING((rect->y2 << 16) | rect->x2); 98 drm_drawable_info_t *drw_cmp =
109 OUT_RING(sarea_priv->front_offset); 99 drm_get_drawable_info(dev, swap_cmp->drw_id);
110 OUT_RING((rect->y1 << 16) | rect->x1);
111 OUT_RING(pitchropcpp & 0xffff);
112 OUT_RING(sarea_priv->back_offset);
113 100
114 ADVANCE_LP_RING(); 101 if (drw_cmp &&
115 } 102 drw_cmp->rects[0].y1 > drw->rects[0].y1) {
103 list_add_tail(list, hit);
104 break;
116 } 105 }
106 }
117 107
118 spin_unlock(&dev->drw_lock); 108 spin_unlock(&dev->drw_lock);
119 109
120 spin_lock(&dev_priv->swaps_lock); 110 /* List of hits was empty, or we reached the end of it */
111 if (hit == &hits)
112 list_add_tail(list, hits.prev);
121 113
122 list_del(list); 114 nhits++;
123 115
124 drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); 116 spin_lock(&dev_priv->swaps_lock);
117 }
118
119 if (nhits == 0) {
120 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
121 return;
122 }
123
124 spin_unlock(&dev_priv->swaps_lock);
125 125
126 dev_priv->swaps_pending--; 126 i915_kernel_lost_context(dev);
127
128 BEGIN_LP_RING(6);
129
130 OUT_RING(GFX_OP_DRAWRECT_INFO);
131 OUT_RING(0);
132 OUT_RING(0);
133 OUT_RING(sarea_priv->width | sarea_priv->height << 16);
134 OUT_RING(sarea_priv->width | sarea_priv->height << 16);
135 OUT_RING(0);
136
137 ADVANCE_LP_RING();
138
139 sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
140
141 upper[0] = upper[1] = 0;
142 slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
143 slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
144 lower[0] = sarea_priv->pipeA_y + slice[0];
145 lower[1] = sarea_priv->pipeB_y + slice[0];
146
147 spin_lock(&dev->drw_lock);
148
149 /* Emit blits for buffer swaps, partitioning both outputs into as many
150 * slices as there are buffer swaps scheduled in order to avoid tearing
151 * (based on the assumption that a single buffer swap would always
152 * complete before scanout starts).
153 */
154 for (i = 0; i++ < nhits;
155 upper[0] = lower[0], lower[0] += slice[0],
156 upper[1] = lower[1], lower[1] += slice[1]) {
157 if (i == nhits)
158 lower[0] = lower[1] = sarea_priv->height;
159
160 list_for_each(hit, &hits) {
161 drm_i915_vbl_swap_t *swap_hit =
162 list_entry(hit, drm_i915_vbl_swap_t, head);
163 drm_clip_rect_t *rect;
164 int num_rects, pipe;
165 unsigned short top, bottom;
166
167 drw = drm_get_drawable_info(dev, swap_hit->drw_id);
168
169 if (!drw)
170 continue;
171
172 rect = drw->rects;
173 pipe = swap_hit->pipe;
174 top = upper[pipe];
175 bottom = lower[pipe];
176
177 for (num_rects = drw->num_rects; num_rects--; rect++) {
178 int y1 = max(rect->y1, top);
179 int y2 = min(rect->y2, bottom);
180
181 if (y1 >= y2)
182 continue;
183
184 BEGIN_LP_RING(8);
185
186 OUT_RING(cmd);
187 OUT_RING(pitchropcpp);
188 OUT_RING((y1 << 16) | rect->x1);
189 OUT_RING((y2 << 16) | rect->x2);
190 OUT_RING(sarea_priv->front_offset);
191 OUT_RING((y1 << 16) | rect->x1);
192 OUT_RING(pitchropcpp & 0xffff);
193 OUT_RING(sarea_priv->back_offset);
194
195 ADVANCE_LP_RING();
196 }
127 } 197 }
128 } 198 }
129 199
130 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); 200 spin_unlock_irqrestore(&dev->drw_lock, irqflags);
201
202 list_for_each_safe(hit, tmp, &hits) {
203 drm_i915_vbl_swap_t *swap_hit =
204 list_entry(hit, drm_i915_vbl_swap_t, head);
205
206 list_del(hit);
207
208 drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
209 }
131} 210}
132 211
133irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 212irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 5d835b006f55..6e8af313f2b4 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -1,7 +1,8 @@
1/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- 1/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com 2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
3 */ 3 */
4/* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. 4/*
5 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 6 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved. 7 * All rights reserved.
7 * 8 *
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 94abffb2cca5..f1efb49de8df 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -1,7 +1,8 @@
1/* r128_drv.h -- Private header for r128 driver -*- linux-c -*- 1/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
2 * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com 2 * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
3 */ 3 */
4/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 4/*
5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 6 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All rights reserved. 7 * All rights reserved.
7 * 8 *
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index a080cdd6081e..17b11e7d8f32 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -1,7 +1,8 @@
1/* r128_state.c -- State support for r128 -*- linux-c -*- 1/* r128_state.c -- State support for r128 -*- linux-c -*-
2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com 2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
3 */ 3 */
4/* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 4/*
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved. 6 * All Rights Reserved.
6 * 7 *
7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index d14477ba3679..032a022ec6a8 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -242,26 +242,6 @@ static __inline__ int r300_check_range(unsigned reg, int count)
242 return 0; 242 return 0;
243} 243}
244 244
245/*
246 * we expect offsets passed to the framebuffer to be either within video
247 * memory or within AGP space
248 */
249static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
250 u32 offset)
251{
252 /* we realy want to check against end of video aperture
253 but this value is not being kept.
254 This code is correct for now (does the same thing as the
255 code that sets MC_FB_LOCATION) in radeon_cp.c */
256 if (offset >= dev_priv->fb_location &&
257 offset < (dev_priv->fb_location + dev_priv->fb_size))
258 return 0;
259 if (offset >= dev_priv->gart_vm_start &&
260 offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
261 return 0;
262 return 1;
263}
264
265static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * 245static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
266 dev_priv, 246 dev_priv,
267 drm_radeon_kcmd_buffer_t 247 drm_radeon_kcmd_buffer_t
@@ -290,7 +270,7 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
290 case MARK_SAFE: 270 case MARK_SAFE:
291 break; 271 break;
292 case MARK_CHECK_OFFSET: 272 case MARK_CHECK_OFFSET:
293 if (r300_check_offset(dev_priv, (u32) values[i])) { 273 if (!radeon_check_offset(dev_priv, (u32) values[i])) {
294 DRM_ERROR 274 DRM_ERROR
295 ("Offset failed range check (reg=%04x sz=%d)\n", 275 ("Offset failed range check (reg=%04x sz=%d)\n",
296 reg, sz); 276 reg, sz);
@@ -452,7 +432,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
452 i = 1; 432 i = 1;
453 while ((k < narrays) && (i < (count + 1))) { 433 while ((k < narrays) && (i < (count + 1))) {
454 i++; /* skip attribute field */ 434 i++; /* skip attribute field */
455 if (r300_check_offset(dev_priv, payload[i])) { 435 if (!radeon_check_offset(dev_priv, payload[i])) {
456 DRM_ERROR 436 DRM_ERROR
457 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", 437 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
458 k, i); 438 k, i);
@@ -463,7 +443,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
463 if (k == narrays) 443 if (k == narrays)
464 break; 444 break;
465 /* have one more to process, they come in pairs */ 445 /* have one more to process, they come in pairs */
466 if (r300_check_offset(dev_priv, payload[i])) { 446 if (!radeon_check_offset(dev_priv, payload[i])) {
467 DRM_ERROR 447 DRM_ERROR
468 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", 448 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
469 k, i); 449 k, i);
@@ -508,7 +488,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
508 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL 488 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
509 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 489 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
510 offset = cmd[2] << 10; 490 offset = cmd[2] << 10;
511 ret = r300_check_offset(dev_priv, offset); 491 ret = !radeon_check_offset(dev_priv, offset);
512 if (ret) { 492 if (ret) {
513 DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); 493 DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
514 return DRM_ERR(EINVAL); 494 return DRM_ERR(EINVAL);
@@ -518,7 +498,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
518 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && 498 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
519 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 499 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
520 offset = cmd[3] << 10; 500 offset = cmd[3] << 10;
521 ret = r300_check_offset(dev_priv, offset); 501 ret = !radeon_check_offset(dev_priv, offset);
522 if (ret) { 502 if (ret) {
523 DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); 503 DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
524 return DRM_ERR(EINVAL); 504 return DRM_ERR(EINVAL);
@@ -551,7 +531,7 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
551 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); 531 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
552 return DRM_ERR(EINVAL); 532 return DRM_ERR(EINVAL);
553 } 533 }
554 ret = r300_check_offset(dev_priv, cmd[2]); 534 ret = !radeon_check_offset(dev_priv, cmd[2]);
555 if (ret) { 535 if (ret) {
556 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); 536 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
557 return DRM_ERR(EINVAL); 537 return DRM_ERR(EINVAL);
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index f45cd7f147a5..8b105f1460a7 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -303,6 +303,21 @@ extern int radeon_no_wb;
303extern drm_ioctl_desc_t radeon_ioctls[]; 303extern drm_ioctl_desc_t radeon_ioctls[];
304extern int radeon_max_ioctl; 304extern int radeon_max_ioctl;
305 305
306/* Check whether the given hardware address is inside the framebuffer or the
307 * GART area.
308 */
309static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
310 u64 off)
311{
312 u32 fb_start = dev_priv->fb_location;
313 u32 fb_end = fb_start + dev_priv->fb_size - 1;
314 u32 gart_start = dev_priv->gart_vm_start;
315 u32 gart_end = gart_start + dev_priv->gart_size - 1;
316
317 return ((off >= fb_start && off <= fb_end) ||
318 (off >= gart_start && off <= gart_end));
319}
320
306 /* radeon_cp.c */ 321 /* radeon_cp.c */
307extern int radeon_cp_init(DRM_IOCTL_ARGS); 322extern int radeon_cp_init(DRM_IOCTL_ARGS);
308extern int radeon_cp_start(DRM_IOCTL_ARGS); 323extern int radeon_cp_start(DRM_IOCTL_ARGS);
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index d60519de887b..3ff0baa2fbfa 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -1,5 +1,5 @@
1/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- 1/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
2 * 2/*
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 * 4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the 5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
index 030a6fad0d86..517cad8b6e3a 100644
--- a/drivers/char/drm/radeon_mem.c
+++ b/drivers/char/drm/radeon_mem.c
@@ -1,5 +1,5 @@
1/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- 1/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */
2 * 2/*
3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 * 4 *
5 * The Weather Channel (TM) funded Tungsten Graphics to develop the 5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 6e04fdd732ac..938eccb78cc0 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -43,10 +43,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
43 u32 *offset) 43 u32 *offset)
44{ 44{
45 u64 off = *offset; 45 u64 off = *offset;
46 u32 fb_start = dev_priv->fb_location; 46 u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
47 u32 fb_end = fb_start + dev_priv->fb_size - 1;
48 u32 gart_start = dev_priv->gart_vm_start;
49 u32 gart_end = gart_start + dev_priv->gart_size - 1;
50 struct drm_radeon_driver_file_fields *radeon_priv; 47 struct drm_radeon_driver_file_fields *radeon_priv;
51 48
52 /* Hrm ... the story of the offset ... So this function converts 49 /* Hrm ... the story of the offset ... So this function converts
@@ -66,8 +63,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
66 /* First, the best case, the offset already lands in either the 63 /* First, the best case, the offset already lands in either the
67 * framebuffer or the GART mapped space 64 * framebuffer or the GART mapped space
68 */ 65 */
69 if ((off >= fb_start && off <= fb_end) || 66 if (radeon_check_offset(dev_priv, off))
70 (off >= gart_start && off <= gart_end))
71 return 0; 67 return 0;
72 68
73 /* Ok, that didn't happen... now check if we have a zero based 69 /* Ok, that didn't happen... now check if we have a zero based
@@ -81,11 +77,10 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
81 77
82 /* Finally, assume we aimed at a GART offset if beyond the fb */ 78 /* Finally, assume we aimed at a GART offset if beyond the fb */
83 if (off > fb_end) 79 if (off > fb_end)
84 off = off - fb_end - 1 + gart_start; 80 off = off - fb_end - 1 + dev_priv->gart_vm_start;
85 81
86 /* Now recheck and fail if out of bounds */ 82 /* Now recheck and fail if out of bounds */
87 if ((off >= fb_start && off <= fb_end) || 83 if (radeon_check_offset(dev_priv, off)) {
88 (off >= gart_start && off <= gart_end)) {
89 DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); 84 DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
90 *offset = off; 85 *offset = off;
91 return 0; 86 return 0;
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index a9a84f88df5e..b94fab556809 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -963,8 +963,8 @@ static int savage_bci_event_emit(DRM_IOCTL_ARGS)
963 963
964 event.count = savage_bci_emit_event(dev_priv, event.flags); 964 event.count = savage_bci_emit_event(dev_priv, event.flags);
965 event.count |= dev_priv->event_wrap << 16; 965 event.count |= dev_priv->event_wrap << 16;
966 DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *) data)-> 966 DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *) data,
967 count, event.count, sizeof(event.count)); 967 event, sizeof(event));
968 return 0; 968 return 0;
969} 969}
970 970