diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/i915/i915_irq.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 567 |
1 files changed, 451 insertions, 116 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index aa7fd82aa6eb..df6a9cd82c4d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -27,6 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/sysrq.h> | 29 | #include <linux/sysrq.h> |
30 | #include <linux/slab.h> | ||
30 | #include "drmP.h" | 31 | #include "drmP.h" |
31 | #include "drm.h" | 32 | #include "drm.h" |
32 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
@@ -43,10 +44,13 @@ | |||
43 | * we leave them always unmasked in IMR and then control enabling them through | 44 | * we leave them always unmasked in IMR and then control enabling them through |
44 | * PIPESTAT alone. | 45 | * PIPESTAT alone. |
45 | */ | 46 | */ |
46 | #define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ | 47 | #define I915_INTERRUPT_ENABLE_FIX \ |
47 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ | 48 | (I915_ASLE_INTERRUPT | \ |
48 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ | 49 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ |
49 | I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) | 50 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ |
51 | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | \ | ||
52 | I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | \ | ||
53 | I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) | ||
50 | 54 | ||
51 | /** Interrupts that we mask and unmask at runtime. */ | 55 | /** Interrupts that we mask and unmask at runtime. */ |
52 | #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) | 56 | #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) |
@@ -61,7 +65,7 @@ | |||
61 | DRM_I915_VBLANK_PIPE_B) | 65 | DRM_I915_VBLANK_PIPE_B) |
62 | 66 | ||
63 | void | 67 | void |
64 | igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) | 68 | ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) |
65 | { | 69 | { |
66 | if ((dev_priv->gt_irq_mask_reg & mask) != 0) { | 70 | if ((dev_priv->gt_irq_mask_reg & mask) != 0) { |
67 | dev_priv->gt_irq_mask_reg &= ~mask; | 71 | dev_priv->gt_irq_mask_reg &= ~mask; |
@@ -71,7 +75,7 @@ igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) | |||
71 | } | 75 | } |
72 | 76 | ||
73 | static inline void | 77 | static inline void |
74 | igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) | 78 | ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) |
75 | { | 79 | { |
76 | if ((dev_priv->gt_irq_mask_reg & mask) != mask) { | 80 | if ((dev_priv->gt_irq_mask_reg & mask) != mask) { |
77 | dev_priv->gt_irq_mask_reg |= mask; | 81 | dev_priv->gt_irq_mask_reg |= mask; |
@@ -82,7 +86,7 @@ igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) | |||
82 | 86 | ||
83 | /* For display hotplug interrupt */ | 87 | /* For display hotplug interrupt */ |
84 | void | 88 | void |
85 | igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | 89 | ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) |
86 | { | 90 | { |
87 | if ((dev_priv->irq_mask_reg & mask) != 0) { | 91 | if ((dev_priv->irq_mask_reg & mask) != 0) { |
88 | dev_priv->irq_mask_reg &= ~mask; | 92 | dev_priv->irq_mask_reg &= ~mask; |
@@ -92,7 +96,7 @@ igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | |||
92 | } | 96 | } |
93 | 97 | ||
94 | static inline void | 98 | static inline void |
95 | igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | 99 | ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) |
96 | { | 100 | { |
97 | if ((dev_priv->irq_mask_reg & mask) != mask) { | 101 | if ((dev_priv->irq_mask_reg & mask) != mask) { |
98 | dev_priv->irq_mask_reg |= mask; | 102 | dev_priv->irq_mask_reg |= mask; |
@@ -157,6 +161,20 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) | |||
157 | } | 161 | } |
158 | 162 | ||
159 | /** | 163 | /** |
164 | * intel_enable_asle - enable ASLE interrupt for OpRegion | ||
165 | */ | ||
166 | void intel_enable_asle (struct drm_device *dev) | ||
167 | { | ||
168 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
169 | |||
170 | if (HAS_PCH_SPLIT(dev)) | ||
171 | ironlake_enable_display_irq(dev_priv, DE_GSE); | ||
172 | else | ||
173 | i915_enable_pipestat(dev_priv, 1, | ||
174 | I915_LEGACY_BLC_EVENT_ENABLE); | ||
175 | } | ||
176 | |||
177 | /** | ||
160 | * i915_pipe_enabled - check if a pipe is enabled | 178 | * i915_pipe_enabled - check if a pipe is enabled |
161 | * @dev: DRM device | 179 | * @dev: DRM device |
162 | * @pipe: pipe to check | 180 | * @pipe: pipe to check |
@@ -191,7 +209,8 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
191 | low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; | 209 | low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; |
192 | 210 | ||
193 | if (!i915_pipe_enabled(dev, pipe)) { | 211 | if (!i915_pipe_enabled(dev, pipe)) { |
194 | DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); | 212 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " |
213 | "pipe %d\n", pipe); | ||
195 | return 0; | 214 | return 0; |
196 | } | 215 | } |
197 | 216 | ||
@@ -220,7 +239,8 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) | |||
220 | int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; | 239 | int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; |
221 | 240 | ||
222 | if (!i915_pipe_enabled(dev, pipe)) { | 241 | if (!i915_pipe_enabled(dev, pipe)) { |
223 | DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); | 242 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " |
243 | "pipe %d\n", pipe); | ||
224 | return 0; | 244 | return 0; |
225 | } | 245 | } |
226 | 246 | ||
@@ -240,22 +260,72 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
240 | 260 | ||
241 | if (mode_config->num_connector) { | 261 | if (mode_config->num_connector) { |
242 | list_for_each_entry(connector, &mode_config->connector_list, head) { | 262 | list_for_each_entry(connector, &mode_config->connector_list, head) { |
243 | struct intel_output *intel_output = to_intel_output(connector); | 263 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
244 | 264 | ||
245 | if (intel_output->hot_plug) | 265 | if (intel_encoder->hot_plug) |
246 | (*intel_output->hot_plug) (intel_output); | 266 | (*intel_encoder->hot_plug) (intel_encoder); |
247 | } | 267 | } |
248 | } | 268 | } |
249 | /* Just fire off a uevent and let userspace tell us what to do */ | 269 | /* Just fire off a uevent and let userspace tell us what to do */ |
250 | drm_sysfs_hotplug_event(dev); | 270 | drm_sysfs_hotplug_event(dev); |
251 | } | 271 | } |
252 | 272 | ||
253 | irqreturn_t igdng_irq_handler(struct drm_device *dev) | 273 | static void i915_handle_rps_change(struct drm_device *dev) |
274 | { | ||
275 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
276 | u32 busy_up, busy_down, max_avg, min_avg; | ||
277 | u16 rgvswctl; | ||
278 | u8 new_delay = dev_priv->cur_delay; | ||
279 | |||
280 | I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG); | ||
281 | busy_up = I915_READ(RCPREVBSYTUPAVG); | ||
282 | busy_down = I915_READ(RCPREVBSYTDNAVG); | ||
283 | max_avg = I915_READ(RCBMAXAVG); | ||
284 | min_avg = I915_READ(RCBMINAVG); | ||
285 | |||
286 | /* Handle RCS change request from hw */ | ||
287 | if (busy_up > max_avg) { | ||
288 | if (dev_priv->cur_delay != dev_priv->max_delay) | ||
289 | new_delay = dev_priv->cur_delay - 1; | ||
290 | if (new_delay < dev_priv->max_delay) | ||
291 | new_delay = dev_priv->max_delay; | ||
292 | } else if (busy_down < min_avg) { | ||
293 | if (dev_priv->cur_delay != dev_priv->min_delay) | ||
294 | new_delay = dev_priv->cur_delay + 1; | ||
295 | if (new_delay > dev_priv->min_delay) | ||
296 | new_delay = dev_priv->min_delay; | ||
297 | } | ||
298 | |||
299 | DRM_DEBUG("rps change requested: %d -> %d\n", | ||
300 | dev_priv->cur_delay, new_delay); | ||
301 | |||
302 | rgvswctl = I915_READ(MEMSWCTL); | ||
303 | if (rgvswctl & MEMCTL_CMD_STS) { | ||
304 | DRM_ERROR("gpu busy, RCS change rejected\n"); | ||
305 | return; /* still busy with another command */ | ||
306 | } | ||
307 | |||
308 | /* Program the new state */ | ||
309 | rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) | | ||
310 | (new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM; | ||
311 | I915_WRITE(MEMSWCTL, rgvswctl); | ||
312 | POSTING_READ(MEMSWCTL); | ||
313 | |||
314 | rgvswctl |= MEMCTL_CMD_STS; | ||
315 | I915_WRITE(MEMSWCTL, rgvswctl); | ||
316 | |||
317 | dev_priv->cur_delay = new_delay; | ||
318 | |||
319 | DRM_DEBUG("rps changed\n"); | ||
320 | |||
321 | return; | ||
322 | } | ||
323 | |||
324 | irqreturn_t ironlake_irq_handler(struct drm_device *dev) | ||
254 | { | 325 | { |
255 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 326 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
256 | int ret = IRQ_NONE; | 327 | int ret = IRQ_NONE; |
257 | u32 de_iir, gt_iir, de_ier; | 328 | u32 de_iir, gt_iir, de_ier, pch_iir; |
258 | u32 new_de_iir, new_gt_iir; | ||
259 | struct drm_i915_master_private *master_priv; | 329 | struct drm_i915_master_private *master_priv; |
260 | 330 | ||
261 | /* disable master interrupt before clearing iir */ | 331 | /* disable master interrupt before clearing iir */ |
@@ -265,36 +335,65 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) | |||
265 | 335 | ||
266 | de_iir = I915_READ(DEIIR); | 336 | de_iir = I915_READ(DEIIR); |
267 | gt_iir = I915_READ(GTIIR); | 337 | gt_iir = I915_READ(GTIIR); |
338 | pch_iir = I915_READ(SDEIIR); | ||
268 | 339 | ||
269 | for (;;) { | 340 | if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) |
270 | if (de_iir == 0 && gt_iir == 0) | 341 | goto done; |
271 | break; | ||
272 | 342 | ||
273 | ret = IRQ_HANDLED; | 343 | ret = IRQ_HANDLED; |
274 | 344 | ||
275 | I915_WRITE(DEIIR, de_iir); | 345 | if (dev->primary->master) { |
276 | new_de_iir = I915_READ(DEIIR); | 346 | master_priv = dev->primary->master->driver_priv; |
277 | I915_WRITE(GTIIR, gt_iir); | 347 | if (master_priv->sarea_priv) |
278 | new_gt_iir = I915_READ(GTIIR); | 348 | master_priv->sarea_priv->last_dispatch = |
349 | READ_BREADCRUMB(dev_priv); | ||
350 | } | ||
279 | 351 | ||
280 | if (dev->primary->master) { | 352 | if (gt_iir & GT_PIPE_NOTIFY) { |
281 | master_priv = dev->primary->master->driver_priv; | 353 | u32 seqno = i915_get_gem_seqno(dev); |
282 | if (master_priv->sarea_priv) | 354 | dev_priv->mm.irq_gem_seqno = seqno; |
283 | master_priv->sarea_priv->last_dispatch = | 355 | trace_i915_gem_request_complete(dev, seqno); |
284 | READ_BREADCRUMB(dev_priv); | 356 | DRM_WAKEUP(&dev_priv->irq_queue); |
285 | } | 357 | dev_priv->hangcheck_count = 0; |
358 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | ||
359 | } | ||
286 | 360 | ||
287 | if (gt_iir & GT_USER_INTERRUPT) { | 361 | if (de_iir & DE_GSE) |
288 | u32 seqno = i915_get_gem_seqno(dev); | 362 | ironlake_opregion_gse_intr(dev); |
289 | dev_priv->mm.irq_gem_seqno = seqno; | 363 | |
290 | trace_i915_gem_request_complete(dev, seqno); | 364 | if (de_iir & DE_PLANEA_FLIP_DONE) { |
291 | DRM_WAKEUP(&dev_priv->irq_queue); | 365 | intel_prepare_page_flip(dev, 0); |
292 | } | 366 | intel_finish_page_flip(dev, 0); |
367 | } | ||
368 | |||
369 | if (de_iir & DE_PLANEB_FLIP_DONE) { | ||
370 | intel_prepare_page_flip(dev, 1); | ||
371 | intel_finish_page_flip(dev, 1); | ||
372 | } | ||
373 | |||
374 | if (de_iir & DE_PIPEA_VBLANK) | ||
375 | drm_handle_vblank(dev, 0); | ||
293 | 376 | ||
294 | de_iir = new_de_iir; | 377 | if (de_iir & DE_PIPEB_VBLANK) |
295 | gt_iir = new_gt_iir; | 378 | drm_handle_vblank(dev, 1); |
379 | |||
380 | /* check event from PCH */ | ||
381 | if ((de_iir & DE_PCH_EVENT) && | ||
382 | (pch_iir & SDE_HOTPLUG_MASK)) { | ||
383 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
384 | } | ||
385 | |||
386 | if (de_iir & DE_PCU_EVENT) { | ||
387 | I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS)); | ||
388 | i915_handle_rps_change(dev); | ||
296 | } | 389 | } |
297 | 390 | ||
391 | /* should clear PCH hotplug event before clear CPU irq */ | ||
392 | I915_WRITE(SDEIIR, pch_iir); | ||
393 | I915_WRITE(GTIIR, gt_iir); | ||
394 | I915_WRITE(DEIIR, de_iir); | ||
395 | |||
396 | done: | ||
298 | I915_WRITE(DEIER, de_ier); | 397 | I915_WRITE(DEIER, de_ier); |
299 | (void)I915_READ(DEIER); | 398 | (void)I915_READ(DEIER); |
300 | 399 | ||
@@ -317,23 +416,142 @@ static void i915_error_work_func(struct work_struct *work) | |||
317 | char *reset_event[] = { "RESET=1", NULL }; | 416 | char *reset_event[] = { "RESET=1", NULL }; |
318 | char *reset_done_event[] = { "ERROR=0", NULL }; | 417 | char *reset_done_event[] = { "ERROR=0", NULL }; |
319 | 418 | ||
320 | DRM_DEBUG("generating error event\n"); | 419 | DRM_DEBUG_DRIVER("generating error event\n"); |
321 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); | 420 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); |
322 | 421 | ||
323 | if (atomic_read(&dev_priv->mm.wedged)) { | 422 | if (atomic_read(&dev_priv->mm.wedged)) { |
324 | if (IS_I965G(dev)) { | 423 | if (IS_I965G(dev)) { |
325 | DRM_DEBUG("resetting chip\n"); | 424 | DRM_DEBUG_DRIVER("resetting chip\n"); |
326 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); | 425 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); |
327 | if (!i965_reset(dev, GDRST_RENDER)) { | 426 | if (!i965_reset(dev, GDRST_RENDER)) { |
328 | atomic_set(&dev_priv->mm.wedged, 0); | 427 | atomic_set(&dev_priv->mm.wedged, 0); |
329 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); | 428 | kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); |
330 | } | 429 | } |
331 | } else { | 430 | } else { |
332 | printk("reboot required\n"); | 431 | DRM_DEBUG_DRIVER("reboot required\n"); |
333 | } | 432 | } |
334 | } | 433 | } |
335 | } | 434 | } |
336 | 435 | ||
436 | static struct drm_i915_error_object * | ||
437 | i915_error_object_create(struct drm_device *dev, | ||
438 | struct drm_gem_object *src) | ||
439 | { | ||
440 | struct drm_i915_error_object *dst; | ||
441 | struct drm_i915_gem_object *src_priv; | ||
442 | int page, page_count; | ||
443 | |||
444 | if (src == NULL) | ||
445 | return NULL; | ||
446 | |||
447 | src_priv = to_intel_bo(src); | ||
448 | if (src_priv->pages == NULL) | ||
449 | return NULL; | ||
450 | |||
451 | page_count = src->size / PAGE_SIZE; | ||
452 | |||
453 | dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC); | ||
454 | if (dst == NULL) | ||
455 | return NULL; | ||
456 | |||
457 | for (page = 0; page < page_count; page++) { | ||
458 | void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC); | ||
459 | unsigned long flags; | ||
460 | |||
461 | if (d == NULL) | ||
462 | goto unwind; | ||
463 | local_irq_save(flags); | ||
464 | s = kmap_atomic(src_priv->pages[page], KM_IRQ0); | ||
465 | memcpy(d, s, PAGE_SIZE); | ||
466 | kunmap_atomic(s, KM_IRQ0); | ||
467 | local_irq_restore(flags); | ||
468 | dst->pages[page] = d; | ||
469 | } | ||
470 | dst->page_count = page_count; | ||
471 | dst->gtt_offset = src_priv->gtt_offset; | ||
472 | |||
473 | return dst; | ||
474 | |||
475 | unwind: | ||
476 | while (page--) | ||
477 | kfree(dst->pages[page]); | ||
478 | kfree(dst); | ||
479 | return NULL; | ||
480 | } | ||
481 | |||
482 | static void | ||
483 | i915_error_object_free(struct drm_i915_error_object *obj) | ||
484 | { | ||
485 | int page; | ||
486 | |||
487 | if (obj == NULL) | ||
488 | return; | ||
489 | |||
490 | for (page = 0; page < obj->page_count; page++) | ||
491 | kfree(obj->pages[page]); | ||
492 | |||
493 | kfree(obj); | ||
494 | } | ||
495 | |||
496 | static void | ||
497 | i915_error_state_free(struct drm_device *dev, | ||
498 | struct drm_i915_error_state *error) | ||
499 | { | ||
500 | i915_error_object_free(error->batchbuffer[0]); | ||
501 | i915_error_object_free(error->batchbuffer[1]); | ||
502 | i915_error_object_free(error->ringbuffer); | ||
503 | kfree(error->active_bo); | ||
504 | kfree(error); | ||
505 | } | ||
506 | |||
507 | static u32 | ||
508 | i915_get_bbaddr(struct drm_device *dev, u32 *ring) | ||
509 | { | ||
510 | u32 cmd; | ||
511 | |||
512 | if (IS_I830(dev) || IS_845G(dev)) | ||
513 | cmd = MI_BATCH_BUFFER; | ||
514 | else if (IS_I965G(dev)) | ||
515 | cmd = (MI_BATCH_BUFFER_START | (2 << 6) | | ||
516 | MI_BATCH_NON_SECURE_I965); | ||
517 | else | ||
518 | cmd = (MI_BATCH_BUFFER_START | (2 << 6)); | ||
519 | |||
520 | return ring[0] == cmd ? ring[1] : 0; | ||
521 | } | ||
522 | |||
523 | static u32 | ||
524 | i915_ringbuffer_last_batch(struct drm_device *dev) | ||
525 | { | ||
526 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
527 | u32 head, bbaddr; | ||
528 | u32 *ring; | ||
529 | |||
530 | /* Locate the current position in the ringbuffer and walk back | ||
531 | * to find the most recently dispatched batch buffer. | ||
532 | */ | ||
533 | bbaddr = 0; | ||
534 | head = I915_READ(PRB0_HEAD) & HEAD_ADDR; | ||
535 | ring = (u32 *)(dev_priv->ring.virtual_start + head); | ||
536 | |||
537 | while (--ring >= (u32 *)dev_priv->ring.virtual_start) { | ||
538 | bbaddr = i915_get_bbaddr(dev, ring); | ||
539 | if (bbaddr) | ||
540 | break; | ||
541 | } | ||
542 | |||
543 | if (bbaddr == 0) { | ||
544 | ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size); | ||
545 | while (--ring >= (u32 *)dev_priv->ring.virtual_start) { | ||
546 | bbaddr = i915_get_bbaddr(dev, ring); | ||
547 | if (bbaddr) | ||
548 | break; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | return bbaddr; | ||
553 | } | ||
554 | |||
337 | /** | 555 | /** |
338 | * i915_capture_error_state - capture an error record for later analysis | 556 | * i915_capture_error_state - capture an error record for later analysis |
339 | * @dev: drm device | 557 | * @dev: drm device |
@@ -346,19 +564,26 @@ static void i915_error_work_func(struct work_struct *work) | |||
346 | static void i915_capture_error_state(struct drm_device *dev) | 564 | static void i915_capture_error_state(struct drm_device *dev) |
347 | { | 565 | { |
348 | struct drm_i915_private *dev_priv = dev->dev_private; | 566 | struct drm_i915_private *dev_priv = dev->dev_private; |
567 | struct drm_i915_gem_object *obj_priv; | ||
349 | struct drm_i915_error_state *error; | 568 | struct drm_i915_error_state *error; |
569 | struct drm_gem_object *batchbuffer[2]; | ||
350 | unsigned long flags; | 570 | unsigned long flags; |
571 | u32 bbaddr; | ||
572 | int count; | ||
351 | 573 | ||
352 | spin_lock_irqsave(&dev_priv->error_lock, flags); | 574 | spin_lock_irqsave(&dev_priv->error_lock, flags); |
353 | if (dev_priv->first_error) | 575 | error = dev_priv->first_error; |
354 | goto out; | 576 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); |
577 | if (error) | ||
578 | return; | ||
355 | 579 | ||
356 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | 580 | error = kmalloc(sizeof(*error), GFP_ATOMIC); |
357 | if (!error) { | 581 | if (!error) { |
358 | DRM_DEBUG("out ot memory, not capturing error state\n"); | 582 | DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); |
359 | goto out; | 583 | return; |
360 | } | 584 | } |
361 | 585 | ||
586 | error->seqno = i915_get_gem_seqno(dev); | ||
362 | error->eir = I915_READ(EIR); | 587 | error->eir = I915_READ(EIR); |
363 | error->pgtbl_er = I915_READ(PGTBL_ER); | 588 | error->pgtbl_er = I915_READ(PGTBL_ER); |
364 | error->pipeastat = I915_READ(PIPEASTAT); | 589 | error->pipeastat = I915_READ(PIPEASTAT); |
@@ -369,6 +594,7 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
369 | error->ipehr = I915_READ(IPEHR); | 594 | error->ipehr = I915_READ(IPEHR); |
370 | error->instdone = I915_READ(INSTDONE); | 595 | error->instdone = I915_READ(INSTDONE); |
371 | error->acthd = I915_READ(ACTHD); | 596 | error->acthd = I915_READ(ACTHD); |
597 | error->bbaddr = 0; | ||
372 | } else { | 598 | } else { |
373 | error->ipeir = I915_READ(IPEIR_I965); | 599 | error->ipeir = I915_READ(IPEIR_I965); |
374 | error->ipehr = I915_READ(IPEHR_I965); | 600 | error->ipehr = I915_READ(IPEHR_I965); |
@@ -376,14 +602,101 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
376 | error->instps = I915_READ(INSTPS); | 602 | error->instps = I915_READ(INSTPS); |
377 | error->instdone1 = I915_READ(INSTDONE1); | 603 | error->instdone1 = I915_READ(INSTDONE1); |
378 | error->acthd = I915_READ(ACTHD_I965); | 604 | error->acthd = I915_READ(ACTHD_I965); |
605 | error->bbaddr = I915_READ64(BB_ADDR); | ||
379 | } | 606 | } |
380 | 607 | ||
381 | do_gettimeofday(&error->time); | 608 | bbaddr = i915_ringbuffer_last_batch(dev); |
609 | |||
610 | /* Grab the current batchbuffer, most likely to have crashed. */ | ||
611 | batchbuffer[0] = NULL; | ||
612 | batchbuffer[1] = NULL; | ||
613 | count = 0; | ||
614 | list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { | ||
615 | struct drm_gem_object *obj = obj_priv->obj; | ||
616 | |||
617 | if (batchbuffer[0] == NULL && | ||
618 | bbaddr >= obj_priv->gtt_offset && | ||
619 | bbaddr < obj_priv->gtt_offset + obj->size) | ||
620 | batchbuffer[0] = obj; | ||
621 | |||
622 | if (batchbuffer[1] == NULL && | ||
623 | error->acthd >= obj_priv->gtt_offset && | ||
624 | error->acthd < obj_priv->gtt_offset + obj->size && | ||
625 | batchbuffer[0] != obj) | ||
626 | batchbuffer[1] = obj; | ||
627 | |||
628 | count++; | ||
629 | } | ||
630 | |||
631 | /* We need to copy these to an anonymous buffer as the simplest | ||
632 | * method to avoid being overwritten by userpace. | ||
633 | */ | ||
634 | error->batchbuffer[0] = i915_error_object_create(dev, batchbuffer[0]); | ||
635 | error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]); | ||
636 | |||
637 | /* Record the ringbuffer */ | ||
638 | error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj); | ||
639 | |||
640 | /* Record buffers on the active list. */ | ||
641 | error->active_bo = NULL; | ||
642 | error->active_bo_count = 0; | ||
643 | |||
644 | if (count) | ||
645 | error->active_bo = kmalloc(sizeof(*error->active_bo)*count, | ||
646 | GFP_ATOMIC); | ||
647 | |||
648 | if (error->active_bo) { | ||
649 | int i = 0; | ||
650 | list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { | ||
651 | struct drm_gem_object *obj = obj_priv->obj; | ||
652 | |||
653 | error->active_bo[i].size = obj->size; | ||
654 | error->active_bo[i].name = obj->name; | ||
655 | error->active_bo[i].seqno = obj_priv->last_rendering_seqno; | ||
656 | error->active_bo[i].gtt_offset = obj_priv->gtt_offset; | ||
657 | error->active_bo[i].read_domains = obj->read_domains; | ||
658 | error->active_bo[i].write_domain = obj->write_domain; | ||
659 | error->active_bo[i].fence_reg = obj_priv->fence_reg; | ||
660 | error->active_bo[i].pinned = 0; | ||
661 | if (obj_priv->pin_count > 0) | ||
662 | error->active_bo[i].pinned = 1; | ||
663 | if (obj_priv->user_pin_count > 0) | ||
664 | error->active_bo[i].pinned = -1; | ||
665 | error->active_bo[i].tiling = obj_priv->tiling_mode; | ||
666 | error->active_bo[i].dirty = obj_priv->dirty; | ||
667 | error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED; | ||
668 | |||
669 | if (++i == count) | ||
670 | break; | ||
671 | } | ||
672 | error->active_bo_count = i; | ||
673 | } | ||
382 | 674 | ||
383 | dev_priv->first_error = error; | 675 | do_gettimeofday(&error->time); |
384 | 676 | ||
385 | out: | 677 | spin_lock_irqsave(&dev_priv->error_lock, flags); |
678 | if (dev_priv->first_error == NULL) { | ||
679 | dev_priv->first_error = error; | ||
680 | error = NULL; | ||
681 | } | ||
386 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | 682 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); |
683 | |||
684 | if (error) | ||
685 | i915_error_state_free(dev, error); | ||
686 | } | ||
687 | |||
688 | void i915_destroy_error_state(struct drm_device *dev) | ||
689 | { | ||
690 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
691 | struct drm_i915_error_state *error; | ||
692 | |||
693 | spin_lock(&dev_priv->error_lock); | ||
694 | error = dev_priv->first_error; | ||
695 | dev_priv->first_error = NULL; | ||
696 | spin_unlock(&dev_priv->error_lock); | ||
697 | |||
698 | if (error) | ||
699 | i915_error_state_free(dev, error); | ||
387 | } | 700 | } |
388 | 701 | ||
389 | /** | 702 | /** |
@@ -512,7 +825,6 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) | |||
512 | /* | 825 | /* |
513 | * Wakeup waiting processes so they don't hang | 826 | * Wakeup waiting processes so they don't hang |
514 | */ | 827 | */ |
515 | printk("i915: Waking up sleeping processes\n"); | ||
516 | DRM_WAKEUP(&dev_priv->irq_queue); | 828 | DRM_WAKEUP(&dev_priv->irq_queue); |
517 | } | 829 | } |
518 | 830 | ||
@@ -535,8 +847,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
535 | 847 | ||
536 | atomic_inc(&dev_priv->irq_received); | 848 | atomic_inc(&dev_priv->irq_received); |
537 | 849 | ||
538 | if (IS_IGDNG(dev)) | 850 | if (HAS_PCH_SPLIT(dev)) |
539 | return igdng_irq_handler(dev); | 851 | return ironlake_irq_handler(dev); |
540 | 852 | ||
541 | iir = I915_READ(IIR); | 853 | iir = I915_READ(IIR); |
542 | 854 | ||
@@ -568,14 +880,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
568 | */ | 880 | */ |
569 | if (pipea_stats & 0x8000ffff) { | 881 | if (pipea_stats & 0x8000ffff) { |
570 | if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) | 882 | if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) |
571 | DRM_DEBUG("pipe a underrun\n"); | 883 | DRM_DEBUG_DRIVER("pipe a underrun\n"); |
572 | I915_WRITE(PIPEASTAT, pipea_stats); | 884 | I915_WRITE(PIPEASTAT, pipea_stats); |
573 | irq_received = 1; | 885 | irq_received = 1; |
574 | } | 886 | } |
575 | 887 | ||
576 | if (pipeb_stats & 0x8000ffff) { | 888 | if (pipeb_stats & 0x8000ffff) { |
577 | if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) | 889 | if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) |
578 | DRM_DEBUG("pipe b underrun\n"); | 890 | DRM_DEBUG_DRIVER("pipe b underrun\n"); |
579 | I915_WRITE(PIPEBSTAT, pipeb_stats); | 891 | I915_WRITE(PIPEBSTAT, pipeb_stats); |
580 | irq_received = 1; | 892 | irq_received = 1; |
581 | } | 893 | } |
@@ -591,7 +903,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
591 | (iir & I915_DISPLAY_PORT_INTERRUPT)) { | 903 | (iir & I915_DISPLAY_PORT_INTERRUPT)) { |
592 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); | 904 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); |
593 | 905 | ||
594 | DRM_DEBUG("hotplug event received, stat 0x%08x\n", | 906 | DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", |
595 | hotplug_status); | 907 | hotplug_status); |
596 | if (hotplug_status & dev_priv->hotplug_supported_mask) | 908 | if (hotplug_status & dev_priv->hotplug_supported_mask) |
597 | queue_work(dev_priv->wq, | 909 | queue_work(dev_priv->wq, |
@@ -599,27 +911,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
599 | 911 | ||
600 | I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); | 912 | I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); |
601 | I915_READ(PORT_HOTPLUG_STAT); | 913 | I915_READ(PORT_HOTPLUG_STAT); |
602 | |||
603 | /* EOS interrupts occurs */ | ||
604 | if (IS_IGD(dev) && | ||
605 | (hotplug_status & CRT_EOS_INT_STATUS)) { | ||
606 | u32 temp; | ||
607 | |||
608 | DRM_DEBUG("EOS interrupt occurs\n"); | ||
609 | /* status is already cleared */ | ||
610 | temp = I915_READ(ADPA); | ||
611 | temp &= ~ADPA_DAC_ENABLE; | ||
612 | I915_WRITE(ADPA, temp); | ||
613 | |||
614 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
615 | temp &= ~CRT_EOS_INT_EN; | ||
616 | I915_WRITE(PORT_HOTPLUG_EN, temp); | ||
617 | |||
618 | temp = I915_READ(PORT_HOTPLUG_STAT); | ||
619 | if (temp & CRT_EOS_INT_STATUS) | ||
620 | I915_WRITE(PORT_HOTPLUG_STAT, | ||
621 | CRT_EOS_INT_STATUS); | ||
622 | } | ||
623 | } | 914 | } |
624 | 915 | ||
625 | I915_WRITE(IIR, iir); | 916 | I915_WRITE(IIR, iir); |
@@ -641,14 +932,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
641 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 932 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); |
642 | } | 933 | } |
643 | 934 | ||
935 | if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) | ||
936 | intel_prepare_page_flip(dev, 0); | ||
937 | |||
938 | if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) | ||
939 | intel_prepare_page_flip(dev, 1); | ||
940 | |||
644 | if (pipea_stats & vblank_status) { | 941 | if (pipea_stats & vblank_status) { |
645 | vblank++; | 942 | vblank++; |
646 | drm_handle_vblank(dev, 0); | 943 | drm_handle_vblank(dev, 0); |
944 | intel_finish_page_flip(dev, 0); | ||
647 | } | 945 | } |
648 | 946 | ||
649 | if (pipeb_stats & vblank_status) { | 947 | if (pipeb_stats & vblank_status) { |
650 | vblank++; | 948 | vblank++; |
651 | drm_handle_vblank(dev, 1); | 949 | drm_handle_vblank(dev, 1); |
950 | intel_finish_page_flip(dev, 1); | ||
652 | } | 951 | } |
653 | 952 | ||
654 | if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || | 953 | if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || |
@@ -684,7 +983,7 @@ static int i915_emit_irq(struct drm_device * dev) | |||
684 | 983 | ||
685 | i915_kernel_lost_context(dev); | 984 | i915_kernel_lost_context(dev); |
686 | 985 | ||
687 | DRM_DEBUG("\n"); | 986 | DRM_DEBUG_DRIVER("\n"); |
688 | 987 | ||
689 | dev_priv->counter++; | 988 | dev_priv->counter++; |
690 | if (dev_priv->counter > 0x7FFFFFFFUL) | 989 | if (dev_priv->counter > 0x7FFFFFFFUL) |
@@ -709,8 +1008,8 @@ void i915_user_irq_get(struct drm_device *dev) | |||
709 | 1008 | ||
710 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1009 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
711 | if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) { | 1010 | if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) { |
712 | if (IS_IGDNG(dev)) | 1011 | if (HAS_PCH_SPLIT(dev)) |
713 | igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT); | 1012 | ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY); |
714 | else | 1013 | else |
715 | i915_enable_irq(dev_priv, I915_USER_INTERRUPT); | 1014 | i915_enable_irq(dev_priv, I915_USER_INTERRUPT); |
716 | } | 1015 | } |
@@ -725,8 +1024,8 @@ void i915_user_irq_put(struct drm_device *dev) | |||
725 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1024 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
726 | BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); | 1025 | BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); |
727 | if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { | 1026 | if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { |
728 | if (IS_IGDNG(dev)) | 1027 | if (HAS_PCH_SPLIT(dev)) |
729 | igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT); | 1028 | ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY); |
730 | else | 1029 | else |
731 | i915_disable_irq(dev_priv, I915_USER_INTERRUPT); | 1030 | i915_disable_irq(dev_priv, I915_USER_INTERRUPT); |
732 | } | 1031 | } |
@@ -749,7 +1048,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) | |||
749 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; | 1048 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; |
750 | int ret = 0; | 1049 | int ret = 0; |
751 | 1050 | ||
752 | DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, | 1051 | DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr, |
753 | READ_BREADCRUMB(dev_priv)); | 1052 | READ_BREADCRUMB(dev_priv)); |
754 | 1053 | ||
755 | if (READ_BREADCRUMB(dev_priv) >= irq_nr) { | 1054 | if (READ_BREADCRUMB(dev_priv) >= irq_nr) { |
@@ -832,11 +1131,11 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) | |||
832 | if (!(pipeconf & PIPEACONF_ENABLE)) | 1131 | if (!(pipeconf & PIPEACONF_ENABLE)) |
833 | return -EINVAL; | 1132 | return -EINVAL; |
834 | 1133 | ||
835 | if (IS_IGDNG(dev)) | ||
836 | return 0; | ||
837 | |||
838 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1134 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
839 | if (IS_I965G(dev)) | 1135 | if (HAS_PCH_SPLIT(dev)) |
1136 | ironlake_enable_display_irq(dev_priv, (pipe == 0) ? | ||
1137 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | ||
1138 | else if (IS_I965G(dev)) | ||
840 | i915_enable_pipestat(dev_priv, pipe, | 1139 | i915_enable_pipestat(dev_priv, pipe, |
841 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 1140 | PIPE_START_VBLANK_INTERRUPT_ENABLE); |
842 | else | 1141 | else |
@@ -854,13 +1153,14 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) | |||
854 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1153 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
855 | unsigned long irqflags; | 1154 | unsigned long irqflags; |
856 | 1155 | ||
857 | if (IS_IGDNG(dev)) | ||
858 | return; | ||
859 | |||
860 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 1156 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
861 | i915_disable_pipestat(dev_priv, pipe, | 1157 | if (HAS_PCH_SPLIT(dev)) |
862 | PIPE_VBLANK_INTERRUPT_ENABLE | | 1158 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? |
863 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | 1159 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); |
1160 | else | ||
1161 | i915_disable_pipestat(dev_priv, pipe, | ||
1162 | PIPE_VBLANK_INTERRUPT_ENABLE | | ||
1163 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | ||
864 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); | 1164 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); |
865 | } | 1165 | } |
866 | 1166 | ||
@@ -868,7 +1168,7 @@ void i915_enable_interrupt (struct drm_device *dev) | |||
868 | { | 1168 | { |
869 | struct drm_i915_private *dev_priv = dev->dev_private; | 1169 | struct drm_i915_private *dev_priv = dev->dev_private; |
870 | 1170 | ||
871 | if (!IS_IGDNG(dev)) | 1171 | if (!HAS_PCH_SPLIT(dev)) |
872 | opregion_enable_asle(dev); | 1172 | opregion_enable_asle(dev); |
873 | dev_priv->irq_enabled = 1; | 1173 | dev_priv->irq_enabled = 1; |
874 | } | 1174 | } |
@@ -944,7 +1244,11 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
944 | struct drm_device *dev = (struct drm_device *)data; | 1244 | struct drm_device *dev = (struct drm_device *)data; |
945 | drm_i915_private_t *dev_priv = dev->dev_private; | 1245 | drm_i915_private_t *dev_priv = dev->dev_private; |
946 | uint32_t acthd; | 1246 | uint32_t acthd; |
947 | 1247 | ||
1248 | /* No reset support on this chip yet. */ | ||
1249 | if (IS_GEN6(dev)) | ||
1250 | return; | ||
1251 | |||
948 | if (!IS_I965G(dev)) | 1252 | if (!IS_I965G(dev)) |
949 | acthd = I915_READ(ACTHD); | 1253 | acthd = I915_READ(ACTHD); |
950 | else | 1254 | else |
@@ -976,7 +1280,7 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
976 | 1280 | ||
977 | /* drm_dma.h hooks | 1281 | /* drm_dma.h hooks |
978 | */ | 1282 | */ |
979 | static void igdng_irq_preinstall(struct drm_device *dev) | 1283 | static void ironlake_irq_preinstall(struct drm_device *dev) |
980 | { | 1284 | { |
981 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1285 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
982 | 1286 | ||
@@ -992,17 +1296,25 @@ static void igdng_irq_preinstall(struct drm_device *dev) | |||
992 | I915_WRITE(GTIMR, 0xffffffff); | 1296 | I915_WRITE(GTIMR, 0xffffffff); |
993 | I915_WRITE(GTIER, 0x0); | 1297 | I915_WRITE(GTIER, 0x0); |
994 | (void) I915_READ(GTIER); | 1298 | (void) I915_READ(GTIER); |
1299 | |||
1300 | /* south display irq */ | ||
1301 | I915_WRITE(SDEIMR, 0xffffffff); | ||
1302 | I915_WRITE(SDEIER, 0x0); | ||
1303 | (void) I915_READ(SDEIER); | ||
995 | } | 1304 | } |
996 | 1305 | ||
997 | static int igdng_irq_postinstall(struct drm_device *dev) | 1306 | static int ironlake_irq_postinstall(struct drm_device *dev) |
998 | { | 1307 | { |
999 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1308 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1000 | /* enable kind of interrupts always enabled */ | 1309 | /* enable kind of interrupts always enabled */ |
1001 | u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */; | 1310 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | |
1002 | u32 render_mask = GT_USER_INTERRUPT; | 1311 | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; |
1312 | u32 render_mask = GT_PIPE_NOTIFY; | ||
1313 | u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | | ||
1314 | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; | ||
1003 | 1315 | ||
1004 | dev_priv->irq_mask_reg = ~display_mask; | 1316 | dev_priv->irq_mask_reg = ~display_mask; |
1005 | dev_priv->de_irq_enable_reg = display_mask; | 1317 | dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK; |
1006 | 1318 | ||
1007 | /* should always can generate irq */ | 1319 | /* should always can generate irq */ |
1008 | I915_WRITE(DEIIR, I915_READ(DEIIR)); | 1320 | I915_WRITE(DEIIR, I915_READ(DEIIR)); |
@@ -1019,6 +1331,21 @@ static int igdng_irq_postinstall(struct drm_device *dev) | |||
1019 | I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); | 1331 | I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); |
1020 | (void) I915_READ(GTIER); | 1332 | (void) I915_READ(GTIER); |
1021 | 1333 | ||
1334 | dev_priv->pch_irq_mask_reg = ~hotplug_mask; | ||
1335 | dev_priv->pch_irq_enable_reg = hotplug_mask; | ||
1336 | |||
1337 | I915_WRITE(SDEIIR, I915_READ(SDEIIR)); | ||
1338 | I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg); | ||
1339 | I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg); | ||
1340 | (void) I915_READ(SDEIER); | ||
1341 | |||
1342 | if (IS_IRONLAKE_M(dev)) { | ||
1343 | /* Clear & enable PCU event interrupts */ | ||
1344 | I915_WRITE(DEIIR, DE_PCU_EVENT); | ||
1345 | I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT); | ||
1346 | ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT); | ||
1347 | } | ||
1348 | |||
1022 | return 0; | 1349 | return 0; |
1023 | } | 1350 | } |
1024 | 1351 | ||
@@ -1031,8 +1358,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) | |||
1031 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); | 1358 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); |
1032 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); | 1359 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); |
1033 | 1360 | ||
1034 | if (IS_IGDNG(dev)) { | 1361 | if (HAS_PCH_SPLIT(dev)) { |
1035 | igdng_irq_preinstall(dev); | 1362 | ironlake_irq_preinstall(dev); |
1036 | return; | 1363 | return; |
1037 | } | 1364 | } |
1038 | 1365 | ||
@@ -1049,6 +1376,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) | |||
1049 | (void) I915_READ(IER); | 1376 | (void) I915_READ(IER); |
1050 | } | 1377 | } |
1051 | 1378 | ||
1379 | /* | ||
1380 | * Must be called after intel_modeset_init or hotplug interrupts won't be | ||
1381 | * enabled correctly. | ||
1382 | */ | ||
1052 | int i915_driver_irq_postinstall(struct drm_device *dev) | 1383 | int i915_driver_irq_postinstall(struct drm_device *dev) |
1053 | { | 1384 | { |
1054 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1385 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -1059,8 +1390,8 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
1059 | 1390 | ||
1060 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; | 1391 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; |
1061 | 1392 | ||
1062 | if (IS_IGDNG(dev)) | 1393 | if (HAS_PCH_SPLIT(dev)) |
1063 | return igdng_irq_postinstall(dev); | 1394 | return ironlake_irq_postinstall(dev); |
1064 | 1395 | ||
1065 | /* Unmask the interrupts that we always want on. */ | 1396 | /* Unmask the interrupts that we always want on. */ |
1066 | dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; | 1397 | dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; |
@@ -1071,19 +1402,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
1071 | if (I915_HAS_HOTPLUG(dev)) { | 1402 | if (I915_HAS_HOTPLUG(dev)) { |
1072 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | 1403 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); |
1073 | 1404 | ||
1074 | /* Leave other bits alone */ | 1405 | /* Note HDMI and DP share bits */ |
1075 | hotplug_en |= HOTPLUG_EN_MASK; | 1406 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) |
1407 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; | ||
1408 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) | ||
1409 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | ||
1410 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | ||
1411 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | ||
1412 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | ||
1413 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | ||
1414 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | ||
1415 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | ||
1416 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) | ||
1417 | hotplug_en |= CRT_HOTPLUG_INT_EN; | ||
1418 | /* Ignore TV since it's buggy */ | ||
1419 | |||
1076 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); | 1420 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
1077 | 1421 | ||
1078 | dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS | | ||
1079 | TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS | | ||
1080 | SDVOB_HOTPLUG_INT_STATUS; | ||
1081 | if (IS_G4X(dev)) { | ||
1082 | dev_priv->hotplug_supported_mask |= | ||
1083 | HDMIB_HOTPLUG_INT_STATUS | | ||
1084 | HDMIC_HOTPLUG_INT_STATUS | | ||
1085 | HDMID_HOTPLUG_INT_STATUS; | ||
1086 | } | ||
1087 | /* Enable in IER... */ | 1422 | /* Enable in IER... */ |
1088 | enable_mask |= I915_DISPLAY_PORT_INTERRUPT; | 1423 | enable_mask |= I915_DISPLAY_PORT_INTERRUPT; |
1089 | /* and unmask in IMR */ | 1424 | /* and unmask in IMR */ |
@@ -1120,7 +1455,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) | |||
1120 | return 0; | 1455 | return 0; |
1121 | } | 1456 | } |
1122 | 1457 | ||
1123 | static void igdng_irq_uninstall(struct drm_device *dev) | 1458 | static void ironlake_irq_uninstall(struct drm_device *dev) |
1124 | { | 1459 | { |
1125 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1460 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1126 | I915_WRITE(HWSTAM, 0xffffffff); | 1461 | I915_WRITE(HWSTAM, 0xffffffff); |
@@ -1143,8 +1478,8 @@ void i915_driver_irq_uninstall(struct drm_device * dev) | |||
1143 | 1478 | ||
1144 | dev_priv->vblank_pipe = 0; | 1479 | dev_priv->vblank_pipe = 0; |
1145 | 1480 | ||
1146 | if (IS_IGDNG(dev)) { | 1481 | if (HAS_PCH_SPLIT(dev)) { |
1147 | igdng_irq_uninstall(dev); | 1482 | ironlake_irq_uninstall(dev); |
1148 | return; | 1483 | return; |
1149 | } | 1484 | } |
1150 | 1485 | ||