diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-20 04:57:11 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-20 06:20:53 -0500 |
commit | e8616b6ced6137085e6657cc63bc2fe3900b8616 (patch) | |
tree | c21be366c9407849418e6698d8450f67d4dc5574 /drivers/gpu | |
parent | 4efe070896e1f7373c98a13713e659d1f5dee52a (diff) |
drm/i915: Initialise ring vfuncs for old DRI paths
We weren't setting up the vfunc table when initialising the old DRI
ringbuffer, leading to such OOPSes as:
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<(null)>] (null)
PGD 10c441067 PUD 1185e5067 PMD 0
Oops: 0010 [#1] PREEMPT SMP
last sysfs file: /sys/class/dmi/id/chassis_asset_tag
CPU 3
Modules linked in: i915 drm_kms_helper drm fb fbdev i2c_algo_bit
cfbcopyarea video backlight output cfbimgblt cfbfillrect autofs4 ipv6
nfs lockd fscache nfs_acl auth_rpcgss sunrpc coretemp hwmon_vid mousedev
usbhid hid option usb_wwan snd_hda_codec_via asus_atk0110 atl1e
usbserial snd_hda_intel snd_hda_codec firmware_class snd_hwdep snd_pcm
snd_seq snd_timer snd_seq_device processor parport_pc thermal snd
thermal_sys parport 8250_pnp button rng_core rtc_cmos shpchp hwmon
rtc_core ehci_hcd pci_hotplug uhci_hcd soundcore tpm_tis i2c_i801
rtc_lib tpm serio_raw snd_page_alloc tpm_bios i2c_core usbcore psmouse
intel_agp sg pcspkr sr_mod evdev cdrom ext3 jbd mbcache dm_mod sd_mod
ata_piix libata scsi_mod unix
Jan 18 15:49:29 lithui kernel:
Pid: 3605, comm: Xorg Not tainted 2.6.36.2 #5 P5KPL-CM/System Product
Name
RIP: 0010:[<0000000000000000>] [<(null)>] (null)
RSP: 0018:ffff8801150d1d40 EFLAGS: 00010202
RAX: 000000000001ffff RBX: ffff88011a011b00 RCX: 000000000001a704
RDX: ffff880118566028 RSI: ffff880118566028 RDI: ffff880117876800
RBP: ffff8801150d1d48 R08: ffff8801195fe300 R09: 00000000c0086444
R10: 0000000000000001 R11: 0000000000003206 R12: ffff880117876800
R13: ffff880118566000 R14: ffff880117876820 R15: ffff8801150d1df8
FS: 00007f1038d456e0(0000) GS:ffff880001780000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 00000001187e7000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process Xorg (pid: 3605, threadinfo ffff8801150d0000, task
ffff88011b016e40)
Stack:
ffffffffa043b8e6 ffff8801150d1d98 ffffffffa041768b dead000000000000
<0> 0000000000000048 00007f1023f2a000 0000000000000044 0000000000000008
<0> ffff88010d26bd80 ffff880117876800 ffff8801150d1df8 ffff8801150d1ea8
Call Trace:
[<ffffffffa043b8e6>] ? intel_ring_advance+0x16/0x20 [i915]
[<ffffffffa041768b>] i915_irq_emit+0x15b/0x240 [i915]
[<ffffffffa03ea7b1>] drm_ioctl+0x1f1/0x460 [drm]
[<ffffffffa0417530>] ? i915_irq_emit+0x0/0x240 [i915]
[<ffffffff810dd8f1>] ? do_sync_read+0xd1/0x120
[<ffffffff81025b1f>] ? do_page_fault+0x1df/0x3d0
[<ffffffff810ed5c7>] do_vfs_ioctl+0x97/0x550
[<ffffffff8115c2ea>] ? security_file_permission+0x7a/0x90
[<ffffffff810edb19>] sys_ioctl+0x99/0xa0
[<ffffffff810024ab>] system_call_fastpath+0x16/0x1b
Code: Bad RIP value.
RIP [<(null)>] (null)
RSP <ffff8801150d1d40>
CR2: 0000000000000000
Reported-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Herbert Xu <herbert@gondor.apana.org.au>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29153
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23172
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: stable@kernel.org
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 3 |
3 files changed, 52 insertions, 18 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 844f3c972b04..665898124200 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -152,7 +152,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) | |||
152 | { | 152 | { |
153 | drm_i915_private_t *dev_priv = dev->dev_private; | 153 | drm_i915_private_t *dev_priv = dev->dev_private; |
154 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; | 154 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; |
155 | struct intel_ring_buffer *ring = LP_RING(dev_priv); | 155 | int ret; |
156 | 156 | ||
157 | master_priv->sarea = drm_getsarea(dev); | 157 | master_priv->sarea = drm_getsarea(dev); |
158 | if (master_priv->sarea) { | 158 | if (master_priv->sarea) { |
@@ -163,33 +163,22 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) | |||
163 | } | 163 | } |
164 | 164 | ||
165 | if (init->ring_size != 0) { | 165 | if (init->ring_size != 0) { |
166 | if (ring->obj != NULL) { | 166 | if (LP_RING(dev_priv)->obj != NULL) { |
167 | i915_dma_cleanup(dev); | 167 | i915_dma_cleanup(dev); |
168 | DRM_ERROR("Client tried to initialize ringbuffer in " | 168 | DRM_ERROR("Client tried to initialize ringbuffer in " |
169 | "GEM mode\n"); | 169 | "GEM mode\n"); |
170 | return -EINVAL; | 170 | return -EINVAL; |
171 | } | 171 | } |
172 | 172 | ||
173 | ring->size = init->ring_size; | 173 | ret = intel_render_ring_init_dri(dev, |
174 | 174 | init->ring_start, | |
175 | ring->map.offset = init->ring_start; | 175 | init->ring_size); |
176 | ring->map.size = init->ring_size; | 176 | if (ret) { |
177 | ring->map.type = 0; | ||
178 | ring->map.flags = 0; | ||
179 | ring->map.mtrr = 0; | ||
180 | |||
181 | drm_core_ioremap_wc(&ring->map, dev); | ||
182 | |||
183 | if (ring->map.handle == NULL) { | ||
184 | i915_dma_cleanup(dev); | 177 | i915_dma_cleanup(dev); |
185 | DRM_ERROR("can not ioremap virtual address for" | 178 | return ret; |
186 | " ring buffer\n"); | ||
187 | return -ENOMEM; | ||
188 | } | 179 | } |
189 | } | 180 | } |
190 | 181 | ||
191 | ring->virtual_start = ring->map.handle; | ||
192 | |||
193 | dev_priv->cpp = init->cpp; | 182 | dev_priv->cpp = init->cpp; |
194 | dev_priv->back_offset = init->back_offset; | 183 | dev_priv->back_offset = init->back_offset; |
195 | dev_priv->front_offset = init->front_offset; | 184 | dev_priv->front_offset = init->front_offset; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 03e337072517..51fbc5e33c55 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -1291,6 +1291,48 @@ int intel_init_render_ring_buffer(struct drm_device *dev) | |||
1291 | return intel_init_ring_buffer(dev, ring); | 1291 | return intel_init_ring_buffer(dev, ring); |
1292 | } | 1292 | } |
1293 | 1293 | ||
1294 | int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) | ||
1295 | { | ||
1296 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1297 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | ||
1298 | |||
1299 | *ring = render_ring; | ||
1300 | if (INTEL_INFO(dev)->gen >= 6) { | ||
1301 | ring->add_request = gen6_add_request; | ||
1302 | ring->irq_get = gen6_render_ring_get_irq; | ||
1303 | ring->irq_put = gen6_render_ring_put_irq; | ||
1304 | } else if (IS_GEN5(dev)) { | ||
1305 | ring->add_request = pc_render_add_request; | ||
1306 | ring->get_seqno = pc_render_get_seqno; | ||
1307 | } | ||
1308 | |||
1309 | ring->dev = dev; | ||
1310 | INIT_LIST_HEAD(&ring->active_list); | ||
1311 | INIT_LIST_HEAD(&ring->request_list); | ||
1312 | INIT_LIST_HEAD(&ring->gpu_write_list); | ||
1313 | |||
1314 | ring->size = size; | ||
1315 | ring->effective_size = ring->size; | ||
1316 | if (IS_I830(ring->dev)) | ||
1317 | ring->effective_size -= 128; | ||
1318 | |||
1319 | ring->map.offset = start; | ||
1320 | ring->map.size = size; | ||
1321 | ring->map.type = 0; | ||
1322 | ring->map.flags = 0; | ||
1323 | ring->map.mtrr = 0; | ||
1324 | |||
1325 | drm_core_ioremap_wc(&ring->map, dev); | ||
1326 | if (ring->map.handle == NULL) { | ||
1327 | DRM_ERROR("can not ioremap virtual address for" | ||
1328 | " ring buffer\n"); | ||
1329 | return -ENOMEM; | ||
1330 | } | ||
1331 | |||
1332 | ring->virtual_start = (void __force __iomem *)ring->map.handle; | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1294 | int intel_init_bsd_ring_buffer(struct drm_device *dev) | 1336 | int intel_init_bsd_ring_buffer(struct drm_device *dev) |
1295 | { | 1337 | { |
1296 | drm_i915_private_t *dev_priv = dev->dev_private; | 1338 | drm_i915_private_t *dev_priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index be9087e4c9be..61d5220c4b58 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -167,4 +167,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev); | |||
167 | u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); | 167 | u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); |
168 | void intel_ring_setup_status_page(struct intel_ring_buffer *ring); | 168 | void intel_ring_setup_status_page(struct intel_ring_buffer *ring); |
169 | 169 | ||
170 | /* DRI warts */ | ||
171 | int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size); | ||
172 | |||
170 | #endif /* _INTEL_RINGBUFFER_H_ */ | 173 | #endif /* _INTEL_RINGBUFFER_H_ */ |