diff options
| author | David S. Miller <davem@davemloft.net> | 2009-03-19 02:53:57 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-03-19 02:53:57 -0400 |
| commit | 0702b30dd821ac8a4103ddbe545518713fdca9be (patch) | |
| tree | 8ce0c9f5e58c5ccb99870505eecd139986caa05e /drivers/gpu | |
| parent | 192d7a4667c6d11d1a174ec4cad9a3c5d5f9043c (diff) | |
| parent | a1e4ee22863d41a6fbb24310d7951836cb6dafe7 (diff) | |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers/gpu')
25 files changed, 570 insertions, 263 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 4be3acbaaf9a..3a22eb9be378 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -80,18 +80,17 @@ config DRM_I915 | |||
| 80 | XFree86 4.4 and above. If unsure, build this and i830 as modules and | 80 | XFree86 4.4 and above. If unsure, build this and i830 as modules and |
| 81 | the X server will load the correct one. | 81 | the X server will load the correct one. |
| 82 | 82 | ||
| 83 | endchoice | ||
| 84 | |||
| 85 | config DRM_I915_KMS | 83 | config DRM_I915_KMS |
| 86 | bool "Enable modesetting on intel by default" | 84 | bool "Enable modesetting on intel by default" |
| 87 | depends on DRM_I915 | 85 | depends on DRM_I915 |
| 88 | help | 86 | help |
| 89 | Choose this option if you want kernel modesetting enabled by default, | 87 | Choose this option if you want kernel modesetting enabled by default, |
| 90 | and you have a new enough userspace to support this. Running old | 88 | and you have a new enough userspace to support this. Running old |
| 91 | userspaces with this enabled will cause pain. Note that this causes | 89 | userspaces with this enabled will cause pain. Note that this causes |
| 92 | the driver to bind to PCI devices, which precludes loading things | 90 | the driver to bind to PCI devices, which precludes loading things |
| 93 | like intelfb. | 91 | like intelfb. |
| 94 | 92 | ||
| 93 | endchoice | ||
| 95 | 94 | ||
| 96 | config DRM_MGA | 95 | config DRM_MGA |
| 97 | tristate "Matrox g200/g400" | 96 | tristate "Matrox g200/g400" |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 72c667f9bee1..12715d3c078d 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
| @@ -420,7 +420,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) | |||
| 420 | dev->sigdata.lock = NULL; | 420 | dev->sigdata.lock = NULL; |
| 421 | master->lock.hw_lock = NULL; /* SHM removed */ | 421 | master->lock.hw_lock = NULL; /* SHM removed */ |
| 422 | master->lock.file_priv = NULL; | 422 | master->lock.file_priv = NULL; |
| 423 | wake_up_interruptible(&master->lock.lock_queue); | 423 | wake_up_interruptible_all(&master->lock.lock_queue); |
| 424 | } | 424 | } |
| 425 | break; | 425 | break; |
| 426 | case _DRM_AGP: | 426 | case _DRM_AGP: |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index bfce0992fefb..94a768871734 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -1741,9 +1741,8 @@ out: | |||
| 1741 | * RETURNS: | 1741 | * RETURNS: |
| 1742 | * Zero on success, errno on failure. | 1742 | * Zero on success, errno on failure. |
| 1743 | */ | 1743 | */ |
| 1744 | void drm_fb_release(struct file *filp) | 1744 | void drm_fb_release(struct drm_file *priv) |
| 1745 | { | 1745 | { |
| 1746 | struct drm_file *priv = filp->private_data; | ||
| 1747 | struct drm_device *dev = priv->minor->dev; | 1746 | struct drm_device *dev = priv->minor->dev; |
| 1748 | struct drm_framebuffer *fb, *tfb; | 1747 | struct drm_framebuffer *fb, *tfb; |
| 1749 | 1748 | ||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 964c5eb1fada..1c3a8c557140 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -452,6 +452,59 @@ static void drm_setup_crtcs(struct drm_device *dev) | |||
| 452 | kfree(modes); | 452 | kfree(modes); |
| 453 | kfree(enabled); | 453 | kfree(enabled); |
| 454 | } | 454 | } |
| 455 | |||
| 456 | /** | ||
| 457 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | ||
| 458 | * @encoder: encoder to test | ||
| 459 | * @crtc: crtc to test | ||
| 460 | * | ||
| 461 | * Return false if @encoder can't be driven by @crtc, true otherwise. | ||
| 462 | */ | ||
| 463 | static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, | ||
| 464 | struct drm_crtc *crtc) | ||
| 465 | { | ||
| 466 | struct drm_device *dev; | ||
| 467 | struct drm_crtc *tmp; | ||
| 468 | int crtc_mask = 1; | ||
| 469 | |||
| 470 | WARN(!crtc, "checking null crtc?"); | ||
| 471 | |||
| 472 | dev = crtc->dev; | ||
| 473 | |||
| 474 | list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { | ||
| 475 | if (tmp == crtc) | ||
| 476 | break; | ||
| 477 | crtc_mask <<= 1; | ||
| 478 | } | ||
| 479 | |||
| 480 | if (encoder->possible_crtcs & crtc_mask) | ||
| 481 | return true; | ||
| 482 | return false; | ||
| 483 | } | ||
| 484 | |||
| 485 | /* | ||
| 486 | * Check the CRTC we're going to map each output to vs. its current | ||
| 487 | * CRTC. If they don't match, we have to disable the output and the CRTC | ||
| 488 | * since the driver will have to re-route things. | ||
| 489 | */ | ||
| 490 | static void | ||
| 491 | drm_crtc_prepare_encoders(struct drm_device *dev) | ||
| 492 | { | ||
| 493 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
| 494 | struct drm_encoder *encoder; | ||
| 495 | |||
| 496 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 497 | encoder_funcs = encoder->helper_private; | ||
| 498 | /* Disable unused encoders */ | ||
| 499 | if (encoder->crtc == NULL) | ||
| 500 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | ||
| 501 | /* Disable encoders whose CRTC is about to change */ | ||
| 502 | if (encoder_funcs->get_crtc && | ||
| 503 | encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) | ||
| 504 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 455 | /** | 508 | /** |
| 456 | * drm_crtc_set_mode - set a mode | 509 | * drm_crtc_set_mode - set a mode |
| 457 | * @crtc: CRTC to program | 510 | * @crtc: CRTC to program |
| @@ -512,8 +565,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
| 512 | if (drm_mode_equal(&saved_mode, &crtc->mode)) { | 565 | if (drm_mode_equal(&saved_mode, &crtc->mode)) { |
| 513 | if (saved_x != crtc->x || saved_y != crtc->y || | 566 | if (saved_x != crtc->x || saved_y != crtc->y || |
| 514 | depth_changed || bpp_changed) { | 567 | depth_changed || bpp_changed) { |
| 515 | crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, | 568 | ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, |
| 516 | old_fb); | 569 | old_fb); |
| 517 | goto done; | 570 | goto done; |
| 518 | } | 571 | } |
| 519 | } | 572 | } |
| @@ -547,12 +600,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
| 547 | encoder_funcs->prepare(encoder); | 600 | encoder_funcs->prepare(encoder); |
| 548 | } | 601 | } |
| 549 | 602 | ||
| 603 | drm_crtc_prepare_encoders(dev); | ||
| 604 | |||
| 550 | crtc_funcs->prepare(crtc); | 605 | crtc_funcs->prepare(crtc); |
| 551 | 606 | ||
| 552 | /* Set up the DPLL and any encoders state that needs to adjust or depend | 607 | /* Set up the DPLL and any encoders state that needs to adjust or depend |
| 553 | * on the DPLL. | 608 | * on the DPLL. |
| 554 | */ | 609 | */ |
| 555 | crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); | 610 | ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); |
| 611 | if (!ret) | ||
| 612 | goto done; | ||
| 556 | 613 | ||
| 557 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 614 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 558 | 615 | ||
| @@ -615,7 +672,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 615 | struct drm_device *dev; | 672 | struct drm_device *dev; |
| 616 | struct drm_crtc **save_crtcs, *new_crtc; | 673 | struct drm_crtc **save_crtcs, *new_crtc; |
| 617 | struct drm_encoder **save_encoders, *new_encoder; | 674 | struct drm_encoder **save_encoders, *new_encoder; |
| 618 | struct drm_framebuffer *old_fb; | 675 | struct drm_framebuffer *old_fb = NULL; |
| 619 | bool save_enabled; | 676 | bool save_enabled; |
| 620 | bool mode_changed = false; | 677 | bool mode_changed = false; |
| 621 | bool fb_changed = false; | 678 | bool fb_changed = false; |
| @@ -666,9 +723,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 666 | * and then just flip_or_move it */ | 723 | * and then just flip_or_move it */ |
| 667 | if (set->crtc->fb != set->fb) { | 724 | if (set->crtc->fb != set->fb) { |
| 668 | /* If we have no fb then treat it as a full mode set */ | 725 | /* If we have no fb then treat it as a full mode set */ |
| 669 | if (set->crtc->fb == NULL) | 726 | if (set->crtc->fb == NULL) { |
| 727 | DRM_DEBUG("crtc has no fb, full mode set\n"); | ||
| 670 | mode_changed = true; | 728 | mode_changed = true; |
| 671 | else if ((set->fb->bits_per_pixel != | 729 | } else if ((set->fb->bits_per_pixel != |
| 672 | set->crtc->fb->bits_per_pixel) || | 730 | set->crtc->fb->bits_per_pixel) || |
| 673 | set->fb->depth != set->crtc->fb->depth) | 731 | set->fb->depth != set->crtc->fb->depth) |
| 674 | fb_changed = true; | 732 | fb_changed = true; |
| @@ -680,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 680 | fb_changed = true; | 738 | fb_changed = true; |
| 681 | 739 | ||
| 682 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { | 740 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { |
| 683 | DRM_DEBUG("modes are different\n"); | 741 | DRM_DEBUG("modes are different, full mode set\n"); |
| 684 | drm_mode_debug_printmodeline(&set->crtc->mode); | 742 | drm_mode_debug_printmodeline(&set->crtc->mode); |
| 685 | drm_mode_debug_printmodeline(set->mode); | 743 | drm_mode_debug_printmodeline(set->mode); |
| 686 | mode_changed = true; | 744 | mode_changed = true; |
| @@ -706,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 706 | } | 764 | } |
| 707 | 765 | ||
| 708 | if (new_encoder != connector->encoder) { | 766 | if (new_encoder != connector->encoder) { |
| 767 | DRM_DEBUG("encoder changed, full mode switch\n"); | ||
| 709 | mode_changed = true; | 768 | mode_changed = true; |
| 710 | connector->encoder = new_encoder; | 769 | connector->encoder = new_encoder; |
| 711 | } | 770 | } |
| @@ -732,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 732 | if (set->connectors[ro] == connector) | 791 | if (set->connectors[ro] == connector) |
| 733 | new_crtc = set->crtc; | 792 | new_crtc = set->crtc; |
| 734 | } | 793 | } |
| 794 | |||
| 795 | /* Make sure the new CRTC will work with the encoder */ | ||
| 796 | if (new_crtc && | ||
| 797 | !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { | ||
| 798 | ret = -EINVAL; | ||
| 799 | goto fail_set_mode; | ||
| 800 | } | ||
| 735 | if (new_crtc != connector->encoder->crtc) { | 801 | if (new_crtc != connector->encoder->crtc) { |
| 802 | DRM_DEBUG("crtc changed, full mode switch\n"); | ||
| 736 | mode_changed = true; | 803 | mode_changed = true; |
| 737 | connector->encoder->crtc = new_crtc; | 804 | connector->encoder->crtc = new_crtc; |
| 738 | } | 805 | } |
| 806 | DRM_DEBUG("setting connector %d crtc to %p\n", | ||
| 807 | connector->base.id, new_crtc); | ||
| 739 | } | 808 | } |
| 740 | 809 | ||
| 741 | /* mode_set_base is not a required function */ | 810 | /* mode_set_base is not a required function */ |
| @@ -752,6 +821,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 752 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, | 821 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
| 753 | set->x, set->y, | 822 | set->x, set->y, |
| 754 | old_fb)) { | 823 | old_fb)) { |
| 824 | DRM_ERROR("failed to set mode on crtc %p\n", | ||
| 825 | set->crtc); | ||
| 755 | ret = -EINVAL; | 826 | ret = -EINVAL; |
| 756 | goto fail_set_mode; | 827 | goto fail_set_mode; |
| 757 | } | 828 | } |
| @@ -765,7 +836,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 765 | old_fb = set->crtc->fb; | 836 | old_fb = set->crtc->fb; |
| 766 | if (set->crtc->fb != set->fb) | 837 | if (set->crtc->fb != set->fb) |
| 767 | set->crtc->fb = set->fb; | 838 | set->crtc->fb = set->fb; |
| 768 | crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); | 839 | ret = crtc_funcs->mode_set_base(set->crtc, |
| 840 | set->x, set->y, old_fb); | ||
| 841 | if (ret != 0) | ||
| 842 | goto fail_set_mode; | ||
| 769 | } | 843 | } |
| 770 | 844 | ||
| 771 | kfree(save_encoders); | 845 | kfree(save_encoders); |
| @@ -774,9 +848,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 774 | 848 | ||
| 775 | fail_set_mode: | 849 | fail_set_mode: |
| 776 | set->crtc->enabled = save_enabled; | 850 | set->crtc->enabled = save_enabled; |
| 851 | set->crtc->fb = old_fb; | ||
| 777 | count = 0; | 852 | count = 0; |
| 778 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | 853 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 854 | if (!connector->encoder) | ||
| 855 | continue; | ||
| 856 | |||
| 779 | connector->encoder->crtc = save_crtcs[count++]; | 857 | connector->encoder->crtc = save_crtcs[count++]; |
| 858 | } | ||
| 780 | fail_no_encoder: | 859 | fail_no_encoder: |
| 781 | kfree(save_crtcs); | 860 | kfree(save_crtcs); |
| 782 | count = 0; | 861 | count = 0; |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5a4d3244758a..a839a28d8ee6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -125,7 +125,7 @@ static bool edid_is_valid(struct edid *edid) | |||
| 125 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); | 125 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); |
| 126 | goto bad; | 126 | goto bad; |
| 127 | } | 127 | } |
| 128 | if (edid->revision <= 0 || edid->revision > 3) { | 128 | if (edid->revision > 3) { |
| 129 | DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); | 129 | DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision); |
| 130 | goto bad; | 130 | goto bad; |
| 131 | } | 131 | } |
| @@ -320,10 +320,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 320 | mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); | 320 | mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); |
| 321 | 321 | ||
| 322 | mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; | 322 | mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; |
| 323 | mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | | 323 | mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) | |
| 324 | pt->vsync_offset_lo); | 324 | pt->vsync_offset_lo); |
| 325 | mode->vsync_end = mode->vsync_start + | 325 | mode->vsync_end = mode->vsync_start + |
| 326 | ((pt->vsync_pulse_width_hi << 8) | | 326 | ((pt->vsync_pulse_width_hi << 4) | |
| 327 | pt->vsync_pulse_width_lo); | 327 | pt->vsync_pulse_width_lo); |
| 328 | mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); | 328 | mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); |
| 329 | 329 | ||
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index b06a53715853..f52663ebe016 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
| @@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 457 | if (dev->driver->driver_features & DRIVER_GEM) | 457 | if (dev->driver->driver_features & DRIVER_GEM) |
| 458 | drm_gem_release(dev, file_priv); | 458 | drm_gem_release(dev, file_priv); |
| 459 | 459 | ||
| 460 | if (dev->driver->driver_features & DRIVER_MODESET) | ||
| 461 | drm_fb_release(file_priv); | ||
| 462 | |||
| 460 | mutex_lock(&dev->ctxlist_mutex); | 463 | mutex_lock(&dev->ctxlist_mutex); |
| 461 | if (!list_empty(&dev->ctxlist)) { | 464 | if (!list_empty(&dev->ctxlist)) { |
| 462 | struct drm_ctx_list *pos, *n; | 465 | struct drm_ctx_list *pos, *n; |
| @@ -481,6 +484,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 481 | mutex_lock(&dev->struct_mutex); | 484 | mutex_lock(&dev->struct_mutex); |
| 482 | 485 | ||
| 483 | if (file_priv->is_master) { | 486 | if (file_priv->is_master) { |
| 487 | struct drm_master *master = file_priv->master; | ||
| 484 | struct drm_file *temp; | 488 | struct drm_file *temp; |
| 485 | list_for_each_entry(temp, &dev->filelist, lhead) { | 489 | list_for_each_entry(temp, &dev->filelist, lhead) { |
| 486 | if ((temp->master == file_priv->master) && | 490 | if ((temp->master == file_priv->master) && |
| @@ -488,6 +492,19 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 488 | temp->authenticated = 0; | 492 | temp->authenticated = 0; |
| 489 | } | 493 | } |
| 490 | 494 | ||
| 495 | /** | ||
| 496 | * Since the master is disappearing, so is the | ||
| 497 | * possibility to lock. | ||
| 498 | */ | ||
| 499 | |||
| 500 | if (master->lock.hw_lock) { | ||
| 501 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
| 502 | dev->sigdata.lock = NULL; | ||
| 503 | master->lock.hw_lock = NULL; | ||
| 504 | master->lock.file_priv = NULL; | ||
| 505 | wake_up_interruptible_all(&master->lock.lock_queue); | ||
| 506 | } | ||
| 507 | |||
| 491 | if (file_priv->minor->master == file_priv->master) { | 508 | if (file_priv->minor->master == file_priv->master) { |
| 492 | /* drop the reference held my the minor */ | 509 | /* drop the reference held my the minor */ |
| 493 | drm_master_put(&file_priv->minor->master); | 510 | drm_master_put(&file_priv->minor->master); |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 6915fb82d0b0..88d3368ffddd 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
| @@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev) | |||
| 104 | 104 | ||
| 105 | if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START, | 105 | if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START, |
| 106 | DRM_FILE_PAGE_OFFSET_SIZE)) { | 106 | DRM_FILE_PAGE_OFFSET_SIZE)) { |
| 107 | drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM); | ||
| 108 | drm_ht_remove(&mm->offset_hash); | 107 | drm_ht_remove(&mm->offset_hash); |
| 108 | drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM); | ||
| 109 | return -ENOMEM; | 109 | return -ENOMEM; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| @@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
| 295 | return -EBADF; | 295 | return -EBADF; |
| 296 | 296 | ||
| 297 | again: | 297 | again: |
| 298 | if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) | 298 | if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) { |
| 299 | return -ENOMEM; | 299 | ret = -ENOMEM; |
| 300 | goto err; | ||
| 301 | } | ||
| 300 | 302 | ||
| 301 | spin_lock(&dev->object_name_lock); | 303 | spin_lock(&dev->object_name_lock); |
| 302 | if (obj->name) { | 304 | if (!obj->name) { |
| 303 | args->name = obj->name; | 305 | ret = idr_get_new_above(&dev->object_name_idr, obj, 1, |
| 306 | &obj->name); | ||
| 307 | args->name = (uint64_t) obj->name; | ||
| 304 | spin_unlock(&dev->object_name_lock); | 308 | spin_unlock(&dev->object_name_lock); |
| 305 | return 0; | ||
| 306 | } | ||
| 307 | ret = idr_get_new_above(&dev->object_name_idr, obj, 1, | ||
| 308 | &obj->name); | ||
| 309 | spin_unlock(&dev->object_name_lock); | ||
| 310 | if (ret == -EAGAIN) | ||
| 311 | goto again; | ||
| 312 | 309 | ||
| 313 | if (ret != 0) { | 310 | if (ret == -EAGAIN) |
| 314 | mutex_lock(&dev->struct_mutex); | 311 | goto again; |
| 315 | drm_gem_object_unreference(obj); | ||
| 316 | mutex_unlock(&dev->struct_mutex); | ||
| 317 | return ret; | ||
| 318 | } | ||
| 319 | 312 | ||
| 320 | /* | 313 | if (ret != 0) |
| 321 | * Leave the reference from the lookup around as the | 314 | goto err; |
| 322 | * name table now holds one | ||
| 323 | */ | ||
| 324 | args->name = (uint64_t) obj->name; | ||
| 325 | 315 | ||
| 326 | return 0; | 316 | /* Allocate a reference for the name table. */ |
| 317 | drm_gem_object_reference(obj); | ||
| 318 | } else { | ||
| 319 | args->name = (uint64_t) obj->name; | ||
| 320 | spin_unlock(&dev->object_name_lock); | ||
| 321 | ret = 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | err: | ||
| 325 | mutex_lock(&dev->struct_mutex); | ||
| 326 | drm_gem_object_unreference(obj); | ||
| 327 | mutex_unlock(&dev->struct_mutex); | ||
| 328 | return ret; | ||
| 327 | } | 329 | } |
| 328 | 330 | ||
| 329 | /** | 331 | /** |
| @@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref) | |||
| 448 | spin_lock(&dev->object_name_lock); | 450 | spin_lock(&dev->object_name_lock); |
| 449 | if (obj->name) { | 451 | if (obj->name) { |
| 450 | idr_remove(&dev->object_name_idr, obj->name); | 452 | idr_remove(&dev->object_name_idr, obj->name); |
| 453 | obj->name = 0; | ||
| 451 | spin_unlock(&dev->object_name_lock); | 454 | spin_unlock(&dev->object_name_lock); |
| 452 | /* | 455 | /* |
| 453 | * The object name held a reference to this object, drop | 456 | * The object name held a reference to this object, drop |
| @@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref) | |||
| 460 | } | 463 | } |
| 461 | EXPORT_SYMBOL(drm_gem_object_handle_free); | 464 | EXPORT_SYMBOL(drm_gem_object_handle_free); |
| 462 | 465 | ||
| 466 | void drm_gem_vm_open(struct vm_area_struct *vma) | ||
| 467 | { | ||
| 468 | struct drm_gem_object *obj = vma->vm_private_data; | ||
| 469 | |||
| 470 | drm_gem_object_reference(obj); | ||
| 471 | } | ||
| 472 | EXPORT_SYMBOL(drm_gem_vm_open); | ||
| 473 | |||
| 474 | void drm_gem_vm_close(struct vm_area_struct *vma) | ||
| 475 | { | ||
| 476 | struct drm_gem_object *obj = vma->vm_private_data; | ||
| 477 | struct drm_device *dev = obj->dev; | ||
| 478 | |||
| 479 | mutex_lock(&dev->struct_mutex); | ||
| 480 | drm_gem_object_unreference(obj); | ||
| 481 | mutex_unlock(&dev->struct_mutex); | ||
| 482 | } | ||
| 483 | EXPORT_SYMBOL(drm_gem_vm_close); | ||
| 484 | |||
| 485 | |||
| 463 | /** | 486 | /** |
| 464 | * drm_gem_mmap - memory map routine for GEM objects | 487 | * drm_gem_mmap - memory map routine for GEM objects |
| 465 | * @filp: DRM file pointer | 488 | * @filp: DRM file pointer |
| @@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 521 | #endif | 544 | #endif |
| 522 | vma->vm_page_prot = __pgprot(prot); | 545 | vma->vm_page_prot = __pgprot(prot); |
| 523 | 546 | ||
| 547 | /* Take a ref for this mapping of the object, so that the fault | ||
| 548 | * handler can dereference the mmap offset's pointer to the object. | ||
| 549 | * This reference is cleaned up by the corresponding vm_close | ||
| 550 | * (which should happen whether the vma was created by this call, or | ||
| 551 | * by a vm_open due to mremap or partial unmap or whatever). | ||
| 552 | */ | ||
| 553 | drm_gem_object_reference(obj); | ||
| 554 | |||
| 524 | vma->vm_file = filp; /* Needed for drm_vm_open() */ | 555 | vma->vm_file = filp; /* Needed for drm_vm_open() */ |
| 525 | drm_vm_open_locked(vma); | 556 | drm_vm_open_locked(vma); |
| 526 | 557 | ||
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3795dbc0f50c..93e677a481f5 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get); | |||
| 435 | */ | 435 | */ |
| 436 | void drm_vblank_put(struct drm_device *dev, int crtc) | 436 | void drm_vblank_put(struct drm_device *dev, int crtc) |
| 437 | { | 437 | { |
| 438 | BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); | ||
| 439 | |||
| 438 | /* Last user schedules interrupt disable */ | 440 | /* Last user schedules interrupt disable */ |
| 439 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) | 441 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) |
| 440 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); | 442 | mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); |
| @@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |||
| 460 | * so that interrupts remain enabled in the interim. | 462 | * so that interrupts remain enabled in the interim. |
| 461 | */ | 463 | */ |
| 462 | if (!dev->vblank_inmodeset[crtc]) { | 464 | if (!dev->vblank_inmodeset[crtc]) { |
| 463 | dev->vblank_inmodeset[crtc] = 1; | 465 | dev->vblank_inmodeset[crtc] = 0x1; |
| 464 | drm_vblank_get(dev, crtc); | 466 | if (drm_vblank_get(dev, crtc) == 0) |
| 467 | dev->vblank_inmodeset[crtc] |= 0x2; | ||
| 465 | } | 468 | } |
| 466 | } | 469 | } |
| 467 | EXPORT_SYMBOL(drm_vblank_pre_modeset); | 470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
| @@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) | |||
| 473 | if (dev->vblank_inmodeset[crtc]) { | 476 | if (dev->vblank_inmodeset[crtc]) { |
| 474 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 477 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 475 | dev->vblank_disable_allowed = 1; | 478 | dev->vblank_disable_allowed = 1; |
| 476 | dev->vblank_inmodeset[crtc] = 0; | ||
| 477 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 479 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
| 478 | drm_vblank_put(dev, crtc); | 480 | |
| 481 | if (dev->vblank_inmodeset[crtc] & 0x2) | ||
| 482 | drm_vblank_put(dev, crtc); | ||
| 483 | |||
| 484 | dev->vblank_inmodeset[crtc] = 0; | ||
| 479 | } | 485 | } |
| 480 | } | 486 | } |
| 481 | EXPORT_SYMBOL(drm_vblank_post_modeset); | 487 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 46e7b28f0707..e2f70a516c34 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
| @@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 80 | __set_current_state(TASK_INTERRUPTIBLE); | 80 | __set_current_state(TASK_INTERRUPTIBLE); |
| 81 | if (!master->lock.hw_lock) { | 81 | if (!master->lock.hw_lock) { |
| 82 | /* Device has been unregistered */ | 82 | /* Device has been unregistered */ |
| 83 | send_sig(SIGTERM, current, 0); | ||
| 83 | ret = -EINTR; | 84 | ret = -EINTR; |
| 84 | break; | 85 | break; |
| 85 | } | 86 | } |
| @@ -93,7 +94,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 93 | /* Contention */ | 94 | /* Contention */ |
| 94 | schedule(); | 95 | schedule(); |
| 95 | if (signal_pending(current)) { | 96 | if (signal_pending(current)) { |
| 96 | ret = -ERESTARTSYS; | 97 | ret = -EINTR; |
| 97 | break; | 98 | break; |
| 98 | } | 99 | } |
| 99 | } | 100 | } |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 46bb923b097c..7c8b15b22bf2 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
| @@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref) | |||
| 146 | 146 | ||
| 147 | drm_ht_remove(&master->magiclist); | 147 | drm_ht_remove(&master->magiclist); |
| 148 | 148 | ||
| 149 | if (master->lock.hw_lock) { | ||
| 150 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
| 151 | dev->sigdata.lock = NULL; | ||
| 152 | master->lock.hw_lock = NULL; | ||
| 153 | master->lock.file_priv = NULL; | ||
| 154 | wake_up_interruptible(&master->lock.lock_queue); | ||
| 155 | } | ||
| 156 | |||
| 157 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); | 149 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); |
| 158 | } | 150 | } |
| 159 | 151 | ||
| @@ -176,7 +168,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, | |||
| 176 | file_priv->minor->master != file_priv->master) { | 168 | file_priv->minor->master != file_priv->master) { |
| 177 | mutex_lock(&dev->struct_mutex); | 169 | mutex_lock(&dev->struct_mutex); |
| 178 | file_priv->minor->master = drm_master_get(file_priv->master); | 170 | file_priv->minor->master = drm_master_get(file_priv->master); |
| 179 | mutex_lock(&dev->struct_mutex); | 171 | mutex_unlock(&dev->struct_mutex); |
| 180 | } | 172 | } |
| 181 | 173 | ||
| 182 | return 0; | 174 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 81f1cff56fd5..6d21b9e48b89 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -202,7 +202,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) | |||
| 202 | dev_priv->ring.map.flags = 0; | 202 | dev_priv->ring.map.flags = 0; |
| 203 | dev_priv->ring.map.mtrr = 0; | 203 | dev_priv->ring.map.mtrr = 0; |
| 204 | 204 | ||
| 205 | drm_core_ioremap(&dev_priv->ring.map, dev); | 205 | drm_core_ioremap_wc(&dev_priv->ring.map, dev); |
| 206 | 206 | ||
| 207 | if (dev_priv->ring.map.handle == NULL) { | 207 | if (dev_priv->ring.map.handle == NULL) { |
| 208 | i915_dma_cleanup(dev); | 208 | i915_dma_cleanup(dev); |
| @@ -811,7 +811,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
| 811 | dev_priv->hws_map.flags = 0; | 811 | dev_priv->hws_map.flags = 0; |
| 812 | dev_priv->hws_map.mtrr = 0; | 812 | dev_priv->hws_map.mtrr = 0; |
| 813 | 813 | ||
| 814 | drm_core_ioremap(&dev_priv->hws_map, dev); | 814 | drm_core_ioremap_wc(&dev_priv->hws_map, dev); |
| 815 | if (dev_priv->hws_map.handle == NULL) { | 815 | if (dev_priv->hws_map.handle == NULL) { |
| 816 | i915_dma_cleanup(dev); | 816 | i915_dma_cleanup(dev); |
| 817 | dev_priv->status_gfx_addr = 0; | 817 | dev_priv->status_gfx_addr = 0; |
| @@ -1090,6 +1090,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1090 | dev_priv->mm.gtt_mapping = | 1090 | dev_priv->mm.gtt_mapping = |
| 1091 | io_mapping_create_wc(dev->agp->base, | 1091 | io_mapping_create_wc(dev->agp->base, |
| 1092 | dev->agp->agp_info.aper_size * 1024*1024); | 1092 | dev->agp->agp_info.aper_size * 1024*1024); |
| 1093 | if (dev_priv->mm.gtt_mapping == NULL) { | ||
| 1094 | ret = -EIO; | ||
| 1095 | goto out_rmmap; | ||
| 1096 | } | ||
| 1097 | |||
| 1093 | /* Set up a WC MTRR for non-PAT systems. This is more common than | 1098 | /* Set up a WC MTRR for non-PAT systems. This is more common than |
| 1094 | * one would think, because the kernel disables PAT on first | 1099 | * one would think, because the kernel disables PAT on first |
| 1095 | * generation Core chips because WC PAT gets overridden by a UC | 1100 | * generation Core chips because WC PAT gets overridden by a UC |
| @@ -1100,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1100 | 1024 * 1024, | 1105 | 1024 * 1024, |
| 1101 | MTRR_TYPE_WRCOMB, 1); | 1106 | MTRR_TYPE_WRCOMB, 1); |
| 1102 | if (dev_priv->mm.gtt_mtrr < 0) { | 1107 | if (dev_priv->mm.gtt_mtrr < 0) { |
| 1103 | DRM_INFO("MTRR allocation failed\n. Graphics " | 1108 | DRM_INFO("MTRR allocation failed. Graphics " |
| 1104 | "performance may suffer.\n"); | 1109 | "performance may suffer.\n"); |
| 1105 | } | 1110 | } |
| 1106 | 1111 | ||
| @@ -1122,7 +1127,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1122 | if (!I915_NEED_GFX_HWS(dev)) { | 1127 | if (!I915_NEED_GFX_HWS(dev)) { |
| 1123 | ret = i915_init_phys_hws(dev); | 1128 | ret = i915_init_phys_hws(dev); |
| 1124 | if (ret != 0) | 1129 | if (ret != 0) |
| 1125 | goto out_rmmap; | 1130 | goto out_iomapfree; |
| 1126 | } | 1131 | } |
| 1127 | 1132 | ||
| 1128 | /* On the 945G/GM, the chipset reports the MSI capability on the | 1133 | /* On the 945G/GM, the chipset reports the MSI capability on the |
| @@ -1161,6 +1166,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1161 | 1166 | ||
| 1162 | return 0; | 1167 | return 0; |
| 1163 | 1168 | ||
| 1169 | out_iomapfree: | ||
| 1170 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
| 1164 | out_rmmap: | 1171 | out_rmmap: |
| 1165 | iounmap(dev_priv->regs); | 1172 | iounmap(dev_priv->regs); |
| 1166 | free_priv: | 1173 | free_priv: |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aac12ee31a46..b293ef0bae71 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | * | 27 | * |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/device.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" |
| @@ -66,6 +67,14 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 66 | 67 | ||
| 67 | i915_save_state(dev); | 68 | i915_save_state(dev); |
| 68 | 69 | ||
| 70 | /* If KMS is active, we do the leavevt stuff here */ | ||
| 71 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 72 | if (i915_gem_idle(dev)) | ||
| 73 | dev_err(&dev->pdev->dev, | ||
| 74 | "GEM idle failed, resume may fail\n"); | ||
| 75 | drm_irq_uninstall(dev); | ||
| 76 | } | ||
| 77 | |||
| 69 | intel_opregion_free(dev); | 78 | intel_opregion_free(dev); |
| 70 | 79 | ||
| 71 | if (state.event == PM_EVENT_SUSPEND) { | 80 | if (state.event == PM_EVENT_SUSPEND) { |
| @@ -79,6 +88,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 79 | 88 | ||
| 80 | static int i915_resume(struct drm_device *dev) | 89 | static int i915_resume(struct drm_device *dev) |
| 81 | { | 90 | { |
| 91 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 92 | int ret = 0; | ||
| 93 | |||
| 82 | pci_set_power_state(dev->pdev, PCI_D0); | 94 | pci_set_power_state(dev->pdev, PCI_D0); |
| 83 | pci_restore_state(dev->pdev); | 95 | pci_restore_state(dev->pdev); |
| 84 | if (pci_enable_device(dev->pdev)) | 96 | if (pci_enable_device(dev->pdev)) |
| @@ -89,11 +101,26 @@ static int i915_resume(struct drm_device *dev) | |||
| 89 | 101 | ||
| 90 | intel_opregion_init(dev); | 102 | intel_opregion_init(dev); |
| 91 | 103 | ||
| 92 | return 0; | 104 | /* KMS EnterVT equivalent */ |
| 105 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 106 | mutex_lock(&dev->struct_mutex); | ||
| 107 | dev_priv->mm.suspended = 0; | ||
| 108 | |||
| 109 | ret = i915_gem_init_ringbuffer(dev); | ||
| 110 | if (ret != 0) | ||
| 111 | ret = -1; | ||
| 112 | mutex_unlock(&dev->struct_mutex); | ||
| 113 | |||
| 114 | drm_irq_install(dev); | ||
| 115 | } | ||
| 116 | |||
| 117 | return ret; | ||
| 93 | } | 118 | } |
| 94 | 119 | ||
| 95 | static struct vm_operations_struct i915_gem_vm_ops = { | 120 | static struct vm_operations_struct i915_gem_vm_ops = { |
| 96 | .fault = i915_gem_fault, | 121 | .fault = i915_gem_fault, |
| 122 | .open = drm_gem_vm_open, | ||
| 123 | .close = drm_gem_vm_close, | ||
| 97 | }; | 124 | }; |
| 98 | 125 | ||
| 99 | static struct drm_driver driver = { | 126 | static struct drm_driver driver = { |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7325363164f8..d6cc9861e0a1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -184,6 +184,8 @@ typedef struct drm_i915_private { | |||
| 184 | unsigned int lvds_dither:1; | 184 | unsigned int lvds_dither:1; |
| 185 | unsigned int lvds_vbt:1; | 185 | unsigned int lvds_vbt:1; |
| 186 | unsigned int int_crt_support:1; | 186 | unsigned int int_crt_support:1; |
| 187 | unsigned int lvds_use_ssc:1; | ||
| 188 | int lvds_ssc_freq; | ||
| 187 | 189 | ||
| 188 | struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ | 190 | struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ |
| 189 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ | 191 | int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ |
| @@ -277,7 +279,6 @@ typedef struct drm_i915_private { | |||
| 277 | u8 saveAR_INDEX; | 279 | u8 saveAR_INDEX; |
| 278 | u8 saveAR[21]; | 280 | u8 saveAR[21]; |
| 279 | u8 saveDACMASK; | 281 | u8 saveDACMASK; |
| 280 | u8 saveDACDATA[256*3]; /* 256 3-byte colors */ | ||
| 281 | u8 saveCR[37]; | 282 | u8 saveCR[37]; |
| 282 | 283 | ||
| 283 | struct { | 284 | struct { |
| @@ -455,6 +456,12 @@ struct drm_i915_gem_object { | |||
| 455 | 456 | ||
| 456 | /** for phy allocated objects */ | 457 | /** for phy allocated objects */ |
| 457 | struct drm_i915_gem_phys_object *phys_obj; | 458 | struct drm_i915_gem_phys_object *phys_obj; |
| 459 | |||
| 460 | /** | ||
| 461 | * Used for checking the object doesn't appear more than once | ||
| 462 | * in an execbuffer object list. | ||
| 463 | */ | ||
| 464 | int in_execbuffer; | ||
| 458 | }; | 465 | }; |
| 459 | 466 | ||
| 460 | /** | 467 | /** |
| @@ -616,6 +623,7 @@ int i915_gem_init_ringbuffer(struct drm_device *dev); | |||
| 616 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 623 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
| 617 | int i915_gem_do_init(struct drm_device *dev, unsigned long start, | 624 | int i915_gem_do_init(struct drm_device *dev, unsigned long start, |
| 618 | unsigned long end); | 625 | unsigned long end); |
| 626 | int i915_gem_idle(struct drm_device *dev); | ||
| 619 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 627 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
| 620 | int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, | 628 | int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, |
| 621 | int write); | 629 | int write); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 818576654092..37427e4016cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -34,10 +34,6 @@ | |||
| 34 | 34 | ||
| 35 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) | 35 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) |
| 36 | 36 | ||
| 37 | static void | ||
| 38 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | ||
| 39 | uint32_t read_domains, | ||
| 40 | uint32_t write_domain); | ||
| 41 | static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); | 37 | static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); |
| 42 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 38 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
| 43 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 39 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
| @@ -607,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 607 | case -EAGAIN: | 603 | case -EAGAIN: |
| 608 | return VM_FAULT_OOM; | 604 | return VM_FAULT_OOM; |
| 609 | case -EFAULT: | 605 | case -EFAULT: |
| 610 | case -EBUSY: | ||
| 611 | DRM_ERROR("can't insert pfn?? fault or busy...\n"); | ||
| 612 | return VM_FAULT_SIGBUS; | 606 | return VM_FAULT_SIGBUS; |
| 613 | default: | 607 | default: |
| 614 | return VM_FAULT_NOPAGE; | 608 | return VM_FAULT_NOPAGE; |
| @@ -684,6 +678,30 @@ out_free_list: | |||
| 684 | return ret; | 678 | return ret; |
| 685 | } | 679 | } |
| 686 | 680 | ||
| 681 | static void | ||
| 682 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) | ||
| 683 | { | ||
| 684 | struct drm_device *dev = obj->dev; | ||
| 685 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
| 686 | struct drm_gem_mm *mm = dev->mm_private; | ||
| 687 | struct drm_map_list *list; | ||
| 688 | |||
| 689 | list = &obj->map_list; | ||
| 690 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
| 691 | |||
| 692 | if (list->file_offset_node) { | ||
| 693 | drm_mm_put_block(list->file_offset_node); | ||
| 694 | list->file_offset_node = NULL; | ||
| 695 | } | ||
| 696 | |||
| 697 | if (list->map) { | ||
| 698 | drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER); | ||
| 699 | list->map = NULL; | ||
| 700 | } | ||
| 701 | |||
| 702 | obj_priv->mmap_offset = 0; | ||
| 703 | } | ||
| 704 | |||
| 687 | /** | 705 | /** |
| 688 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object | 706 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object |
| 689 | * @obj: object to check | 707 | * @obj: object to check |
| @@ -758,8 +776,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
| 758 | 776 | ||
| 759 | if (!obj_priv->mmap_offset) { | 777 | if (!obj_priv->mmap_offset) { |
| 760 | ret = i915_gem_create_mmap_offset(obj); | 778 | ret = i915_gem_create_mmap_offset(obj); |
| 761 | if (ret) | 779 | if (ret) { |
| 780 | drm_gem_object_unreference(obj); | ||
| 781 | mutex_unlock(&dev->struct_mutex); | ||
| 762 | return ret; | 782 | return ret; |
| 783 | } | ||
| 763 | } | 784 | } |
| 764 | 785 | ||
| 765 | args->offset = obj_priv->mmap_offset; | 786 | args->offset = obj_priv->mmap_offset; |
| @@ -1030,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
| 1030 | drm_i915_private_t *dev_priv = dev->dev_private; | 1051 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 1031 | uint32_t seqno; | 1052 | uint32_t seqno; |
| 1032 | 1053 | ||
| 1054 | if (!dev_priv->hw_status_page) | ||
| 1055 | return; | ||
| 1056 | |||
| 1033 | seqno = i915_get_gem_seqno(dev); | 1057 | seqno = i915_get_gem_seqno(dev); |
| 1034 | 1058 | ||
| 1035 | while (!list_empty(&dev_priv->mm.request_list)) { | 1059 | while (!list_empty(&dev_priv->mm.request_list)) { |
| @@ -1452,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1452 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1476 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1453 | int regnum = obj_priv->fence_reg; | 1477 | int regnum = obj_priv->fence_reg; |
| 1454 | int tile_width; | 1478 | int tile_width; |
| 1455 | uint32_t val; | 1479 | uint32_t fence_reg, val; |
| 1456 | uint32_t pitch_val; | 1480 | uint32_t pitch_val; |
| 1457 | 1481 | ||
| 1458 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1482 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
| @@ -1479,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1479 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; | 1503 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; |
| 1480 | val |= I830_FENCE_REG_VALID; | 1504 | val |= I830_FENCE_REG_VALID; |
| 1481 | 1505 | ||
| 1482 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); | 1506 | if (regnum < 8) |
| 1507 | fence_reg = FENCE_REG_830_0 + (regnum * 4); | ||
| 1508 | else | ||
| 1509 | fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); | ||
| 1510 | I915_WRITE(fence_reg, val); | ||
| 1483 | } | 1511 | } |
| 1484 | 1512 | ||
| 1485 | static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | 1513 | static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) |
| @@ -1533,7 +1561,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) | |||
| 1533 | struct drm_i915_private *dev_priv = dev->dev_private; | 1561 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1534 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1562 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1535 | struct drm_i915_fence_reg *reg = NULL; | 1563 | struct drm_i915_fence_reg *reg = NULL; |
| 1536 | int i, ret; | 1564 | struct drm_i915_gem_object *old_obj_priv = NULL; |
| 1565 | int i, ret, avail; | ||
| 1537 | 1566 | ||
| 1538 | switch (obj_priv->tiling_mode) { | 1567 | switch (obj_priv->tiling_mode) { |
| 1539 | case I915_TILING_NONE: | 1568 | case I915_TILING_NONE: |
| @@ -1556,25 +1585,46 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) | |||
| 1556 | } | 1585 | } |
| 1557 | 1586 | ||
| 1558 | /* First try to find a free reg */ | 1587 | /* First try to find a free reg */ |
| 1588 | try_again: | ||
| 1589 | avail = 0; | ||
| 1559 | for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { | 1590 | for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { |
| 1560 | reg = &dev_priv->fence_regs[i]; | 1591 | reg = &dev_priv->fence_regs[i]; |
| 1561 | if (!reg->obj) | 1592 | if (!reg->obj) |
| 1562 | break; | 1593 | break; |
| 1594 | |||
| 1595 | old_obj_priv = reg->obj->driver_private; | ||
| 1596 | if (!old_obj_priv->pin_count) | ||
| 1597 | avail++; | ||
| 1563 | } | 1598 | } |
| 1564 | 1599 | ||
| 1565 | /* None available, try to steal one or wait for a user to finish */ | 1600 | /* None available, try to steal one or wait for a user to finish */ |
| 1566 | if (i == dev_priv->num_fence_regs) { | 1601 | if (i == dev_priv->num_fence_regs) { |
| 1567 | struct drm_i915_gem_object *old_obj_priv = NULL; | 1602 | uint32_t seqno = dev_priv->mm.next_gem_seqno; |
| 1568 | loff_t offset; | 1603 | loff_t offset; |
| 1569 | 1604 | ||
| 1570 | try_again: | 1605 | if (avail == 0) |
| 1571 | /* Could try to use LRU here instead... */ | 1606 | return -ENOMEM; |
| 1607 | |||
| 1572 | for (i = dev_priv->fence_reg_start; | 1608 | for (i = dev_priv->fence_reg_start; |
| 1573 | i < dev_priv->num_fence_regs; i++) { | 1609 | i < dev_priv->num_fence_regs; i++) { |
| 1610 | uint32_t this_seqno; | ||
| 1611 | |||
| 1574 | reg = &dev_priv->fence_regs[i]; | 1612 | reg = &dev_priv->fence_regs[i]; |
| 1575 | old_obj_priv = reg->obj->driver_private; | 1613 | old_obj_priv = reg->obj->driver_private; |
| 1576 | if (!old_obj_priv->pin_count) | 1614 | |
| 1615 | if (old_obj_priv->pin_count) | ||
| 1616 | continue; | ||
| 1617 | |||
| 1618 | /* i915 uses fences for GPU access to tiled buffers */ | ||
| 1619 | if (IS_I965G(dev) || !old_obj_priv->active) | ||
| 1577 | break; | 1620 | break; |
| 1621 | |||
| 1622 | /* find the seqno of the first available fence */ | ||
| 1623 | this_seqno = old_obj_priv->last_rendering_seqno; | ||
| 1624 | if (this_seqno != 0 && | ||
| 1625 | reg->obj->write_domain == 0 && | ||
| 1626 | i915_seqno_passed(seqno, this_seqno)) | ||
| 1627 | seqno = this_seqno; | ||
| 1578 | } | 1628 | } |
| 1579 | 1629 | ||
| 1580 | /* | 1630 | /* |
| @@ -1582,15 +1632,25 @@ try_again: | |||
| 1582 | * objects to finish before trying again. | 1632 | * objects to finish before trying again. |
| 1583 | */ | 1633 | */ |
| 1584 | if (i == dev_priv->num_fence_regs) { | 1634 | if (i == dev_priv->num_fence_regs) { |
| 1585 | ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); | 1635 | if (seqno == dev_priv->mm.next_gem_seqno) { |
| 1586 | if (ret) { | 1636 | i915_gem_flush(dev, |
| 1587 | WARN(ret != -ERESTARTSYS, | 1637 | I915_GEM_GPU_DOMAINS, |
| 1588 | "switch to GTT domain failed: %d\n", ret); | 1638 | I915_GEM_GPU_DOMAINS); |
| 1589 | return ret; | 1639 | seqno = i915_add_request(dev, |
| 1640 | I915_GEM_GPU_DOMAINS); | ||
| 1641 | if (seqno == 0) | ||
| 1642 | return -ENOMEM; | ||
| 1590 | } | 1643 | } |
| 1644 | |||
| 1645 | ret = i915_wait_request(dev, seqno); | ||
| 1646 | if (ret) | ||
| 1647 | return ret; | ||
| 1591 | goto try_again; | 1648 | goto try_again; |
| 1592 | } | 1649 | } |
| 1593 | 1650 | ||
| 1651 | BUG_ON(old_obj_priv->active || | ||
| 1652 | (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); | ||
| 1653 | |||
| 1594 | /* | 1654 | /* |
| 1595 | * Zap this virtual mapping so we can set up a fence again | 1655 | * Zap this virtual mapping so we can set up a fence again |
| 1596 | * for this object next time we need it. | 1656 | * for this object next time we need it. |
| @@ -1631,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) | |||
| 1631 | 1691 | ||
| 1632 | if (IS_I965G(dev)) | 1692 | if (IS_I965G(dev)) |
| 1633 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); | 1693 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); |
| 1634 | else | 1694 | else { |
| 1635 | I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); | 1695 | uint32_t fence_reg; |
| 1696 | |||
| 1697 | if (obj_priv->fence_reg < 8) | ||
| 1698 | fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; | ||
| 1699 | else | ||
| 1700 | fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - | ||
| 1701 | 8) * 4; | ||
| 1702 | |||
| 1703 | I915_WRITE(fence_reg, 0); | ||
| 1704 | } | ||
| 1636 | 1705 | ||
| 1637 | dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; | 1706 | dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; |
| 1638 | obj_priv->fence_reg = I915_FENCE_REG_NONE; | 1707 | obj_priv->fence_reg = I915_FENCE_REG_NONE; |
| @@ -1996,30 +2065,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
| 1996 | * drm_agp_chipset_flush | 2065 | * drm_agp_chipset_flush |
| 1997 | */ | 2066 | */ |
| 1998 | static void | 2067 | static void |
| 1999 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | 2068 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) |
| 2000 | uint32_t read_domains, | ||
| 2001 | uint32_t write_domain) | ||
| 2002 | { | 2069 | { |
| 2003 | struct drm_device *dev = obj->dev; | 2070 | struct drm_device *dev = obj->dev; |
| 2004 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2071 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 2005 | uint32_t invalidate_domains = 0; | 2072 | uint32_t invalidate_domains = 0; |
| 2006 | uint32_t flush_domains = 0; | 2073 | uint32_t flush_domains = 0; |
| 2007 | 2074 | ||
| 2008 | BUG_ON(read_domains & I915_GEM_DOMAIN_CPU); | 2075 | BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); |
| 2009 | BUG_ON(write_domain == I915_GEM_DOMAIN_CPU); | 2076 | BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); |
| 2010 | 2077 | ||
| 2011 | #if WATCH_BUF | 2078 | #if WATCH_BUF |
| 2012 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", | 2079 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", |
| 2013 | __func__, obj, | 2080 | __func__, obj, |
| 2014 | obj->read_domains, read_domains, | 2081 | obj->read_domains, obj->pending_read_domains, |
| 2015 | obj->write_domain, write_domain); | 2082 | obj->write_domain, obj->pending_write_domain); |
| 2016 | #endif | 2083 | #endif |
| 2017 | /* | 2084 | /* |
| 2018 | * If the object isn't moving to a new write domain, | 2085 | * If the object isn't moving to a new write domain, |
| 2019 | * let the object stay in multiple read domains | 2086 | * let the object stay in multiple read domains |
| 2020 | */ | 2087 | */ |
| 2021 | if (write_domain == 0) | 2088 | if (obj->pending_write_domain == 0) |
| 2022 | read_domains |= obj->read_domains; | 2089 | obj->pending_read_domains |= obj->read_domains; |
| 2023 | else | 2090 | else |
| 2024 | obj_priv->dirty = 1; | 2091 | obj_priv->dirty = 1; |
| 2025 | 2092 | ||
| @@ -2029,15 +2096,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
| 2029 | * any read domains which differ from the old | 2096 | * any read domains which differ from the old |
| 2030 | * write domain | 2097 | * write domain |
| 2031 | */ | 2098 | */ |
| 2032 | if (obj->write_domain && obj->write_domain != read_domains) { | 2099 | if (obj->write_domain && |
| 2100 | obj->write_domain != obj->pending_read_domains) { | ||
| 2033 | flush_domains |= obj->write_domain; | 2101 | flush_domains |= obj->write_domain; |
| 2034 | invalidate_domains |= read_domains & ~obj->write_domain; | 2102 | invalidate_domains |= |
| 2103 | obj->pending_read_domains & ~obj->write_domain; | ||
| 2035 | } | 2104 | } |
| 2036 | /* | 2105 | /* |
| 2037 | * Invalidate any read caches which may have | 2106 | * Invalidate any read caches which may have |
| 2038 | * stale data. That is, any new read domains. | 2107 | * stale data. That is, any new read domains. |
| 2039 | */ | 2108 | */ |
| 2040 | invalidate_domains |= read_domains & ~obj->read_domains; | 2109 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; |
| 2041 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { | 2110 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { |
| 2042 | #if WATCH_BUF | 2111 | #if WATCH_BUF |
| 2043 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", | 2112 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", |
| @@ -2046,9 +2115,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
| 2046 | i915_gem_clflush_object(obj); | 2115 | i915_gem_clflush_object(obj); |
| 2047 | } | 2116 | } |
| 2048 | 2117 | ||
| 2049 | if ((write_domain | flush_domains) != 0) | 2118 | /* The actual obj->write_domain will be updated with |
| 2050 | obj->write_domain = write_domain; | 2119 | * pending_write_domain after we emit the accumulated flush for all |
| 2051 | obj->read_domains = read_domains; | 2120 | * of our domain changes in execbuffers (which clears objects' |
| 2121 | * write_domains). So if we have a current write domain that we | ||
| 2122 | * aren't changing, set pending_write_domain to that. | ||
| 2123 | */ | ||
| 2124 | if (flush_domains == 0 && obj->pending_write_domain == 0) | ||
| 2125 | obj->pending_write_domain = obj->write_domain; | ||
| 2126 | obj->read_domains = obj->pending_read_domains; | ||
| 2052 | 2127 | ||
| 2053 | dev->invalidate_domains |= invalidate_domains; | 2128 | dev->invalidate_domains |= invalidate_domains; |
| 2054 | dev->flush_domains |= flush_domains; | 2129 | dev->flush_domains |= flush_domains; |
| @@ -2251,6 +2326,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
| 2251 | (int) reloc.offset, | 2326 | (int) reloc.offset, |
| 2252 | reloc.read_domains, | 2327 | reloc.read_domains, |
| 2253 | reloc.write_domain); | 2328 | reloc.write_domain); |
| 2329 | drm_gem_object_unreference(target_obj); | ||
| 2330 | i915_gem_object_unpin(obj); | ||
| 2254 | return -EINVAL; | 2331 | return -EINVAL; |
| 2255 | } | 2332 | } |
| 2256 | 2333 | ||
| @@ -2437,6 +2514,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2437 | struct drm_i915_gem_exec_object *exec_list = NULL; | 2514 | struct drm_i915_gem_exec_object *exec_list = NULL; |
| 2438 | struct drm_gem_object **object_list = NULL; | 2515 | struct drm_gem_object **object_list = NULL; |
| 2439 | struct drm_gem_object *batch_obj; | 2516 | struct drm_gem_object *batch_obj; |
| 2517 | struct drm_i915_gem_object *obj_priv; | ||
| 2440 | int ret, i, pinned = 0; | 2518 | int ret, i, pinned = 0; |
| 2441 | uint64_t exec_offset; | 2519 | uint64_t exec_offset; |
| 2442 | uint32_t seqno, flush_domains; | 2520 | uint32_t seqno, flush_domains; |
| @@ -2480,13 +2558,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2480 | if (dev_priv->mm.wedged) { | 2558 | if (dev_priv->mm.wedged) { |
| 2481 | DRM_ERROR("Execbuf while wedged\n"); | 2559 | DRM_ERROR("Execbuf while wedged\n"); |
| 2482 | mutex_unlock(&dev->struct_mutex); | 2560 | mutex_unlock(&dev->struct_mutex); |
| 2483 | return -EIO; | 2561 | ret = -EIO; |
| 2562 | goto pre_mutex_err; | ||
| 2484 | } | 2563 | } |
| 2485 | 2564 | ||
| 2486 | if (dev_priv->mm.suspended) { | 2565 | if (dev_priv->mm.suspended) { |
| 2487 | DRM_ERROR("Execbuf while VT-switched.\n"); | 2566 | DRM_ERROR("Execbuf while VT-switched.\n"); |
| 2488 | mutex_unlock(&dev->struct_mutex); | 2567 | mutex_unlock(&dev->struct_mutex); |
| 2489 | return -EBUSY; | 2568 | ret = -EBUSY; |
| 2569 | goto pre_mutex_err; | ||
| 2490 | } | 2570 | } |
| 2491 | 2571 | ||
| 2492 | /* Look up object handles */ | 2572 | /* Look up object handles */ |
| @@ -2499,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2499 | ret = -EBADF; | 2579 | ret = -EBADF; |
| 2500 | goto err; | 2580 | goto err; |
| 2501 | } | 2581 | } |
| 2582 | |||
| 2583 | obj_priv = object_list[i]->driver_private; | ||
| 2584 | if (obj_priv->in_execbuffer) { | ||
| 2585 | DRM_ERROR("Object %p appears more than once in object list\n", | ||
| 2586 | object_list[i]); | ||
| 2587 | ret = -EBADF; | ||
| 2588 | goto err; | ||
| 2589 | } | ||
| 2590 | obj_priv->in_execbuffer = true; | ||
| 2502 | } | 2591 | } |
| 2503 | 2592 | ||
| 2504 | /* Pin and relocate */ | 2593 | /* Pin and relocate */ |
| @@ -2554,9 +2643,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2554 | struct drm_gem_object *obj = object_list[i]; | 2643 | struct drm_gem_object *obj = object_list[i]; |
| 2555 | 2644 | ||
| 2556 | /* Compute new gpu domains and update invalidate/flush */ | 2645 | /* Compute new gpu domains and update invalidate/flush */ |
| 2557 | i915_gem_object_set_to_gpu_domain(obj, | 2646 | i915_gem_object_set_to_gpu_domain(obj); |
| 2558 | obj->pending_read_domains, | ||
| 2559 | obj->pending_write_domain); | ||
| 2560 | } | 2647 | } |
| 2561 | 2648 | ||
| 2562 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2649 | i915_verify_inactive(dev, __FILE__, __LINE__); |
| @@ -2575,6 +2662,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2575 | (void)i915_add_request(dev, dev->flush_domains); | 2662 | (void)i915_add_request(dev, dev->flush_domains); |
| 2576 | } | 2663 | } |
| 2577 | 2664 | ||
| 2665 | for (i = 0; i < args->buffer_count; i++) { | ||
| 2666 | struct drm_gem_object *obj = object_list[i]; | ||
| 2667 | |||
| 2668 | obj->write_domain = obj->pending_write_domain; | ||
| 2669 | } | ||
| 2670 | |||
| 2578 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2671 | i915_verify_inactive(dev, __FILE__, __LINE__); |
| 2579 | 2672 | ||
| 2580 | #if WATCH_COHERENCY | 2673 | #if WATCH_COHERENCY |
| @@ -2632,24 +2725,32 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2632 | 2725 | ||
| 2633 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2726 | i915_verify_inactive(dev, __FILE__, __LINE__); |
| 2634 | 2727 | ||
| 2635 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
| 2636 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
| 2637 | (uintptr_t) args->buffers_ptr, | ||
| 2638 | exec_list, | ||
| 2639 | sizeof(*exec_list) * args->buffer_count); | ||
| 2640 | if (ret) | ||
| 2641 | DRM_ERROR("failed to copy %d exec entries " | ||
| 2642 | "back to user (%d)\n", | ||
| 2643 | args->buffer_count, ret); | ||
| 2644 | err: | 2728 | err: |
| 2645 | for (i = 0; i < pinned; i++) | 2729 | for (i = 0; i < pinned; i++) |
| 2646 | i915_gem_object_unpin(object_list[i]); | 2730 | i915_gem_object_unpin(object_list[i]); |
| 2647 | 2731 | ||
| 2648 | for (i = 0; i < args->buffer_count; i++) | 2732 | for (i = 0; i < args->buffer_count; i++) { |
| 2733 | if (object_list[i]) { | ||
| 2734 | obj_priv = object_list[i]->driver_private; | ||
| 2735 | obj_priv->in_execbuffer = false; | ||
| 2736 | } | ||
| 2649 | drm_gem_object_unreference(object_list[i]); | 2737 | drm_gem_object_unreference(object_list[i]); |
| 2738 | } | ||
| 2650 | 2739 | ||
| 2651 | mutex_unlock(&dev->struct_mutex); | 2740 | mutex_unlock(&dev->struct_mutex); |
| 2652 | 2741 | ||
| 2742 | if (!ret) { | ||
| 2743 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
| 2744 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
| 2745 | (uintptr_t) args->buffers_ptr, | ||
| 2746 | exec_list, | ||
| 2747 | sizeof(*exec_list) * args->buffer_count); | ||
| 2748 | if (ret) | ||
| 2749 | DRM_ERROR("failed to copy %d exec entries " | ||
| 2750 | "back to user (%d)\n", | ||
| 2751 | args->buffer_count, ret); | ||
| 2752 | } | ||
| 2753 | |||
| 2653 | pre_mutex_err: | 2754 | pre_mutex_err: |
| 2654 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, | 2755 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, |
| 2655 | DRM_MEM_DRIVER); | 2756 | DRM_MEM_DRIVER); |
| @@ -2671,17 +2772,24 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
| 2671 | ret = i915_gem_object_bind_to_gtt(obj, alignment); | 2772 | ret = i915_gem_object_bind_to_gtt(obj, alignment); |
| 2672 | if (ret != 0) { | 2773 | if (ret != 0) { |
| 2673 | if (ret != -EBUSY && ret != -ERESTARTSYS) | 2774 | if (ret != -EBUSY && ret != -ERESTARTSYS) |
| 2674 | DRM_ERROR("Failure to bind: %d", ret); | 2775 | DRM_ERROR("Failure to bind: %d\n", ret); |
| 2776 | return ret; | ||
| 2777 | } | ||
| 2778 | } | ||
| 2779 | /* | ||
| 2780 | * Pre-965 chips need a fence register set up in order to | ||
| 2781 | * properly handle tiled surfaces. | ||
| 2782 | */ | ||
| 2783 | if (!IS_I965G(dev) && | ||
| 2784 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
| 2785 | obj_priv->tiling_mode != I915_TILING_NONE) { | ||
| 2786 | ret = i915_gem_object_get_fence_reg(obj, true); | ||
| 2787 | if (ret != 0) { | ||
| 2788 | if (ret != -EBUSY && ret != -ERESTARTSYS) | ||
| 2789 | DRM_ERROR("Failure to install fence: %d\n", | ||
| 2790 | ret); | ||
| 2675 | return ret; | 2791 | return ret; |
| 2676 | } | 2792 | } |
| 2677 | /* | ||
| 2678 | * Pre-965 chips need a fence register set up in order to | ||
| 2679 | * properly handle tiled surfaces. | ||
| 2680 | */ | ||
| 2681 | if (!IS_I965G(dev) && | ||
| 2682 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
| 2683 | obj_priv->tiling_mode != I915_TILING_NONE) | ||
| 2684 | i915_gem_object_get_fence_reg(obj, true); | ||
| 2685 | } | 2793 | } |
| 2686 | obj_priv->pin_count++; | 2794 | obj_priv->pin_count++; |
| 2687 | 2795 | ||
| @@ -2753,6 +2861,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
| 2753 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { | 2861 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { |
| 2754 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", | 2862 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", |
| 2755 | args->handle); | 2863 | args->handle); |
| 2864 | drm_gem_object_unreference(obj); | ||
| 2756 | mutex_unlock(&dev->struct_mutex); | 2865 | mutex_unlock(&dev->struct_mutex); |
| 2757 | return -EINVAL; | 2866 | return -EINVAL; |
| 2758 | } | 2867 | } |
| @@ -2833,6 +2942,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
| 2833 | return -EBADF; | 2942 | return -EBADF; |
| 2834 | } | 2943 | } |
| 2835 | 2944 | ||
| 2945 | /* Update the active list for the hardware's current position. | ||
| 2946 | * Otherwise this only updates on a delayed timer or when irqs are | ||
| 2947 | * actually unmasked, and our working set ends up being larger than | ||
| 2948 | * required. | ||
| 2949 | */ | ||
| 2950 | i915_gem_retire_requests(dev); | ||
| 2951 | |||
| 2836 | obj_priv = obj->driver_private; | 2952 | obj_priv = obj->driver_private; |
| 2837 | /* Don't count being on the flushing list against the object being | 2953 | /* Don't count being on the flushing list against the object being |
| 2838 | * done. Otherwise, a buffer left on the flushing list but not getting | 2954 | * done. Otherwise, a buffer left on the flushing list but not getting |
| @@ -2885,9 +3001,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) | |||
| 2885 | void i915_gem_free_object(struct drm_gem_object *obj) | 3001 | void i915_gem_free_object(struct drm_gem_object *obj) |
| 2886 | { | 3002 | { |
| 2887 | struct drm_device *dev = obj->dev; | 3003 | struct drm_device *dev = obj->dev; |
| 2888 | struct drm_gem_mm *mm = dev->mm_private; | ||
| 2889 | struct drm_map_list *list; | ||
| 2890 | struct drm_map *map; | ||
| 2891 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 3004 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 2892 | 3005 | ||
| 2893 | while (obj_priv->pin_count > 0) | 3006 | while (obj_priv->pin_count > 0) |
| @@ -2898,19 +3011,7 @@ void i915_gem_free_object(struct drm_gem_object *obj) | |||
| 2898 | 3011 | ||
| 2899 | i915_gem_object_unbind(obj); | 3012 | i915_gem_object_unbind(obj); |
| 2900 | 3013 | ||
| 2901 | list = &obj->map_list; | 3014 | i915_gem_free_mmap_offset(obj); |
| 2902 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
| 2903 | |||
| 2904 | if (list->file_offset_node) { | ||
| 2905 | drm_mm_put_block(list->file_offset_node); | ||
| 2906 | list->file_offset_node = NULL; | ||
| 2907 | } | ||
| 2908 | |||
| 2909 | map = list->map; | ||
| 2910 | if (map) { | ||
| 2911 | drm_free(map, sizeof(*map), DRM_MEM_DRIVER); | ||
| 2912 | list->map = NULL; | ||
| 2913 | } | ||
| 2914 | 3015 | ||
| 2915 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); | 3016 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); |
| 2916 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); | 3017 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); |
| @@ -2949,7 +3050,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head) | |||
| 2949 | return 0; | 3050 | return 0; |
| 2950 | } | 3051 | } |
| 2951 | 3052 | ||
| 2952 | static int | 3053 | int |
| 2953 | i915_gem_idle(struct drm_device *dev) | 3054 | i915_gem_idle(struct drm_device *dev) |
| 2954 | { | 3055 | { |
| 2955 | drm_i915_private_t *dev_priv = dev->dev_private; | 3056 | drm_i915_private_t *dev_priv = dev->dev_private; |
| @@ -3095,6 +3196,7 @@ i915_gem_init_hws(struct drm_device *dev) | |||
| 3095 | if (dev_priv->hw_status_page == NULL) { | 3196 | if (dev_priv->hw_status_page == NULL) { |
| 3096 | DRM_ERROR("Failed to map status page.\n"); | 3197 | DRM_ERROR("Failed to map status page.\n"); |
| 3097 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | 3198 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); |
| 3199 | i915_gem_object_unpin(obj); | ||
| 3098 | drm_gem_object_unreference(obj); | 3200 | drm_gem_object_unreference(obj); |
| 3099 | return -EINVAL; | 3201 | return -EINVAL; |
| 3100 | } | 3202 | } |
| @@ -3107,6 +3209,31 @@ i915_gem_init_hws(struct drm_device *dev) | |||
| 3107 | return 0; | 3209 | return 0; |
| 3108 | } | 3210 | } |
| 3109 | 3211 | ||
| 3212 | static void | ||
| 3213 | i915_gem_cleanup_hws(struct drm_device *dev) | ||
| 3214 | { | ||
| 3215 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 3216 | struct drm_gem_object *obj; | ||
| 3217 | struct drm_i915_gem_object *obj_priv; | ||
| 3218 | |||
| 3219 | if (dev_priv->hws_obj == NULL) | ||
| 3220 | return; | ||
| 3221 | |||
| 3222 | obj = dev_priv->hws_obj; | ||
| 3223 | obj_priv = obj->driver_private; | ||
| 3224 | |||
| 3225 | kunmap(obj_priv->page_list[0]); | ||
| 3226 | i915_gem_object_unpin(obj); | ||
| 3227 | drm_gem_object_unreference(obj); | ||
| 3228 | dev_priv->hws_obj = NULL; | ||
| 3229 | |||
| 3230 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | ||
| 3231 | dev_priv->hw_status_page = NULL; | ||
| 3232 | |||
| 3233 | /* Write high address into HWS_PGA when disabling. */ | ||
| 3234 | I915_WRITE(HWS_PGA, 0x1ffff000); | ||
| 3235 | } | ||
| 3236 | |||
| 3110 | int | 3237 | int |
| 3111 | i915_gem_init_ringbuffer(struct drm_device *dev) | 3238 | i915_gem_init_ringbuffer(struct drm_device *dev) |
| 3112 | { | 3239 | { |
| @@ -3124,6 +3251,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
| 3124 | obj = drm_gem_object_alloc(dev, 128 * 1024); | 3251 | obj = drm_gem_object_alloc(dev, 128 * 1024); |
| 3125 | if (obj == NULL) { | 3252 | if (obj == NULL) { |
| 3126 | DRM_ERROR("Failed to allocate ringbuffer\n"); | 3253 | DRM_ERROR("Failed to allocate ringbuffer\n"); |
| 3254 | i915_gem_cleanup_hws(dev); | ||
| 3127 | return -ENOMEM; | 3255 | return -ENOMEM; |
| 3128 | } | 3256 | } |
| 3129 | obj_priv = obj->driver_private; | 3257 | obj_priv = obj->driver_private; |
| @@ -3131,6 +3259,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
| 3131 | ret = i915_gem_object_pin(obj, 4096); | 3259 | ret = i915_gem_object_pin(obj, 4096); |
| 3132 | if (ret != 0) { | 3260 | if (ret != 0) { |
| 3133 | drm_gem_object_unreference(obj); | 3261 | drm_gem_object_unreference(obj); |
| 3262 | i915_gem_cleanup_hws(dev); | ||
| 3134 | return ret; | 3263 | return ret; |
| 3135 | } | 3264 | } |
| 3136 | 3265 | ||
| @@ -3148,7 +3277,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
| 3148 | if (ring->map.handle == NULL) { | 3277 | if (ring->map.handle == NULL) { |
| 3149 | DRM_ERROR("Failed to map ringbuffer.\n"); | 3278 | DRM_ERROR("Failed to map ringbuffer.\n"); |
| 3150 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); | 3279 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); |
| 3280 | i915_gem_object_unpin(obj); | ||
| 3151 | drm_gem_object_unreference(obj); | 3281 | drm_gem_object_unreference(obj); |
| 3282 | i915_gem_cleanup_hws(dev); | ||
| 3152 | return -EINVAL; | 3283 | return -EINVAL; |
| 3153 | } | 3284 | } |
| 3154 | ring->ring_obj = obj; | 3285 | ring->ring_obj = obj; |
| @@ -3228,20 +3359,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) | |||
| 3228 | dev_priv->ring.ring_obj = NULL; | 3359 | dev_priv->ring.ring_obj = NULL; |
| 3229 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); | 3360 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); |
| 3230 | 3361 | ||
| 3231 | if (dev_priv->hws_obj != NULL) { | 3362 | i915_gem_cleanup_hws(dev); |
| 3232 | struct drm_gem_object *obj = dev_priv->hws_obj; | ||
| 3233 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
| 3234 | |||
| 3235 | kunmap(obj_priv->page_list[0]); | ||
| 3236 | i915_gem_object_unpin(obj); | ||
| 3237 | drm_gem_object_unreference(obj); | ||
| 3238 | dev_priv->hws_obj = NULL; | ||
| 3239 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | ||
| 3240 | dev_priv->hw_status_page = NULL; | ||
| 3241 | |||
| 3242 | /* Write high address into HWS_PGA when disabling. */ | ||
| 3243 | I915_WRITE(HWS_PGA, 0x1ffff000); | ||
| 3244 | } | ||
| 3245 | } | 3363 | } |
| 3246 | 3364 | ||
| 3247 | int | 3365 | int |
| @@ -3497,7 +3615,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 3497 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 3615 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
| 3498 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; | 3616 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; |
| 3499 | 3617 | ||
| 3500 | DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); | 3618 | DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); |
| 3501 | ret = copy_from_user(obj_addr, user_data, args->size); | 3619 | ret = copy_from_user(obj_addr, user_data, args->size); |
| 3502 | if (ret) | 3620 | if (ret) |
| 3503 | return -EFAULT; | 3621 | return -EFAULT; |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index fa1685cba840..7fb4191ef934 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
| 299 | } | 299 | } |
| 300 | obj_priv->stride = args->stride; | 300 | obj_priv->stride = args->stride; |
| 301 | 301 | ||
| 302 | mutex_unlock(&dev->struct_mutex); | ||
| 303 | |||
| 304 | drm_gem_object_unreference(obj); | 302 | drm_gem_object_unreference(obj); |
| 303 | mutex_unlock(&dev->struct_mutex); | ||
| 305 | 304 | ||
| 306 | return 0; | 305 | return 0; |
| 307 | } | 306 | } |
| @@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
| 340 | DRM_ERROR("unknown tiling mode\n"); | 339 | DRM_ERROR("unknown tiling mode\n"); |
| 341 | } | 340 | } |
| 342 | 341 | ||
| 343 | mutex_unlock(&dev->struct_mutex); | ||
| 344 | |||
| 345 | drm_gem_object_unreference(obj); | 342 | drm_gem_object_unreference(obj); |
| 343 | mutex_unlock(&dev->struct_mutex); | ||
| 346 | 344 | ||
| 347 | return 0; | 345 | return 0; |
| 348 | } | 346 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 548ff2c66431..87b6b603469e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -383,12 +383,13 @@ int i915_irq_emit(struct drm_device *dev, void *data, | |||
| 383 | drm_i915_irq_emit_t *emit = data; | 383 | drm_i915_irq_emit_t *emit = data; |
| 384 | int result; | 384 | int result; |
| 385 | 385 | ||
| 386 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 387 | |||
| 388 | if (!dev_priv) { | 386 | if (!dev_priv) { |
| 389 | DRM_ERROR("called with no initialization\n"); | 387 | DRM_ERROR("called with no initialization\n"); |
| 390 | return -EINVAL; | 388 | return -EINVAL; |
| 391 | } | 389 | } |
| 390 | |||
| 391 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 392 | |||
| 392 | mutex_lock(&dev->struct_mutex); | 393 | mutex_lock(&dev->struct_mutex); |
| 393 | result = i915_emit_irq(dev); | 394 | result = i915_emit_irq(dev); |
| 394 | mutex_unlock(&dev->struct_mutex); | 395 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d6539a868b3..90600d899413 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -184,6 +184,7 @@ | |||
| 184 | * Fence registers | 184 | * Fence registers |
| 185 | */ | 185 | */ |
| 186 | #define FENCE_REG_830_0 0x2000 | 186 | #define FENCE_REG_830_0 0x2000 |
| 187 | #define FENCE_REG_945_8 0x3000 | ||
| 187 | #define I830_FENCE_START_MASK 0x07f80000 | 188 | #define I830_FENCE_START_MASK 0x07f80000 |
| 188 | #define I830_FENCE_TILING_Y_SHIFT 12 | 189 | #define I830_FENCE_TILING_Y_SHIFT 12 |
| 189 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) | 190 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5d84027ee8f3..d669cc2b42c0 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev) | |||
| 119 | 119 | ||
| 120 | /* VGA color palette registers */ | 120 | /* VGA color palette registers */ |
| 121 | dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); | 121 | dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); |
| 122 | /* DACCRX automatically increments during read */ | ||
| 123 | I915_WRITE8(VGA_DACRX, 0); | ||
| 124 | /* Read 3 bytes of color data from each index */ | ||
| 125 | for (i = 0; i < 256 * 3; i++) | ||
| 126 | dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA); | ||
| 127 | 122 | ||
| 128 | /* MSR bits */ | 123 | /* MSR bits */ |
| 129 | dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); | 124 | dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); |
| @@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev) | |||
| 225 | 220 | ||
| 226 | /* VGA color palette registers */ | 221 | /* VGA color palette registers */ |
| 227 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); | 222 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); |
| 228 | /* DACCRX automatically increments during read */ | ||
| 229 | I915_WRITE8(VGA_DACWX, 0); | ||
| 230 | /* Read 3 bytes of color data from each index */ | ||
| 231 | for (i = 0; i < 256 * 3; i++) | ||
| 232 | I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]); | ||
| 233 | |||
| 234 | } | 223 | } |
| 235 | 224 | ||
| 236 | int i915_save_state(struct drm_device *dev) | 225 | int i915_save_state(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4ca82a025525..fc28e2bbd542 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -111,6 +111,12 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
| 111 | panel_fixed_mode->clock = dvo_timing->clock * 10; | 111 | panel_fixed_mode->clock = dvo_timing->clock * 10; |
| 112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | 112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; |
| 113 | 113 | ||
| 114 | /* Some VBTs have bogus h/vtotal values */ | ||
| 115 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
| 116 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
| 117 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
| 118 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
| 119 | |||
| 114 | drm_mode_set_name(panel_fixed_mode); | 120 | drm_mode_set_name(panel_fixed_mode); |
| 115 | 121 | ||
| 116 | dev_priv->vbt_mode = panel_fixed_mode; | 122 | dev_priv->vbt_mode = panel_fixed_mode; |
| @@ -135,6 +141,14 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
| 135 | if (general) { | 141 | if (general) { |
| 136 | dev_priv->int_tv_support = general->int_tv_support; | 142 | dev_priv->int_tv_support = general->int_tv_support; |
| 137 | dev_priv->int_crt_support = general->int_crt_support; | 143 | dev_priv->int_crt_support = general->int_crt_support; |
| 144 | dev_priv->lvds_use_ssc = general->enable_ssc; | ||
| 145 | |||
| 146 | if (dev_priv->lvds_use_ssc) { | ||
| 147 | if (IS_I855(dev_priv->dev)) | ||
| 148 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48; | ||
| 149 | else | ||
| 150 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96; | ||
| 151 | } | ||
| 138 | } | 152 | } |
| 139 | } | 153 | } |
| 140 | 154 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bbdd72909a11..a2834276cb38 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -90,12 +90,12 @@ typedef struct { | |||
| 90 | #define I9XX_DOT_MAX 400000 | 90 | #define I9XX_DOT_MAX 400000 |
| 91 | #define I9XX_VCO_MIN 1400000 | 91 | #define I9XX_VCO_MIN 1400000 |
| 92 | #define I9XX_VCO_MAX 2800000 | 92 | #define I9XX_VCO_MAX 2800000 |
| 93 | #define I9XX_N_MIN 3 | 93 | #define I9XX_N_MIN 1 |
| 94 | #define I9XX_N_MAX 8 | 94 | #define I9XX_N_MAX 6 |
| 95 | #define I9XX_M_MIN 70 | 95 | #define I9XX_M_MIN 70 |
| 96 | #define I9XX_M_MAX 120 | 96 | #define I9XX_M_MAX 120 |
| 97 | #define I9XX_M1_MIN 10 | 97 | #define I9XX_M1_MIN 10 |
| 98 | #define I9XX_M1_MAX 20 | 98 | #define I9XX_M1_MAX 22 |
| 99 | #define I9XX_M2_MIN 5 | 99 | #define I9XX_M2_MIN 5 |
| 100 | #define I9XX_M2_MAX 9 | 100 | #define I9XX_M2_MAX 9 |
| 101 | #define I9XX_P_SDVO_DAC_MIN 5 | 101 | #define I9XX_P_SDVO_DAC_MIN 5 |
| @@ -189,9 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
| 189 | return limit; | 189 | return limit; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ | 192 | static void intel_clock(int refclk, intel_clock_t *clock) |
| 193 | |||
| 194 | static void i8xx_clock(int refclk, intel_clock_t *clock) | ||
| 195 | { | 193 | { |
| 196 | clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); | 194 | clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); |
| 197 | clock->p = clock->p1 * clock->p2; | 195 | clock->p = clock->p1 * clock->p2; |
| @@ -199,25 +197,6 @@ static void i8xx_clock(int refclk, intel_clock_t *clock) | |||
| 199 | clock->dot = clock->vco / clock->p; | 197 | clock->dot = clock->vco / clock->p; |
| 200 | } | 198 | } |
| 201 | 199 | ||
| 202 | /** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ | ||
| 203 | |||
| 204 | static void i9xx_clock(int refclk, intel_clock_t *clock) | ||
| 205 | { | ||
| 206 | clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); | ||
| 207 | clock->p = clock->p1 * clock->p2; | ||
| 208 | clock->vco = refclk * clock->m / (clock->n + 2); | ||
| 209 | clock->dot = clock->vco / clock->p; | ||
| 210 | } | ||
| 211 | |||
| 212 | static void intel_clock(struct drm_device *dev, int refclk, | ||
| 213 | intel_clock_t *clock) | ||
| 214 | { | ||
| 215 | if (IS_I9XX(dev)) | ||
| 216 | i9xx_clock (refclk, clock); | ||
| 217 | else | ||
| 218 | i8xx_clock (refclk, clock); | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | 200 | /** |
| 222 | * Returns whether any output on the specified pipe is of the specified type | 201 | * Returns whether any output on the specified pipe is of the specified type |
| 223 | */ | 202 | */ |
| @@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) | |||
| 238 | return false; | 217 | return false; |
| 239 | } | 218 | } |
| 240 | 219 | ||
| 241 | #define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } | 220 | #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) |
| 242 | /** | 221 | /** |
| 243 | * Returns whether the given set of divisors are valid for a given refclk with | 222 | * Returns whether the given set of divisors are valid for a given refclk with |
| 244 | * the given connectors. | 223 | * the given connectors. |
| @@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, | |||
| 318 | clock.p1 <= limit->p1.max; clock.p1++) { | 297 | clock.p1 <= limit->p1.max; clock.p1++) { |
| 319 | int this_err; | 298 | int this_err; |
| 320 | 299 | ||
| 321 | intel_clock(dev, refclk, &clock); | 300 | intel_clock(refclk, &clock); |
| 322 | 301 | ||
| 323 | if (!intel_PLL_is_valid(crtc, &clock)) | 302 | if (!intel_PLL_is_valid(crtc, &clock)) |
| 324 | continue; | 303 | continue; |
| @@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev) | |||
| 343 | udelay(20000); | 322 | udelay(20000); |
| 344 | } | 323 | } |
| 345 | 324 | ||
| 346 | static void | 325 | static int |
| 347 | intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | 326 | intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, |
| 348 | struct drm_framebuffer *old_fb) | 327 | struct drm_framebuffer *old_fb) |
| 349 | { | 328 | { |
| @@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 361 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | 340 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; |
| 362 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | 341 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; |
| 363 | u32 dspcntr, alignment; | 342 | u32 dspcntr, alignment; |
| 343 | int ret; | ||
| 364 | 344 | ||
| 365 | /* no fb bound */ | 345 | /* no fb bound */ |
| 366 | if (!crtc->fb) { | 346 | if (!crtc->fb) { |
| 367 | DRM_DEBUG("No FB bound\n"); | 347 | DRM_DEBUG("No FB bound\n"); |
| 368 | return; | 348 | return 0; |
| 349 | } | ||
| 350 | |||
| 351 | switch (pipe) { | ||
| 352 | case 0: | ||
| 353 | case 1: | ||
| 354 | break; | ||
| 355 | default: | ||
| 356 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | ||
| 357 | return -EINVAL; | ||
| 369 | } | 358 | } |
| 370 | 359 | ||
| 371 | intel_fb = to_intel_framebuffer(crtc->fb); | 360 | intel_fb = to_intel_framebuffer(crtc->fb); |
| @@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 377 | alignment = 64 * 1024; | 366 | alignment = 64 * 1024; |
| 378 | break; | 367 | break; |
| 379 | case I915_TILING_X: | 368 | case I915_TILING_X: |
| 380 | if (IS_I9XX(dev)) | 369 | /* pin() will align the object as required by fence */ |
| 381 | alignment = 1024 * 1024; | 370 | alignment = 0; |
| 382 | else | ||
| 383 | alignment = 512 * 1024; | ||
| 384 | break; | 371 | break; |
| 385 | case I915_TILING_Y: | 372 | case I915_TILING_Y: |
| 386 | /* FIXME: Is this true? */ | 373 | /* FIXME: Is this true? */ |
| 387 | DRM_ERROR("Y tiled not allowed for scan out buffers\n"); | 374 | DRM_ERROR("Y tiled not allowed for scan out buffers\n"); |
| 388 | return; | 375 | return -EINVAL; |
| 389 | default: | 376 | default: |
| 390 | BUG(); | 377 | BUG(); |
| 391 | } | 378 | } |
| 392 | 379 | ||
| 393 | if (i915_gem_object_pin(intel_fb->obj, alignment)) | 380 | mutex_lock(&dev->struct_mutex); |
| 394 | return; | 381 | ret = i915_gem_object_pin(intel_fb->obj, alignment); |
| 395 | 382 | if (ret != 0) { | |
| 396 | i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); | 383 | mutex_unlock(&dev->struct_mutex); |
| 397 | 384 | return ret; | |
| 398 | Start = obj_priv->gtt_offset; | 385 | } |
| 399 | Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); | ||
| 400 | 386 | ||
| 401 | I915_WRITE(dspstride, crtc->fb->pitch); | 387 | ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); |
| 388 | if (ret != 0) { | ||
| 389 | i915_gem_object_unpin(intel_fb->obj); | ||
| 390 | mutex_unlock(&dev->struct_mutex); | ||
| 391 | return ret; | ||
| 392 | } | ||
| 402 | 393 | ||
| 403 | dspcntr = I915_READ(dspcntr_reg); | 394 | dspcntr = I915_READ(dspcntr_reg); |
| 404 | /* Mask out pixel format bits in case we change it */ | 395 | /* Mask out pixel format bits in case we change it */ |
| @@ -419,11 +410,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 419 | break; | 410 | break; |
| 420 | default: | 411 | default: |
| 421 | DRM_ERROR("Unknown color depth\n"); | 412 | DRM_ERROR("Unknown color depth\n"); |
| 422 | return; | 413 | i915_gem_object_unpin(intel_fb->obj); |
| 414 | mutex_unlock(&dev->struct_mutex); | ||
| 415 | return -EINVAL; | ||
| 423 | } | 416 | } |
| 424 | I915_WRITE(dspcntr_reg, dspcntr); | 417 | I915_WRITE(dspcntr_reg, dspcntr); |
| 425 | 418 | ||
| 419 | Start = obj_priv->gtt_offset; | ||
| 420 | Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); | ||
| 421 | |||
| 426 | DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); | 422 | DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); |
| 423 | I915_WRITE(dspstride, crtc->fb->pitch); | ||
| 427 | if (IS_I965G(dev)) { | 424 | if (IS_I965G(dev)) { |
| 428 | I915_WRITE(dspbase, Offset); | 425 | I915_WRITE(dspbase, Offset); |
| 429 | I915_READ(dspbase); | 426 | I915_READ(dspbase); |
| @@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 440 | intel_fb = to_intel_framebuffer(old_fb); | 437 | intel_fb = to_intel_framebuffer(old_fb); |
| 441 | i915_gem_object_unpin(intel_fb->obj); | 438 | i915_gem_object_unpin(intel_fb->obj); |
| 442 | } | 439 | } |
| 440 | mutex_unlock(&dev->struct_mutex); | ||
| 443 | 441 | ||
| 444 | if (!dev->primary->master) | 442 | if (!dev->primary->master) |
| 445 | return; | 443 | return 0; |
| 446 | 444 | ||
| 447 | master_priv = dev->primary->master->driver_priv; | 445 | master_priv = dev->primary->master->driver_priv; |
| 448 | if (!master_priv->sarea_priv) | 446 | if (!master_priv->sarea_priv) |
| 449 | return; | 447 | return 0; |
| 450 | 448 | ||
| 451 | switch (pipe) { | 449 | if (pipe) { |
| 452 | case 0: | ||
| 453 | master_priv->sarea_priv->pipeA_x = x; | ||
| 454 | master_priv->sarea_priv->pipeA_y = y; | ||
| 455 | break; | ||
| 456 | case 1: | ||
| 457 | master_priv->sarea_priv->pipeB_x = x; | 450 | master_priv->sarea_priv->pipeB_x = x; |
| 458 | master_priv->sarea_priv->pipeB_y = y; | 451 | master_priv->sarea_priv->pipeB_y = y; |
| 459 | break; | 452 | } else { |
| 460 | default: | 453 | master_priv->sarea_priv->pipeA_x = x; |
| 461 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | 454 | master_priv->sarea_priv->pipeA_y = y; |
| 462 | break; | ||
| 463 | } | 455 | } |
| 456 | |||
| 457 | return 0; | ||
| 464 | } | 458 | } |
| 465 | 459 | ||
| 466 | 460 | ||
| @@ -708,11 +702,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev) | |||
| 708 | return 1; | 702 | return 1; |
| 709 | } | 703 | } |
| 710 | 704 | ||
| 711 | static void intel_crtc_mode_set(struct drm_crtc *crtc, | 705 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
| 712 | struct drm_display_mode *mode, | 706 | struct drm_display_mode *mode, |
| 713 | struct drm_display_mode *adjusted_mode, | 707 | struct drm_display_mode *adjusted_mode, |
| 714 | int x, int y, | 708 | int x, int y, |
| 715 | struct drm_framebuffer *old_fb) | 709 | struct drm_framebuffer *old_fb) |
| 716 | { | 710 | { |
| 717 | struct drm_device *dev = crtc->dev; | 711 | struct drm_device *dev = crtc->dev; |
| 718 | struct drm_i915_private *dev_priv = dev->dev_private; | 712 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 732 | int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | 726 | int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; |
| 733 | int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | 727 | int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; |
| 734 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | 728 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; |
| 735 | int refclk; | 729 | int refclk, num_outputs = 0; |
| 736 | intel_clock_t clock; | 730 | intel_clock_t clock; |
| 737 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | 731 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; |
| 738 | bool ok, is_sdvo = false, is_dvo = false; | 732 | bool ok, is_sdvo = false, is_dvo = false; |
| 739 | bool is_crt = false, is_lvds = false, is_tv = false; | 733 | bool is_crt = false, is_lvds = false, is_tv = false; |
| 740 | struct drm_mode_config *mode_config = &dev->mode_config; | 734 | struct drm_mode_config *mode_config = &dev->mode_config; |
| 741 | struct drm_connector *connector; | 735 | struct drm_connector *connector; |
| 736 | int ret; | ||
| 742 | 737 | ||
| 743 | drm_vblank_pre_modeset(dev, pipe); | 738 | drm_vblank_pre_modeset(dev, pipe); |
| 744 | 739 | ||
| @@ -768,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 768 | is_crt = true; | 763 | is_crt = true; |
| 769 | break; | 764 | break; |
| 770 | } | 765 | } |
| 766 | |||
| 767 | num_outputs++; | ||
| 771 | } | 768 | } |
| 772 | 769 | ||
| 773 | if (IS_I9XX(dev)) { | 770 | if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) { |
| 771 | refclk = dev_priv->lvds_ssc_freq * 1000; | ||
| 772 | DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000); | ||
| 773 | } else if (IS_I9XX(dev)) { | ||
| 774 | refclk = 96000; | 774 | refclk = 96000; |
| 775 | } else { | 775 | } else { |
| 776 | refclk = 48000; | 776 | refclk = 48000; |
| @@ -779,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 779 | ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); | 779 | ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); |
| 780 | if (!ok) { | 780 | if (!ok) { |
| 781 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); | 781 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); |
| 782 | return; | 782 | return -EINVAL; |
| 783 | } | 783 | } |
| 784 | 784 | ||
| 785 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | 785 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; |
| @@ -829,11 +829,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 829 | } | 829 | } |
| 830 | } | 830 | } |
| 831 | 831 | ||
| 832 | if (is_tv) { | 832 | if (is_sdvo && is_tv) |
| 833 | dpll |= PLL_REF_INPUT_TVCLKINBC; | ||
| 834 | else if (is_tv) | ||
| 833 | /* XXX: just matching BIOS for now */ | 835 | /* XXX: just matching BIOS for now */ |
| 834 | /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ | 836 | /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ |
| 835 | dpll |= 3; | 837 | dpll |= 3; |
| 836 | } | 838 | else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) |
| 839 | dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; | ||
| 837 | else | 840 | else |
| 838 | dpll |= PLL_REF_INPUT_DREFCLK; | 841 | dpll |= PLL_REF_INPUT_DREFCLK; |
| 839 | 842 | ||
| @@ -950,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 950 | I915_WRITE(dspcntr_reg, dspcntr); | 953 | I915_WRITE(dspcntr_reg, dspcntr); |
| 951 | 954 | ||
| 952 | /* Flush the plane changes */ | 955 | /* Flush the plane changes */ |
| 953 | intel_pipe_set_base(crtc, x, y, old_fb); | 956 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
| 957 | if (ret != 0) | ||
| 958 | return ret; | ||
| 954 | 959 | ||
| 955 | drm_vblank_post_modeset(dev, pipe); | 960 | drm_vblank_post_modeset(dev, pipe); |
| 961 | |||
| 962 | return 0; | ||
| 956 | } | 963 | } |
| 957 | 964 | ||
| 958 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ | 965 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ |
| @@ -1001,6 +1008,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 1001 | temp = CURSOR_MODE_DISABLE; | 1008 | temp = CURSOR_MODE_DISABLE; |
| 1002 | addr = 0; | 1009 | addr = 0; |
| 1003 | bo = NULL; | 1010 | bo = NULL; |
| 1011 | mutex_lock(&dev->struct_mutex); | ||
| 1004 | goto finish; | 1012 | goto finish; |
| 1005 | } | 1013 | } |
| 1006 | 1014 | ||
| @@ -1023,18 +1031,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 1023 | } | 1031 | } |
| 1024 | 1032 | ||
| 1025 | /* we only need to pin inside GTT if cursor is non-phy */ | 1033 | /* we only need to pin inside GTT if cursor is non-phy */ |
| 1034 | mutex_lock(&dev->struct_mutex); | ||
| 1026 | if (!dev_priv->cursor_needs_physical) { | 1035 | if (!dev_priv->cursor_needs_physical) { |
| 1027 | ret = i915_gem_object_pin(bo, PAGE_SIZE); | 1036 | ret = i915_gem_object_pin(bo, PAGE_SIZE); |
| 1028 | if (ret) { | 1037 | if (ret) { |
| 1029 | DRM_ERROR("failed to pin cursor bo\n"); | 1038 | DRM_ERROR("failed to pin cursor bo\n"); |
| 1030 | goto fail; | 1039 | goto fail_locked; |
| 1031 | } | 1040 | } |
| 1032 | addr = obj_priv->gtt_offset; | 1041 | addr = obj_priv->gtt_offset; |
| 1033 | } else { | 1042 | } else { |
| 1034 | ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); | 1043 | ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); |
| 1035 | if (ret) { | 1044 | if (ret) { |
| 1036 | DRM_ERROR("failed to attach phys object\n"); | 1045 | DRM_ERROR("failed to attach phys object\n"); |
| 1037 | goto fail; | 1046 | goto fail_locked; |
| 1038 | } | 1047 | } |
| 1039 | addr = obj_priv->phys_obj->handle->busaddr; | 1048 | addr = obj_priv->phys_obj->handle->busaddr; |
| 1040 | } | 1049 | } |
| @@ -1054,10 +1063,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 1054 | i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); | 1063 | i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); |
| 1055 | } else | 1064 | } else |
| 1056 | i915_gem_object_unpin(intel_crtc->cursor_bo); | 1065 | i915_gem_object_unpin(intel_crtc->cursor_bo); |
| 1057 | mutex_lock(&dev->struct_mutex); | ||
| 1058 | drm_gem_object_unreference(intel_crtc->cursor_bo); | 1066 | drm_gem_object_unreference(intel_crtc->cursor_bo); |
| 1059 | mutex_unlock(&dev->struct_mutex); | ||
| 1060 | } | 1067 | } |
| 1068 | mutex_unlock(&dev->struct_mutex); | ||
| 1061 | 1069 | ||
| 1062 | intel_crtc->cursor_addr = addr; | 1070 | intel_crtc->cursor_addr = addr; |
| 1063 | intel_crtc->cursor_bo = bo; | 1071 | intel_crtc->cursor_bo = bo; |
| @@ -1065,6 +1073,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
| 1065 | return 0; | 1073 | return 0; |
| 1066 | fail: | 1074 | fail: |
| 1067 | mutex_lock(&dev->struct_mutex); | 1075 | mutex_lock(&dev->struct_mutex); |
| 1076 | fail_locked: | ||
| 1068 | drm_gem_object_unreference(bo); | 1077 | drm_gem_object_unreference(bo); |
| 1069 | mutex_unlock(&dev->struct_mutex); | 1078 | mutex_unlock(&dev->struct_mutex); |
| 1070 | return ret; | 1079 | return ret; |
| @@ -1292,7 +1301,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | |||
| 1292 | } | 1301 | } |
| 1293 | 1302 | ||
| 1294 | /* XXX: Handle the 100Mhz refclk */ | 1303 | /* XXX: Handle the 100Mhz refclk */ |
| 1295 | i9xx_clock(96000, &clock); | 1304 | intel_clock(96000, &clock); |
| 1296 | } else { | 1305 | } else { |
| 1297 | bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); | 1306 | bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); |
| 1298 | 1307 | ||
| @@ -1304,9 +1313,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | |||
| 1304 | if ((dpll & PLL_REF_INPUT_MASK) == | 1313 | if ((dpll & PLL_REF_INPUT_MASK) == |
| 1305 | PLLB_REF_INPUT_SPREADSPECTRUMIN) { | 1314 | PLLB_REF_INPUT_SPREADSPECTRUMIN) { |
| 1306 | /* XXX: might not be 66MHz */ | 1315 | /* XXX: might not be 66MHz */ |
| 1307 | i8xx_clock(66000, &clock); | 1316 | intel_clock(66000, &clock); |
| 1308 | } else | 1317 | } else |
| 1309 | i8xx_clock(48000, &clock); | 1318 | intel_clock(48000, &clock); |
| 1310 | } else { | 1319 | } else { |
| 1311 | if (dpll & PLL_P1_DIVIDE_BY_TWO) | 1320 | if (dpll & PLL_P1_DIVIDE_BY_TWO) |
| 1312 | clock.p1 = 2; | 1321 | clock.p1 = 2; |
| @@ -1319,7 +1328,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | |||
| 1319 | else | 1328 | else |
| 1320 | clock.p2 = 2; | 1329 | clock.p2 = 2; |
| 1321 | 1330 | ||
| 1322 | i8xx_clock(48000, &clock); | 1331 | intel_clock(48000, &clock); |
| 1323 | } | 1332 | } |
| 1324 | } | 1333 | } |
| 1325 | 1334 | ||
| @@ -1598,7 +1607,9 @@ intel_user_framebuffer_create(struct drm_device *dev, | |||
| 1598 | 1607 | ||
| 1599 | ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj); | 1608 | ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj); |
| 1600 | if (ret) { | 1609 | if (ret) { |
| 1610 | mutex_lock(&dev->struct_mutex); | ||
| 1601 | drm_gem_object_unreference(obj); | 1611 | drm_gem_object_unreference(obj); |
| 1612 | mutex_unlock(&dev->struct_mutex); | ||
| 1602 | return NULL; | 1613 | return NULL; |
| 1603 | } | 1614 | } |
| 1604 | 1615 | ||
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index afd1217b8a02..b7f0ebe9f810 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 473 | ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); | 473 | ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); |
| 474 | if (ret) { | 474 | if (ret) { |
| 475 | DRM_ERROR("failed to allocate fb.\n"); | 475 | DRM_ERROR("failed to allocate fb.\n"); |
| 476 | goto out_unref; | 476 | goto out_unpin; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); | 479 | list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); |
| @@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 484 | info = framebuffer_alloc(sizeof(struct intelfb_par), device); | 484 | info = framebuffer_alloc(sizeof(struct intelfb_par), device); |
| 485 | if (!info) { | 485 | if (!info) { |
| 486 | ret = -ENOMEM; | 486 | ret = -ENOMEM; |
| 487 | goto out_unref; | 487 | goto out_unpin; |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | par = info->par; | 490 | par = info->par; |
| @@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 513 | size); | 513 | size); |
| 514 | if (!info->screen_base) { | 514 | if (!info->screen_base) { |
| 515 | ret = -ENOSPC; | 515 | ret = -ENOSPC; |
| 516 | goto out_unref; | 516 | goto out_unpin; |
| 517 | } | 517 | } |
| 518 | info->screen_size = size; | 518 | info->screen_size = size; |
| 519 | 519 | ||
| @@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
| 608 | mutex_unlock(&dev->struct_mutex); | 608 | mutex_unlock(&dev->struct_mutex); |
| 609 | return 0; | 609 | return 0; |
| 610 | 610 | ||
| 611 | out_unpin: | ||
| 612 | i915_gem_object_unpin(fbo); | ||
| 611 | out_unref: | 613 | out_unref: |
| 612 | drm_gem_object_unreference(fbo); | 614 | drm_gem_object_unreference(fbo); |
| 613 | mutex_unlock(&dev->struct_mutex); | 615 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 6d4f91265354..0d211af98854 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 481 | if (dev_priv->panel_fixed_mode) { | 481 | if (dev_priv->panel_fixed_mode) { |
| 482 | dev_priv->panel_fixed_mode->type |= | 482 | dev_priv->panel_fixed_mode->type |= |
| 483 | DRM_MODE_TYPE_PREFERRED; | 483 | DRM_MODE_TYPE_PREFERRED; |
| 484 | drm_mode_probed_add(connector, | ||
| 485 | dev_priv->panel_fixed_mode); | ||
| 486 | goto out; | 484 | goto out; |
| 487 | } | 485 | } |
| 488 | } | 486 | } |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index a30508b639ba..fbe6f3931b1b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | |||
| 193 | 193 | ||
| 194 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} | 194 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} |
| 195 | /** Mapping of command numbers to names, for debug output */ | 195 | /** Mapping of command numbers to names, for debug output */ |
| 196 | const static struct _sdvo_cmd_name { | 196 | static const struct _sdvo_cmd_name { |
| 197 | u8 cmd; | 197 | u8 cmd; |
| 198 | char *name; | 198 | char *name; |
| 199 | } sdvo_cmd_names[] = { | 199 | } sdvo_cmd_names[] = { |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index fbb35dc56f5c..56485d67369b 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -411,7 +411,7 @@ struct tv_mode { | |||
| 411 | * These values account for -1s required. | 411 | * These values account for -1s required. |
| 412 | */ | 412 | */ |
| 413 | 413 | ||
| 414 | const static struct tv_mode tv_modes[] = { | 414 | static const struct tv_mode tv_modes[] = { |
| 415 | { | 415 | { |
| 416 | .name = "NTSC-M", | 416 | .name = "NTSC-M", |
| 417 | .clock = 107520, | 417 | .clock = 107520, |
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index df4cf97e5d97..92965dbb3c14 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
| @@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev) | |||
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | static void radeon_cp_init_ring_buffer(struct drm_device * dev, | 559 | static void radeon_cp_init_ring_buffer(struct drm_device * dev, |
| 560 | drm_radeon_private_t * dev_priv) | 560 | drm_radeon_private_t *dev_priv, |
| 561 | struct drm_file *file_priv) | ||
| 561 | { | 562 | { |
| 563 | struct drm_radeon_master_private *master_priv; | ||
| 562 | u32 ring_start, cur_read_ptr; | 564 | u32 ring_start, cur_read_ptr; |
| 563 | u32 tmp; | 565 | u32 tmp; |
| 564 | 566 | ||
| @@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, | |||
| 677 | dev_priv->scratch[2] = 0; | 679 | dev_priv->scratch[2] = 0; |
| 678 | RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); | 680 | RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); |
| 679 | 681 | ||
| 682 | /* reset sarea copies of these */ | ||
| 683 | master_priv = file_priv->master->driver_priv; | ||
| 684 | if (master_priv->sarea_priv) { | ||
| 685 | master_priv->sarea_priv->last_frame = 0; | ||
| 686 | master_priv->sarea_priv->last_dispatch = 0; | ||
| 687 | master_priv->sarea_priv->last_clear = 0; | ||
| 688 | } | ||
| 689 | |||
| 680 | radeon_do_wait_for_idle(dev_priv); | 690 | radeon_do_wait_for_idle(dev_priv); |
| 681 | 691 | ||
| 682 | /* Sync everything up */ | 692 | /* Sync everything up */ |
| @@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, | |||
| 1215 | } | 1225 | } |
| 1216 | 1226 | ||
| 1217 | radeon_cp_load_microcode(dev_priv); | 1227 | radeon_cp_load_microcode(dev_priv); |
| 1218 | radeon_cp_init_ring_buffer(dev, dev_priv); | 1228 | radeon_cp_init_ring_buffer(dev, dev_priv, file_priv); |
| 1219 | 1229 | ||
| 1220 | dev_priv->last_buf = 0; | 1230 | dev_priv->last_buf = 0; |
| 1221 | 1231 | ||
| @@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) | |||
| 1281 | * | 1291 | * |
| 1282 | * Charl P. Botha <http://cpbotha.net> | 1292 | * Charl P. Botha <http://cpbotha.net> |
| 1283 | */ | 1293 | */ |
| 1284 | static int radeon_do_resume_cp(struct drm_device * dev) | 1294 | static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv) |
| 1285 | { | 1295 | { |
| 1286 | drm_radeon_private_t *dev_priv = dev->dev_private; | 1296 | drm_radeon_private_t *dev_priv = dev->dev_private; |
| 1287 | 1297 | ||
| @@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev) | |||
| 1304 | } | 1314 | } |
| 1305 | 1315 | ||
| 1306 | radeon_cp_load_microcode(dev_priv); | 1316 | radeon_cp_load_microcode(dev_priv); |
| 1307 | radeon_cp_init_ring_buffer(dev, dev_priv); | 1317 | radeon_cp_init_ring_buffer(dev, dev_priv, file_priv); |
| 1308 | 1318 | ||
| 1309 | radeon_do_engine_reset(dev); | 1319 | radeon_do_engine_reset(dev); |
| 1310 | radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); | 1320 | radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); |
| @@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri | |||
| 1479 | */ | 1489 | */ |
| 1480 | int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) | 1490 | int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) |
| 1481 | { | 1491 | { |
| 1482 | 1492 | return radeon_do_resume_cp(dev, file_priv); | |
| 1483 | return radeon_do_resume_cp(dev); | ||
| 1484 | } | 1493 | } |
| 1485 | 1494 | ||
| 1486 | int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) | 1495 | int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) |
