diff options
author | Dave Airlie <airlied@redhat.com> | 2018-05-15 17:10:13 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-05-15 17:10:13 -0400 |
commit | b8a71080ad288eb3fe42f101e64526cdd2823f93 (patch) | |
tree | 505f645f90b5e16aadc304f31fd806459f0fe0e1 | |
parent | 2045b22461c07a88dc3d2bab3cbfc6dc0c602fd4 (diff) | |
parent | 01f83786f9ab9c8883ce634cb9a0de51086ad7ea (diff) |
Merge tag 'drm-intel-next-2018-05-14' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
Last drm/i915 changes for v4.18:
- NV12 enabling (Chandra, Maarten)
- ICL workarounds (Oscar)
- ICL basic DPLL enabling (Paulo)
- GVT updates
- DP link config refactoring (Jani)
- Module parameter to override DMC firmware (Jani)
- PSR updates (José, DK, Daniel, Ville)
- ICL DP vswing programming (Manasi)
- ICL DBuf slice updates (Mahesh)
- Selftest fixes and updates (Chris, Matthew, Oscar)
- Execlist fixes and updates (Chris)
- Stolen memory first 4k fix (Hans de Goede)
- wait_for fixes (Mika)
- Tons of GEM improvements (Chris)
- Plenty of other fixes and improvements (Everyone)
- Crappy changelog (Me)
Signed-off-by: Dave Airlie <airlied@redhat.com>
# gpg: Signature made Mon 14 May 2018 11:04:24 PM AEST
# gpg: using RSA key D398079D26ABEE6F
# gpg: Good signature from "Jani Nikula <jani.nikula@intel.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 1565 A65B 77B0 632E 1124 E59C D398 079D 26AB EE6F
# Conflicts:
# drivers/gpu/drm/i915/intel_lrc.c
# drivers/gpu/drm/i915/intel_sprite.c
Link: https://patchwork.freedesktop.org/patch/msgid/87k1s51bvw.fsf@intel.com
94 files changed, 4488 insertions, 1889 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index dc850b4b6e21..26a22f529e9b 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -1716,11 +1716,15 @@ int drm_atomic_check_only(struct drm_atomic_state *state) | |||
1716 | } | 1716 | } |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | if (config->funcs->atomic_check) | 1719 | if (config->funcs->atomic_check) { |
1720 | ret = config->funcs->atomic_check(state->dev, state); | 1720 | ret = config->funcs->atomic_check(state->dev, state); |
1721 | 1721 | ||
1722 | if (ret) | 1722 | if (ret) { |
1723 | return ret; | 1723 | DRM_DEBUG_ATOMIC("atomic driver check for %p failed: %d\n", |
1724 | state, ret); | ||
1725 | return ret; | ||
1726 | } | ||
1727 | } | ||
1724 | 1728 | ||
1725 | if (!state->allow_modeset) { | 1729 | if (!state->allow_modeset) { |
1726 | for_each_new_crtc_in_state(state, crtc, crtc_state, i) { | 1730 | for_each_new_crtc_in_state(state, crtc, crtc_state, i) { |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9bee52a949a9..4c6adae23e18 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -18,6 +18,10 @@ subdir-ccflags-y += $(call cc-disable-warning, type-limits) | |||
18 | subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) | 18 | subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) |
19 | subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough) | 19 | subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough) |
20 | subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) | 20 | subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) |
21 | # clang warnings | ||
22 | subdir-ccflags-y += $(call cc-disable-warning, sign-compare) | ||
23 | subdir-ccflags-y += $(call cc-disable-warning, sometimes-uninitialized) | ||
24 | subdir-ccflags-y += $(call cc-disable-warning, initializer-overrides) | ||
21 | subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror | 25 | subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror |
22 | 26 | ||
23 | # Fine grained warnings disable | 27 | # Fine grained warnings disable |
@@ -67,11 +71,11 @@ i915-y += i915_cmd_parser.o \ | |||
67 | i915_gem_shrinker.o \ | 71 | i915_gem_shrinker.o \ |
68 | i915_gem_stolen.o \ | 72 | i915_gem_stolen.o \ |
69 | i915_gem_tiling.o \ | 73 | i915_gem_tiling.o \ |
70 | i915_gem_timeline.o \ | ||
71 | i915_gem_userptr.o \ | 74 | i915_gem_userptr.o \ |
72 | i915_gemfs.o \ | 75 | i915_gemfs.o \ |
73 | i915_query.o \ | 76 | i915_query.o \ |
74 | i915_request.o \ | 77 | i915_request.o \ |
78 | i915_timeline.o \ | ||
75 | i915_trace_points.o \ | 79 | i915_trace_points.o \ |
76 | i915_vma.o \ | 80 | i915_vma.o \ |
77 | intel_breadcrumbs.o \ | 81 | intel_breadcrumbs.o \ |
@@ -154,7 +158,8 @@ i915-y += dvo_ch7017.o \ | |||
154 | i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o | 158 | i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o |
155 | i915-$(CONFIG_DRM_I915_SELFTEST) += \ | 159 | i915-$(CONFIG_DRM_I915_SELFTEST) += \ |
156 | selftests/i915_random.o \ | 160 | selftests/i915_random.o \ |
157 | selftests/i915_selftest.o | 161 | selftests/i915_selftest.o \ |
162 | selftests/igt_flush_test.o | ||
158 | 163 | ||
159 | # virtual gpu code | 164 | # virtual gpu code |
160 | i915-y += i915_vgpu.o | 165 | i915-y += i915_vgpu.o |
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index d85939bd7b47..718ca08f9575 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c | |||
@@ -813,15 +813,31 @@ static inline bool is_force_nonpriv_mmio(unsigned int offset) | |||
813 | } | 813 | } |
814 | 814 | ||
815 | static int force_nonpriv_reg_handler(struct parser_exec_state *s, | 815 | static int force_nonpriv_reg_handler(struct parser_exec_state *s, |
816 | unsigned int offset, unsigned int index) | 816 | unsigned int offset, unsigned int index, char *cmd) |
817 | { | 817 | { |
818 | struct intel_gvt *gvt = s->vgpu->gvt; | 818 | struct intel_gvt *gvt = s->vgpu->gvt; |
819 | unsigned int data = cmd_val(s, index + 1); | 819 | unsigned int data; |
820 | u32 ring_base; | ||
821 | u32 nopid; | ||
822 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
823 | |||
824 | if (!strcmp(cmd, "lri")) | ||
825 | data = cmd_val(s, index + 1); | ||
826 | else { | ||
827 | gvt_err("Unexpected forcenonpriv 0x%x write from cmd %s\n", | ||
828 | offset, cmd); | ||
829 | return -EINVAL; | ||
830 | } | ||
831 | |||
832 | ring_base = dev_priv->engine[s->ring_id]->mmio_base; | ||
833 | nopid = i915_mmio_reg_offset(RING_NOPID(ring_base)); | ||
820 | 834 | ||
821 | if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data)) { | 835 | if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data) && |
836 | data != nopid) { | ||
822 | gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n", | 837 | gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n", |
823 | offset, data); | 838 | offset, data); |
824 | return -EPERM; | 839 | patch_value(s, cmd_ptr(s, index), nopid); |
840 | return 0; | ||
825 | } | 841 | } |
826 | return 0; | 842 | return 0; |
827 | } | 843 | } |
@@ -869,7 +885,7 @@ static int cmd_reg_handler(struct parser_exec_state *s, | |||
869 | return -EINVAL; | 885 | return -EINVAL; |
870 | 886 | ||
871 | if (is_force_nonpriv_mmio(offset) && | 887 | if (is_force_nonpriv_mmio(offset) && |
872 | force_nonpriv_reg_handler(s, offset, index)) | 888 | force_nonpriv_reg_handler(s, offset, index, cmd)) |
873 | return -EPERM; | 889 | return -EPERM; |
874 | 890 | ||
875 | if (offset == i915_mmio_reg_offset(DERRMR) || | 891 | if (offset == i915_mmio_reg_offset(DERRMR) || |
@@ -1604,7 +1620,8 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s) | |||
1604 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) | 1620 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) |
1605 | || IS_KABYLAKE(gvt->dev_priv)) { | 1621 | || IS_KABYLAKE(gvt->dev_priv)) { |
1606 | /* BDW decides privilege based on address space */ | 1622 | /* BDW decides privilege based on address space */ |
1607 | if (cmd_val(s, 0) & (1 << 8)) | 1623 | if (cmd_val(s, 0) & (1 << 8) && |
1624 | !(s->vgpu->scan_nonprivbb & (1 << s->ring_id))) | ||
1608 | return 0; | 1625 | return 0; |
1609 | } | 1626 | } |
1610 | return 1; | 1627 | return 1; |
@@ -1618,6 +1635,8 @@ static int find_bb_size(struct parser_exec_state *s, unsigned long *bb_size) | |||
1618 | bool bb_end = false; | 1635 | bool bb_end = false; |
1619 | struct intel_vgpu *vgpu = s->vgpu; | 1636 | struct intel_vgpu *vgpu = s->vgpu; |
1620 | u32 cmd; | 1637 | u32 cmd; |
1638 | struct intel_vgpu_mm *mm = (s->buf_addr_type == GTT_BUFFER) ? | ||
1639 | s->vgpu->gtt.ggtt_mm : s->workload->shadow_mm; | ||
1621 | 1640 | ||
1622 | *bb_size = 0; | 1641 | *bb_size = 0; |
1623 | 1642 | ||
@@ -1629,18 +1648,22 @@ static int find_bb_size(struct parser_exec_state *s, unsigned long *bb_size) | |||
1629 | cmd = cmd_val(s, 0); | 1648 | cmd = cmd_val(s, 0); |
1630 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); | 1649 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); |
1631 | if (info == NULL) { | 1650 | if (info == NULL) { |
1632 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n", | 1651 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x, addr_type=%s, ring %d, workload=%p\n", |
1633 | cmd, get_opcode(cmd, s->ring_id)); | 1652 | cmd, get_opcode(cmd, s->ring_id), |
1653 | (s->buf_addr_type == PPGTT_BUFFER) ? | ||
1654 | "ppgtt" : "ggtt", s->ring_id, s->workload); | ||
1634 | return -EBADRQC; | 1655 | return -EBADRQC; |
1635 | } | 1656 | } |
1636 | do { | 1657 | do { |
1637 | if (copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, | 1658 | if (copy_gma_to_hva(s->vgpu, mm, |
1638 | gma, gma + 4, &cmd) < 0) | 1659 | gma, gma + 4, &cmd) < 0) |
1639 | return -EFAULT; | 1660 | return -EFAULT; |
1640 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); | 1661 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); |
1641 | if (info == NULL) { | 1662 | if (info == NULL) { |
1642 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n", | 1663 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x, addr_type=%s, ring %d, workload=%p\n", |
1643 | cmd, get_opcode(cmd, s->ring_id)); | 1664 | cmd, get_opcode(cmd, s->ring_id), |
1665 | (s->buf_addr_type == PPGTT_BUFFER) ? | ||
1666 | "ppgtt" : "ggtt", s->ring_id, s->workload); | ||
1644 | return -EBADRQC; | 1667 | return -EBADRQC; |
1645 | } | 1668 | } |
1646 | 1669 | ||
@@ -1666,6 +1689,9 @@ static int perform_bb_shadow(struct parser_exec_state *s) | |||
1666 | unsigned long gma = 0; | 1689 | unsigned long gma = 0; |
1667 | unsigned long bb_size; | 1690 | unsigned long bb_size; |
1668 | int ret = 0; | 1691 | int ret = 0; |
1692 | struct intel_vgpu_mm *mm = (s->buf_addr_type == GTT_BUFFER) ? | ||
1693 | s->vgpu->gtt.ggtt_mm : s->workload->shadow_mm; | ||
1694 | unsigned long gma_start_offset = 0; | ||
1669 | 1695 | ||
1670 | /* get the start gm address of the batch buffer */ | 1696 | /* get the start gm address of the batch buffer */ |
1671 | gma = get_gma_bb_from_cmd(s, 1); | 1697 | gma = get_gma_bb_from_cmd(s, 1); |
@@ -1680,8 +1706,24 @@ static int perform_bb_shadow(struct parser_exec_state *s) | |||
1680 | if (!bb) | 1706 | if (!bb) |
1681 | return -ENOMEM; | 1707 | return -ENOMEM; |
1682 | 1708 | ||
1709 | bb->ppgtt = (s->buf_addr_type == GTT_BUFFER) ? false : true; | ||
1710 | |||
1711 | /* the gma_start_offset stores the batch buffer's start gma's | ||
1712 | * offset relative to page boundary. so for non-privileged batch | ||
1713 | * buffer, the shadowed gem object holds exactly the same page | ||
1714 | * layout as original gem object. This is for the convience of | ||
1715 | * replacing the whole non-privilged batch buffer page to this | ||
1716 | * shadowed one in PPGTT at the same gma address. (this replacing | ||
1717 | * action is not implemented yet now, but may be necessary in | ||
1718 | * future). | ||
1719 | * for prileged batch buffer, we just change start gma address to | ||
1720 | * that of shadowed page. | ||
1721 | */ | ||
1722 | if (bb->ppgtt) | ||
1723 | gma_start_offset = gma & ~I915_GTT_PAGE_MASK; | ||
1724 | |||
1683 | bb->obj = i915_gem_object_create(s->vgpu->gvt->dev_priv, | 1725 | bb->obj = i915_gem_object_create(s->vgpu->gvt->dev_priv, |
1684 | roundup(bb_size, PAGE_SIZE)); | 1726 | roundup(bb_size + gma_start_offset, PAGE_SIZE)); |
1685 | if (IS_ERR(bb->obj)) { | 1727 | if (IS_ERR(bb->obj)) { |
1686 | ret = PTR_ERR(bb->obj); | 1728 | ret = PTR_ERR(bb->obj); |
1687 | goto err_free_bb; | 1729 | goto err_free_bb; |
@@ -1702,9 +1744,9 @@ static int perform_bb_shadow(struct parser_exec_state *s) | |||
1702 | bb->clflush &= ~CLFLUSH_BEFORE; | 1744 | bb->clflush &= ~CLFLUSH_BEFORE; |
1703 | } | 1745 | } |
1704 | 1746 | ||
1705 | ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, | 1747 | ret = copy_gma_to_hva(s->vgpu, mm, |
1706 | gma, gma + bb_size, | 1748 | gma, gma + bb_size, |
1707 | bb->va); | 1749 | bb->va + gma_start_offset); |
1708 | if (ret < 0) { | 1750 | if (ret < 0) { |
1709 | gvt_vgpu_err("fail to copy guest ring buffer\n"); | 1751 | gvt_vgpu_err("fail to copy guest ring buffer\n"); |
1710 | ret = -EFAULT; | 1752 | ret = -EFAULT; |
@@ -1730,7 +1772,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) | |||
1730 | * buffer's gma in pair. After all, we don't want to pin the shadow | 1772 | * buffer's gma in pair. After all, we don't want to pin the shadow |
1731 | * buffer here (too early). | 1773 | * buffer here (too early). |
1732 | */ | 1774 | */ |
1733 | s->ip_va = bb->va; | 1775 | s->ip_va = bb->va + gma_start_offset; |
1734 | s->ip_gma = gma; | 1776 | s->ip_gma = gma; |
1735 | return 0; | 1777 | return 0; |
1736 | err_unmap: | 1778 | err_unmap: |
@@ -2469,15 +2511,18 @@ static int cmd_parser_exec(struct parser_exec_state *s) | |||
2469 | 2511 | ||
2470 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); | 2512 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); |
2471 | if (info == NULL) { | 2513 | if (info == NULL) { |
2472 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n", | 2514 | gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x, addr_type=%s, ring %d, workload=%p\n", |
2473 | cmd, get_opcode(cmd, s->ring_id)); | 2515 | cmd, get_opcode(cmd, s->ring_id), |
2516 | (s->buf_addr_type == PPGTT_BUFFER) ? | ||
2517 | "ppgtt" : "ggtt", s->ring_id, s->workload); | ||
2474 | return -EBADRQC; | 2518 | return -EBADRQC; |
2475 | } | 2519 | } |
2476 | 2520 | ||
2477 | s->info = info; | 2521 | s->info = info; |
2478 | 2522 | ||
2479 | trace_gvt_command(vgpu->id, s->ring_id, s->ip_gma, s->ip_va, | 2523 | trace_gvt_command(vgpu->id, s->ring_id, s->ip_gma, s->ip_va, |
2480 | cmd_length(s), s->buf_type); | 2524 | cmd_length(s), s->buf_type, s->buf_addr_type, |
2525 | s->workload, info->name); | ||
2481 | 2526 | ||
2482 | if (info->handler) { | 2527 | if (info->handler) { |
2483 | ret = info->handler(s); | 2528 | ret = info->handler(s); |
diff --git a/drivers/gpu/drm/i915/gvt/debugfs.c b/drivers/gpu/drm/i915/gvt/debugfs.c index f7d0078eb61b..2ec89bcb59f1 100644 --- a/drivers/gpu/drm/i915/gvt/debugfs.c +++ b/drivers/gpu/drm/i915/gvt/debugfs.c | |||
@@ -124,6 +124,68 @@ static int vgpu_mmio_diff_show(struct seq_file *s, void *unused) | |||
124 | } | 124 | } |
125 | DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff); | 125 | DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff); |
126 | 126 | ||
127 | static int | ||
128 | vgpu_scan_nonprivbb_get(void *data, u64 *val) | ||
129 | { | ||
130 | struct intel_vgpu *vgpu = (struct intel_vgpu *)data; | ||
131 | *val = vgpu->scan_nonprivbb; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * set/unset bit engine_id of vgpu->scan_nonprivbb to turn on/off scanning | ||
137 | * of non-privileged batch buffer. e.g. | ||
138 | * if vgpu->scan_nonprivbb=3, then it will scan non-privileged batch buffer | ||
139 | * on engine 0 and 1. | ||
140 | */ | ||
141 | static int | ||
142 | vgpu_scan_nonprivbb_set(void *data, u64 val) | ||
143 | { | ||
144 | struct intel_vgpu *vgpu = (struct intel_vgpu *)data; | ||
145 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
146 | enum intel_engine_id id; | ||
147 | char buf[128], *s; | ||
148 | int len; | ||
149 | |||
150 | val &= (1 << I915_NUM_ENGINES) - 1; | ||
151 | |||
152 | if (vgpu->scan_nonprivbb == val) | ||
153 | return 0; | ||
154 | |||
155 | if (!val) | ||
156 | goto done; | ||
157 | |||
158 | len = sprintf(buf, | ||
159 | "gvt: vgpu %d turns on non-privileged batch buffers scanning on Engines:", | ||
160 | vgpu->id); | ||
161 | |||
162 | s = buf + len; | ||
163 | |||
164 | for (id = 0; id < I915_NUM_ENGINES; id++) { | ||
165 | struct intel_engine_cs *engine; | ||
166 | |||
167 | engine = dev_priv->engine[id]; | ||
168 | if (engine && (val & (1 << id))) { | ||
169 | len = snprintf(s, 4, "%d, ", engine->id); | ||
170 | s += len; | ||
171 | } else | ||
172 | val &= ~(1 << id); | ||
173 | } | ||
174 | |||
175 | if (val) | ||
176 | sprintf(s, "low performance expected."); | ||
177 | |||
178 | pr_warn("%s\n", buf); | ||
179 | |||
180 | done: | ||
181 | vgpu->scan_nonprivbb = val; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | DEFINE_SIMPLE_ATTRIBUTE(vgpu_scan_nonprivbb_fops, | ||
186 | vgpu_scan_nonprivbb_get, vgpu_scan_nonprivbb_set, | ||
187 | "0x%llx\n"); | ||
188 | |||
127 | /** | 189 | /** |
128 | * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU | 190 | * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU |
129 | * @vgpu: a vGPU | 191 | * @vgpu: a vGPU |
@@ -151,6 +213,11 @@ int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu) | |||
151 | if (!ent) | 213 | if (!ent) |
152 | return -ENOMEM; | 214 | return -ENOMEM; |
153 | 215 | ||
216 | ent = debugfs_create_file("scan_nonprivbb", 0644, vgpu->debugfs, | ||
217 | vgpu, &vgpu_scan_nonprivbb_fops); | ||
218 | if (!ent) | ||
219 | return -ENOMEM; | ||
220 | |||
154 | return 0; | 221 | return 0; |
155 | } | 222 | } |
156 | 223 | ||
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index efacd8abbedc..05d15a095310 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h | |||
@@ -99,7 +99,6 @@ struct intel_vgpu_fence { | |||
99 | struct intel_vgpu_mmio { | 99 | struct intel_vgpu_mmio { |
100 | void *vreg; | 100 | void *vreg; |
101 | void *sreg; | 101 | void *sreg; |
102 | bool disable_warn_untrack; | ||
103 | }; | 102 | }; |
104 | 103 | ||
105 | #define INTEL_GVT_MAX_BAR_NUM 4 | 104 | #define INTEL_GVT_MAX_BAR_NUM 4 |
@@ -226,6 +225,7 @@ struct intel_vgpu { | |||
226 | 225 | ||
227 | struct completion vblank_done; | 226 | struct completion vblank_done; |
228 | 227 | ||
228 | u32 scan_nonprivbb; | ||
229 | }; | 229 | }; |
230 | 230 | ||
231 | /* validating GM healthy status*/ | 231 | /* validating GM healthy status*/ |
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index a33c1c3e4a21..4b6532fb789a 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c | |||
@@ -191,6 +191,8 @@ static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu, | |||
191 | unsigned int max_fence = vgpu_fence_sz(vgpu); | 191 | unsigned int max_fence = vgpu_fence_sz(vgpu); |
192 | 192 | ||
193 | if (fence_num >= max_fence) { | 193 | if (fence_num >= max_fence) { |
194 | gvt_vgpu_err("access oob fence reg %d/%d\n", | ||
195 | fence_num, max_fence); | ||
194 | 196 | ||
195 | /* When guest access oob fence regs without access | 197 | /* When guest access oob fence regs without access |
196 | * pv_info first, we treat guest not supporting GVT, | 198 | * pv_info first, we treat guest not supporting GVT, |
@@ -200,11 +202,6 @@ static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu, | |||
200 | enter_failsafe_mode(vgpu, | 202 | enter_failsafe_mode(vgpu, |
201 | GVT_FAILSAFE_UNSUPPORTED_GUEST); | 203 | GVT_FAILSAFE_UNSUPPORTED_GUEST); |
202 | 204 | ||
203 | if (!vgpu->mmio.disable_warn_untrack) { | ||
204 | gvt_vgpu_err("found oob fence register access\n"); | ||
205 | gvt_vgpu_err("total fence %d, access fence %d\n", | ||
206 | max_fence, fence_num); | ||
207 | } | ||
208 | memset(p_data, 0, bytes); | 205 | memset(p_data, 0, bytes); |
209 | return -EINVAL; | 206 | return -EINVAL; |
210 | } | 207 | } |
@@ -477,22 +474,28 @@ static int force_nonpriv_write(struct intel_vgpu *vgpu, | |||
477 | unsigned int offset, void *p_data, unsigned int bytes) | 474 | unsigned int offset, void *p_data, unsigned int bytes) |
478 | { | 475 | { |
479 | u32 reg_nonpriv = *(u32 *)p_data; | 476 | u32 reg_nonpriv = *(u32 *)p_data; |
477 | int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); | ||
478 | u32 ring_base; | ||
479 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
480 | int ret = -EINVAL; | 480 | int ret = -EINVAL; |
481 | 481 | ||
482 | if ((bytes != 4) || ((offset & (bytes - 1)) != 0)) { | 482 | if ((bytes != 4) || ((offset & (bytes - 1)) != 0) || ring_id < 0) { |
483 | gvt_err("vgpu(%d) Invalid FORCE_NONPRIV offset %x(%dB)\n", | 483 | gvt_err("vgpu(%d) ring %d Invalid FORCE_NONPRIV offset %x(%dB)\n", |
484 | vgpu->id, offset, bytes); | 484 | vgpu->id, ring_id, offset, bytes); |
485 | return ret; | 485 | return ret; |
486 | } | 486 | } |
487 | 487 | ||
488 | if (in_whitelist(reg_nonpriv)) { | 488 | ring_base = dev_priv->engine[ring_id]->mmio_base; |
489 | |||
490 | if (in_whitelist(reg_nonpriv) || | ||
491 | reg_nonpriv == i915_mmio_reg_offset(RING_NOPID(ring_base))) { | ||
489 | ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data, | 492 | ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data, |
490 | bytes); | 493 | bytes); |
491 | } else { | 494 | } else |
492 | gvt_err("vgpu(%d) Invalid FORCE_NONPRIV write %x\n", | 495 | gvt_err("vgpu(%d) Invalid FORCE_NONPRIV write %x at offset %x\n", |
493 | vgpu->id, reg_nonpriv); | 496 | vgpu->id, reg_nonpriv, offset); |
494 | } | 497 | |
495 | return ret; | 498 | return 0; |
496 | } | 499 | } |
497 | 500 | ||
498 | static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | 501 | static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, |
@@ -3092,9 +3095,7 @@ int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset, | |||
3092 | */ | 3095 | */ |
3093 | mmio_info = find_mmio_info(gvt, offset); | 3096 | mmio_info = find_mmio_info(gvt, offset); |
3094 | if (!mmio_info) { | 3097 | if (!mmio_info) { |
3095 | if (!vgpu->mmio.disable_warn_untrack) | 3098 | gvt_dbg_mmio("untracked MMIO %08x len %d\n", offset, bytes); |
3096 | gvt_vgpu_err("untracked MMIO %08x len %d\n", | ||
3097 | offset, bytes); | ||
3098 | goto default_rw; | 3099 | goto default_rw; |
3099 | } | 3100 | } |
3100 | 3101 | ||
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 11b71b33f1c0..e4960aff68bd 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c | |||
@@ -244,8 +244,6 @@ void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr) | |||
244 | 244 | ||
245 | /* set the bit 0:2(Core C-State ) to C0 */ | 245 | /* set the bit 0:2(Core C-State ) to C0 */ |
246 | vgpu_vreg_t(vgpu, GEN6_GT_CORE_STATUS) = 0; | 246 | vgpu_vreg_t(vgpu, GEN6_GT_CORE_STATUS) = 0; |
247 | |||
248 | vgpu->mmio.disable_warn_untrack = false; | ||
249 | } else { | 247 | } else { |
250 | #define GVT_GEN8_MMIO_RESET_OFFSET (0x44200) | 248 | #define GVT_GEN8_MMIO_RESET_OFFSET (0x44200) |
251 | /* only reset the engine related, so starting with 0x44200 | 249 | /* only reset the engine related, so starting with 0x44200 |
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index a5bac83d53a9..0f949554d118 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c | |||
@@ -448,7 +448,7 @@ static void switch_mocs(struct intel_vgpu *pre, struct intel_vgpu *next, | |||
448 | 448 | ||
449 | bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id) | 449 | bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id) |
450 | { | 450 | { |
451 | u32 *reg_state = ctx->engine[ring_id].lrc_reg_state; | 451 | u32 *reg_state = ctx->__engine[ring_id].lrc_reg_state; |
452 | u32 inhibit_mask = | 452 | u32 inhibit_mask = |
453 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); | 453 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); |
454 | 454 | ||
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index 75b7bc7b344c..d053cbe1dc94 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c | |||
@@ -53,7 +53,6 @@ struct vgpu_sched_data { | |||
53 | bool active; | 53 | bool active; |
54 | 54 | ||
55 | ktime_t sched_in_time; | 55 | ktime_t sched_in_time; |
56 | ktime_t sched_out_time; | ||
57 | ktime_t sched_time; | 56 | ktime_t sched_time; |
58 | ktime_t left_ts; | 57 | ktime_t left_ts; |
59 | ktime_t allocated_ts; | 58 | ktime_t allocated_ts; |
@@ -66,17 +65,22 @@ struct gvt_sched_data { | |||
66 | struct hrtimer timer; | 65 | struct hrtimer timer; |
67 | unsigned long period; | 66 | unsigned long period; |
68 | struct list_head lru_runq_head; | 67 | struct list_head lru_runq_head; |
68 | ktime_t expire_time; | ||
69 | }; | 69 | }; |
70 | 70 | ||
71 | static void vgpu_update_timeslice(struct intel_vgpu *pre_vgpu) | 71 | static void vgpu_update_timeslice(struct intel_vgpu *vgpu, ktime_t cur_time) |
72 | { | 72 | { |
73 | ktime_t delta_ts; | 73 | ktime_t delta_ts; |
74 | struct vgpu_sched_data *vgpu_data = pre_vgpu->sched_data; | 74 | struct vgpu_sched_data *vgpu_data; |
75 | 75 | ||
76 | delta_ts = vgpu_data->sched_out_time - vgpu_data->sched_in_time; | 76 | if (!vgpu || vgpu == vgpu->gvt->idle_vgpu) |
77 | return; | ||
77 | 78 | ||
78 | vgpu_data->sched_time += delta_ts; | 79 | vgpu_data = vgpu->sched_data; |
79 | vgpu_data->left_ts -= delta_ts; | 80 | delta_ts = ktime_sub(cur_time, vgpu_data->sched_in_time); |
81 | vgpu_data->sched_time = ktime_add(vgpu_data->sched_time, delta_ts); | ||
82 | vgpu_data->left_ts = ktime_sub(vgpu_data->left_ts, delta_ts); | ||
83 | vgpu_data->sched_in_time = cur_time; | ||
80 | } | 84 | } |
81 | 85 | ||
82 | #define GVT_TS_BALANCE_PERIOD_MS 100 | 86 | #define GVT_TS_BALANCE_PERIOD_MS 100 |
@@ -150,11 +154,7 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) | |||
150 | } | 154 | } |
151 | 155 | ||
152 | cur_time = ktime_get(); | 156 | cur_time = ktime_get(); |
153 | if (scheduler->current_vgpu) { | 157 | vgpu_update_timeslice(scheduler->current_vgpu, cur_time); |
154 | vgpu_data = scheduler->current_vgpu->sched_data; | ||
155 | vgpu_data->sched_out_time = cur_time; | ||
156 | vgpu_update_timeslice(scheduler->current_vgpu); | ||
157 | } | ||
158 | vgpu_data = scheduler->next_vgpu->sched_data; | 158 | vgpu_data = scheduler->next_vgpu->sched_data; |
159 | vgpu_data->sched_in_time = cur_time; | 159 | vgpu_data->sched_in_time = cur_time; |
160 | 160 | ||
@@ -226,17 +226,22 @@ out: | |||
226 | void intel_gvt_schedule(struct intel_gvt *gvt) | 226 | void intel_gvt_schedule(struct intel_gvt *gvt) |
227 | { | 227 | { |
228 | struct gvt_sched_data *sched_data = gvt->scheduler.sched_data; | 228 | struct gvt_sched_data *sched_data = gvt->scheduler.sched_data; |
229 | static uint64_t timer_check; | 229 | ktime_t cur_time; |
230 | 230 | ||
231 | mutex_lock(&gvt->lock); | 231 | mutex_lock(&gvt->lock); |
232 | cur_time = ktime_get(); | ||
232 | 233 | ||
233 | if (test_and_clear_bit(INTEL_GVT_REQUEST_SCHED, | 234 | if (test_and_clear_bit(INTEL_GVT_REQUEST_SCHED, |
234 | (void *)&gvt->service_request)) { | 235 | (void *)&gvt->service_request)) { |
235 | if (!(timer_check++ % GVT_TS_BALANCE_PERIOD_MS)) | 236 | if (cur_time >= sched_data->expire_time) { |
236 | gvt_balance_timeslice(sched_data); | 237 | gvt_balance_timeslice(sched_data); |
238 | sched_data->expire_time = ktime_add_ms( | ||
239 | cur_time, GVT_TS_BALANCE_PERIOD_MS); | ||
240 | } | ||
237 | } | 241 | } |
238 | clear_bit(INTEL_GVT_REQUEST_EVENT_SCHED, (void *)&gvt->service_request); | 242 | clear_bit(INTEL_GVT_REQUEST_EVENT_SCHED, (void *)&gvt->service_request); |
239 | 243 | ||
244 | vgpu_update_timeslice(gvt->scheduler.current_vgpu, cur_time); | ||
240 | tbs_sched_func(sched_data); | 245 | tbs_sched_func(sched_data); |
241 | 246 | ||
242 | mutex_unlock(&gvt->lock); | 247 | mutex_unlock(&gvt->lock); |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 638abe84857c..c2d183b91500 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c | |||
@@ -58,7 +58,7 @@ static void update_shadow_pdps(struct intel_vgpu_workload *workload) | |||
58 | int ring_id = workload->ring_id; | 58 | int ring_id = workload->ring_id; |
59 | struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; | 59 | struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; |
60 | struct drm_i915_gem_object *ctx_obj = | 60 | struct drm_i915_gem_object *ctx_obj = |
61 | shadow_ctx->engine[ring_id].state->obj; | 61 | shadow_ctx->__engine[ring_id].state->obj; |
62 | struct execlist_ring_context *shadow_ring_context; | 62 | struct execlist_ring_context *shadow_ring_context; |
63 | struct page *page; | 63 | struct page *page; |
64 | 64 | ||
@@ -97,7 +97,7 @@ static void sr_oa_regs(struct intel_vgpu_workload *workload, | |||
97 | i915_mmio_reg_offset(EU_PERF_CNTL6), | 97 | i915_mmio_reg_offset(EU_PERF_CNTL6), |
98 | }; | 98 | }; |
99 | 99 | ||
100 | if (!workload || !reg_state || workload->ring_id != RCS) | 100 | if (workload->ring_id != RCS) |
101 | return; | 101 | return; |
102 | 102 | ||
103 | if (save) { | 103 | if (save) { |
@@ -130,7 +130,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) | |||
130 | int ring_id = workload->ring_id; | 130 | int ring_id = workload->ring_id; |
131 | struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; | 131 | struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx; |
132 | struct drm_i915_gem_object *ctx_obj = | 132 | struct drm_i915_gem_object *ctx_obj = |
133 | shadow_ctx->engine[ring_id].state->obj; | 133 | shadow_ctx->__engine[ring_id].state->obj; |
134 | struct execlist_ring_context *shadow_ring_context; | 134 | struct execlist_ring_context *shadow_ring_context; |
135 | struct page *page; | 135 | struct page *page; |
136 | void *dst; | 136 | void *dst; |
@@ -283,7 +283,7 @@ static int shadow_context_status_change(struct notifier_block *nb, | |||
283 | static void shadow_context_descriptor_update(struct i915_gem_context *ctx, | 283 | static void shadow_context_descriptor_update(struct i915_gem_context *ctx, |
284 | struct intel_engine_cs *engine) | 284 | struct intel_engine_cs *engine) |
285 | { | 285 | { |
286 | struct intel_context *ce = &ctx->engine[engine->id]; | 286 | struct intel_context *ce = to_intel_context(ctx, engine); |
287 | u64 desc = 0; | 287 | u64 desc = 0; |
288 | 288 | ||
289 | desc = ce->lrc_desc; | 289 | desc = ce->lrc_desc; |
@@ -389,7 +389,7 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) | |||
389 | * shadow_ctx pages invalid. So gvt need to pin itself. After update | 389 | * shadow_ctx pages invalid. So gvt need to pin itself. After update |
390 | * the guest context, gvt can unpin the shadow_ctx safely. | 390 | * the guest context, gvt can unpin the shadow_ctx safely. |
391 | */ | 391 | */ |
392 | ring = engine->context_pin(engine, shadow_ctx); | 392 | ring = intel_context_pin(shadow_ctx, engine); |
393 | if (IS_ERR(ring)) { | 393 | if (IS_ERR(ring)) { |
394 | ret = PTR_ERR(ring); | 394 | ret = PTR_ERR(ring); |
395 | gvt_vgpu_err("fail to pin shadow context\n"); | 395 | gvt_vgpu_err("fail to pin shadow context\n"); |
@@ -403,7 +403,7 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) | |||
403 | return 0; | 403 | return 0; |
404 | 404 | ||
405 | err_unpin: | 405 | err_unpin: |
406 | engine->context_unpin(engine, shadow_ctx); | 406 | intel_context_unpin(shadow_ctx, engine); |
407 | err_shadow: | 407 | err_shadow: |
408 | release_shadow_wa_ctx(&workload->wa_ctx); | 408 | release_shadow_wa_ctx(&workload->wa_ctx); |
409 | err_scan: | 409 | err_scan: |
@@ -437,7 +437,7 @@ static int intel_gvt_generate_request(struct intel_vgpu_workload *workload) | |||
437 | return 0; | 437 | return 0; |
438 | 438 | ||
439 | err_unpin: | 439 | err_unpin: |
440 | engine->context_unpin(engine, shadow_ctx); | 440 | intel_context_unpin(shadow_ctx, engine); |
441 | release_shadow_wa_ctx(&workload->wa_ctx); | 441 | release_shadow_wa_ctx(&workload->wa_ctx); |
442 | return ret; | 442 | return ret; |
443 | } | 443 | } |
@@ -452,12 +452,6 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |||
452 | int ret; | 452 | int ret; |
453 | 453 | ||
454 | list_for_each_entry(bb, &workload->shadow_bb, list) { | 454 | list_for_each_entry(bb, &workload->shadow_bb, list) { |
455 | bb->vma = i915_gem_object_ggtt_pin(bb->obj, NULL, 0, 0, 0); | ||
456 | if (IS_ERR(bb->vma)) { | ||
457 | ret = PTR_ERR(bb->vma); | ||
458 | goto err; | ||
459 | } | ||
460 | |||
461 | /* For privilge batch buffer and not wa_ctx, the bb_start_cmd_va | 455 | /* For privilge batch buffer and not wa_ctx, the bb_start_cmd_va |
462 | * is only updated into ring_scan_buffer, not real ring address | 456 | * is only updated into ring_scan_buffer, not real ring address |
463 | * allocated in later copy_workload_to_ring_buffer. pls be noted | 457 | * allocated in later copy_workload_to_ring_buffer. pls be noted |
@@ -469,25 +463,53 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |||
469 | bb->bb_start_cmd_va = workload->shadow_ring_buffer_va | 463 | bb->bb_start_cmd_va = workload->shadow_ring_buffer_va |
470 | + bb->bb_offset; | 464 | + bb->bb_offset; |
471 | 465 | ||
472 | /* relocate shadow batch buffer */ | 466 | if (bb->ppgtt) { |
473 | bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); | 467 | /* for non-priv bb, scan&shadow is only for |
474 | if (gmadr_bytes == 8) | 468 | * debugging purpose, so the content of shadow bb |
475 | bb->bb_start_cmd_va[2] = 0; | 469 | * is the same as original bb. Therefore, |
470 | * here, rather than switch to shadow bb's gma | ||
471 | * address, we directly use original batch buffer's | ||
472 | * gma address, and send original bb to hardware | ||
473 | * directly | ||
474 | */ | ||
475 | if (bb->clflush & CLFLUSH_AFTER) { | ||
476 | drm_clflush_virt_range(bb->va, | ||
477 | bb->obj->base.size); | ||
478 | bb->clflush &= ~CLFLUSH_AFTER; | ||
479 | } | ||
480 | i915_gem_obj_finish_shmem_access(bb->obj); | ||
481 | bb->accessing = false; | ||
482 | |||
483 | } else { | ||
484 | bb->vma = i915_gem_object_ggtt_pin(bb->obj, | ||
485 | NULL, 0, 0, 0); | ||
486 | if (IS_ERR(bb->vma)) { | ||
487 | ret = PTR_ERR(bb->vma); | ||
488 | goto err; | ||
489 | } | ||
476 | 490 | ||
477 | /* No one is going to touch shadow bb from now on. */ | 491 | /* relocate shadow batch buffer */ |
478 | if (bb->clflush & CLFLUSH_AFTER) { | 492 | bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); |
479 | drm_clflush_virt_range(bb->va, bb->obj->base.size); | 493 | if (gmadr_bytes == 8) |
480 | bb->clflush &= ~CLFLUSH_AFTER; | 494 | bb->bb_start_cmd_va[2] = 0; |
481 | } | ||
482 | 495 | ||
483 | ret = i915_gem_object_set_to_gtt_domain(bb->obj, false); | 496 | /* No one is going to touch shadow bb from now on. */ |
484 | if (ret) | 497 | if (bb->clflush & CLFLUSH_AFTER) { |
485 | goto err; | 498 | drm_clflush_virt_range(bb->va, |
499 | bb->obj->base.size); | ||
500 | bb->clflush &= ~CLFLUSH_AFTER; | ||
501 | } | ||
486 | 502 | ||
487 | i915_gem_obj_finish_shmem_access(bb->obj); | 503 | ret = i915_gem_object_set_to_gtt_domain(bb->obj, |
488 | bb->accessing = false; | 504 | false); |
505 | if (ret) | ||
506 | goto err; | ||
489 | 507 | ||
490 | i915_vma_move_to_active(bb->vma, workload->req, 0); | 508 | i915_gem_obj_finish_shmem_access(bb->obj); |
509 | bb->accessing = false; | ||
510 | |||
511 | i915_vma_move_to_active(bb->vma, workload->req, 0); | ||
512 | } | ||
491 | } | 513 | } |
492 | return 0; | 514 | return 0; |
493 | err: | 515 | err: |
@@ -504,7 +526,7 @@ static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
504 | struct intel_vgpu_submission *s = &workload->vgpu->submission; | 526 | struct intel_vgpu_submission *s = &workload->vgpu->submission; |
505 | struct i915_gem_context *shadow_ctx = s->shadow_ctx; | 527 | struct i915_gem_context *shadow_ctx = s->shadow_ctx; |
506 | struct drm_i915_gem_object *ctx_obj = | 528 | struct drm_i915_gem_object *ctx_obj = |
507 | shadow_ctx->engine[ring_id].state->obj; | 529 | shadow_ctx->__engine[ring_id].state->obj; |
508 | struct execlist_ring_context *shadow_ring_context; | 530 | struct execlist_ring_context *shadow_ring_context; |
509 | struct page *page; | 531 | struct page *page; |
510 | 532 | ||
@@ -666,7 +688,7 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) | |||
666 | 688 | ||
667 | ret = prepare_workload(workload); | 689 | ret = prepare_workload(workload); |
668 | if (ret) { | 690 | if (ret) { |
669 | engine->context_unpin(engine, shadow_ctx); | 691 | intel_context_unpin(shadow_ctx, engine); |
670 | goto out; | 692 | goto out; |
671 | } | 693 | } |
672 | 694 | ||
@@ -749,7 +771,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) | |||
749 | struct i915_gem_context *shadow_ctx = s->shadow_ctx; | 771 | struct i915_gem_context *shadow_ctx = s->shadow_ctx; |
750 | int ring_id = workload->ring_id; | 772 | int ring_id = workload->ring_id; |
751 | struct drm_i915_gem_object *ctx_obj = | 773 | struct drm_i915_gem_object *ctx_obj = |
752 | shadow_ctx->engine[ring_id].state->obj; | 774 | shadow_ctx->__engine[ring_id].state->obj; |
753 | struct execlist_ring_context *shadow_ring_context; | 775 | struct execlist_ring_context *shadow_ring_context; |
754 | struct page *page; | 776 | struct page *page; |
755 | void *src; | 777 | void *src; |
@@ -876,7 +898,7 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id) | |||
876 | } | 898 | } |
877 | mutex_lock(&dev_priv->drm.struct_mutex); | 899 | mutex_lock(&dev_priv->drm.struct_mutex); |
878 | /* unpin shadow ctx as the shadow_ctx update is done */ | 900 | /* unpin shadow ctx as the shadow_ctx update is done */ |
879 | engine->context_unpin(engine, s->shadow_ctx); | 901 | intel_context_unpin(s->shadow_ctx, engine); |
880 | mutex_unlock(&dev_priv->drm.struct_mutex); | 902 | mutex_unlock(&dev_priv->drm.struct_mutex); |
881 | } | 903 | } |
882 | 904 | ||
@@ -1134,9 +1156,6 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) | |||
1134 | if (IS_ERR(s->shadow_ctx)) | 1156 | if (IS_ERR(s->shadow_ctx)) |
1135 | return PTR_ERR(s->shadow_ctx); | 1157 | return PTR_ERR(s->shadow_ctx); |
1136 | 1158 | ||
1137 | if (HAS_LOGICAL_RING_PREEMPTION(vgpu->gvt->dev_priv)) | ||
1138 | s->shadow_ctx->priority = INT_MAX; | ||
1139 | |||
1140 | bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); | 1159 | bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); |
1141 | 1160 | ||
1142 | s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload", | 1161 | s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload", |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 486ed57a4ad1..6c644782193e 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h | |||
@@ -125,6 +125,7 @@ struct intel_vgpu_shadow_bb { | |||
125 | unsigned int clflush; | 125 | unsigned int clflush; |
126 | bool accessing; | 126 | bool accessing; |
127 | unsigned long bb_offset; | 127 | unsigned long bb_offset; |
128 | bool ppgtt; | ||
128 | }; | 129 | }; |
129 | 130 | ||
130 | #define workload_q_head(vgpu, ring_id) \ | 131 | #define workload_q_head(vgpu, ring_id) \ |
diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h index 82093f1e8612..1fd64202d74e 100644 --- a/drivers/gpu/drm/i915/gvt/trace.h +++ b/drivers/gpu/drm/i915/gvt/trace.h | |||
@@ -224,19 +224,25 @@ TRACE_EVENT(oos_sync, | |||
224 | TP_printk("%s", __entry->buf) | 224 | TP_printk("%s", __entry->buf) |
225 | ); | 225 | ); |
226 | 226 | ||
227 | #define GVT_CMD_STR_LEN 40 | ||
227 | TRACE_EVENT(gvt_command, | 228 | TRACE_EVENT(gvt_command, |
228 | TP_PROTO(u8 vgpu_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, u32 cmd_len, | 229 | TP_PROTO(u8 vgpu_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, |
229 | u32 buf_type), | 230 | u32 cmd_len, u32 buf_type, u32 buf_addr_type, |
231 | void *workload, char *cmd_name), | ||
230 | 232 | ||
231 | TP_ARGS(vgpu_id, ring_id, ip_gma, cmd_va, cmd_len, buf_type), | 233 | TP_ARGS(vgpu_id, ring_id, ip_gma, cmd_va, cmd_len, buf_type, |
234 | buf_addr_type, workload, cmd_name), | ||
232 | 235 | ||
233 | TP_STRUCT__entry( | 236 | TP_STRUCT__entry( |
234 | __field(u8, vgpu_id) | 237 | __field(u8, vgpu_id) |
235 | __field(u8, ring_id) | 238 | __field(u8, ring_id) |
236 | __field(u32, ip_gma) | 239 | __field(u32, ip_gma) |
237 | __field(u32, buf_type) | 240 | __field(u32, buf_type) |
241 | __field(u32, buf_addr_type) | ||
238 | __field(u32, cmd_len) | 242 | __field(u32, cmd_len) |
243 | __field(void*, workload) | ||
239 | __dynamic_array(u32, raw_cmd, cmd_len) | 244 | __dynamic_array(u32, raw_cmd, cmd_len) |
245 | __array(char, cmd_name, GVT_CMD_STR_LEN) | ||
240 | ), | 246 | ), |
241 | 247 | ||
242 | TP_fast_assign( | 248 | TP_fast_assign( |
@@ -244,17 +250,25 @@ TRACE_EVENT(gvt_command, | |||
244 | __entry->ring_id = ring_id; | 250 | __entry->ring_id = ring_id; |
245 | __entry->ip_gma = ip_gma; | 251 | __entry->ip_gma = ip_gma; |
246 | __entry->buf_type = buf_type; | 252 | __entry->buf_type = buf_type; |
253 | __entry->buf_addr_type = buf_addr_type; | ||
247 | __entry->cmd_len = cmd_len; | 254 | __entry->cmd_len = cmd_len; |
255 | __entry->workload = workload; | ||
256 | snprintf(__entry->cmd_name, GVT_CMD_STR_LEN, "%s", cmd_name); | ||
248 | memcpy(__get_dynamic_array(raw_cmd), cmd_va, cmd_len * sizeof(*cmd_va)); | 257 | memcpy(__get_dynamic_array(raw_cmd), cmd_va, cmd_len * sizeof(*cmd_va)); |
249 | ), | 258 | ), |
250 | 259 | ||
251 | 260 | ||
252 | TP_printk("vgpu%d ring %d: buf_type %u, ip_gma %08x, raw cmd %s", | 261 | TP_printk("vgpu%d ring %d: address_type %u, buf_type %u, ip_gma %08x,cmd (name=%s,len=%u,raw cmd=%s), workload=%p\n", |
253 | __entry->vgpu_id, | 262 | __entry->vgpu_id, |
254 | __entry->ring_id, | 263 | __entry->ring_id, |
264 | __entry->buf_addr_type, | ||
255 | __entry->buf_type, | 265 | __entry->buf_type, |
256 | __entry->ip_gma, | 266 | __entry->ip_gma, |
257 | __print_array(__get_dynamic_array(raw_cmd), __entry->cmd_len, 4)) | 267 | __entry->cmd_name, |
268 | __entry->cmd_len, | ||
269 | __print_array(__get_dynamic_array(raw_cmd), | ||
270 | __entry->cmd_len, 4), | ||
271 | __entry->workload) | ||
258 | ); | 272 | ); |
259 | 273 | ||
260 | #define GVT_TEMP_STR_LEN 10 | 274 | #define GVT_TEMP_STR_LEN 10 |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 2e6652a9bb9e..13e7b9e4a6e6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -377,16 +377,19 @@ static void print_batch_pool_stats(struct seq_file *m, | |||
377 | print_file_stats(m, "[k]batch pool", stats); | 377 | print_file_stats(m, "[k]batch pool", stats); |
378 | } | 378 | } |
379 | 379 | ||
380 | static int per_file_ctx_stats(int id, void *ptr, void *data) | 380 | static int per_file_ctx_stats(int idx, void *ptr, void *data) |
381 | { | 381 | { |
382 | struct i915_gem_context *ctx = ptr; | 382 | struct i915_gem_context *ctx = ptr; |
383 | int n; | 383 | struct intel_engine_cs *engine; |
384 | enum intel_engine_id id; | ||
385 | |||
386 | for_each_engine(engine, ctx->i915, id) { | ||
387 | struct intel_context *ce = to_intel_context(ctx, engine); | ||
384 | 388 | ||
385 | for (n = 0; n < ARRAY_SIZE(ctx->engine); n++) { | 389 | if (ce->state) |
386 | if (ctx->engine[n].state) | 390 | per_file_stats(0, ce->state->obj, data); |
387 | per_file_stats(0, ctx->engine[n].state->obj, data); | 391 | if (ce->ring) |
388 | if (ctx->engine[n].ring) | 392 | per_file_stats(0, ce->ring->vma->obj, data); |
389 | per_file_stats(0, ctx->engine[n].ring->vma->obj, data); | ||
390 | } | 393 | } |
391 | 394 | ||
392 | return 0; | 395 | return 0; |
@@ -1340,10 +1343,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) | |||
1340 | struct rb_node *rb; | 1343 | struct rb_node *rb; |
1341 | 1344 | ||
1342 | seq_printf(m, "%s:\n", engine->name); | 1345 | seq_printf(m, "%s:\n", engine->name); |
1343 | seq_printf(m, "\tseqno = %x [current %x, last %x], inflight %d\n", | 1346 | seq_printf(m, "\tseqno = %x [current %x, last %x]\n", |
1344 | engine->hangcheck.seqno, seqno[id], | 1347 | engine->hangcheck.seqno, seqno[id], |
1345 | intel_engine_last_submit(engine), | 1348 | intel_engine_last_submit(engine)); |
1346 | engine->timeline->inflight_seqnos); | ||
1347 | seq_printf(m, "\twaiters? %s, fake irq active? %s, stalled? %s\n", | 1349 | seq_printf(m, "\twaiters? %s, fake irq active? %s, stalled? %s\n", |
1348 | yesno(intel_engine_has_waiter(engine)), | 1350 | yesno(intel_engine_has_waiter(engine)), |
1349 | yesno(test_bit(engine->id, | 1351 | yesno(test_bit(engine->id, |
@@ -1960,7 +1962,8 @@ static int i915_context_status(struct seq_file *m, void *unused) | |||
1960 | seq_putc(m, '\n'); | 1962 | seq_putc(m, '\n'); |
1961 | 1963 | ||
1962 | for_each_engine(engine, dev_priv, id) { | 1964 | for_each_engine(engine, dev_priv, id) { |
1963 | struct intel_context *ce = &ctx->engine[engine->id]; | 1965 | struct intel_context *ce = |
1966 | to_intel_context(ctx, engine); | ||
1964 | 1967 | ||
1965 | seq_printf(m, "%s: ", engine->name); | 1968 | seq_printf(m, "%s: ", engine->name); |
1966 | if (ce->state) | 1969 | if (ce->state) |
@@ -2603,6 +2606,26 @@ static const char *psr2_live_status(u32 val) | |||
2603 | return "unknown"; | 2606 | return "unknown"; |
2604 | } | 2607 | } |
2605 | 2608 | ||
2609 | static const char *psr_sink_status(u8 val) | ||
2610 | { | ||
2611 | static const char * const sink_status[] = { | ||
2612 | "inactive", | ||
2613 | "transition to active, capture and display", | ||
2614 | "active, display from RFB", | ||
2615 | "active, capture and display on sink device timings", | ||
2616 | "transition to inactive, capture and display, timing re-sync", | ||
2617 | "reserved", | ||
2618 | "reserved", | ||
2619 | "sink internal error" | ||
2620 | }; | ||
2621 | |||
2622 | val &= DP_PSR_SINK_STATE_MASK; | ||
2623 | if (val < ARRAY_SIZE(sink_status)) | ||
2624 | return sink_status[val]; | ||
2625 | |||
2626 | return "unknown"; | ||
2627 | } | ||
2628 | |||
2606 | static int i915_edp_psr_status(struct seq_file *m, void *data) | 2629 | static int i915_edp_psr_status(struct seq_file *m, void *data) |
2607 | { | 2630 | { |
2608 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 2631 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
@@ -2684,12 +2707,61 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) | |||
2684 | seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", | 2707 | seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n", |
2685 | psr2, psr2_live_status(psr2)); | 2708 | psr2, psr2_live_status(psr2)); |
2686 | } | 2709 | } |
2710 | |||
2711 | if (dev_priv->psr.enabled) { | ||
2712 | struct drm_dp_aux *aux = &dev_priv->psr.enabled->aux; | ||
2713 | u8 val; | ||
2714 | |||
2715 | if (drm_dp_dpcd_readb(aux, DP_PSR_STATUS, &val) == 1) | ||
2716 | seq_printf(m, "Sink PSR status: 0x%x [%s]\n", val, | ||
2717 | psr_sink_status(val)); | ||
2718 | } | ||
2687 | mutex_unlock(&dev_priv->psr.lock); | 2719 | mutex_unlock(&dev_priv->psr.lock); |
2688 | 2720 | ||
2721 | if (READ_ONCE(dev_priv->psr.debug)) { | ||
2722 | seq_printf(m, "Last attempted entry at: %lld\n", | ||
2723 | dev_priv->psr.last_entry_attempt); | ||
2724 | seq_printf(m, "Last exit at: %lld\n", | ||
2725 | dev_priv->psr.last_exit); | ||
2726 | } | ||
2727 | |||
2728 | intel_runtime_pm_put(dev_priv); | ||
2729 | return 0; | ||
2730 | } | ||
2731 | |||
2732 | static int | ||
2733 | i915_edp_psr_debug_set(void *data, u64 val) | ||
2734 | { | ||
2735 | struct drm_i915_private *dev_priv = data; | ||
2736 | |||
2737 | if (!CAN_PSR(dev_priv)) | ||
2738 | return -ENODEV; | ||
2739 | |||
2740 | DRM_DEBUG_KMS("PSR debug %s\n", enableddisabled(val)); | ||
2741 | |||
2742 | intel_runtime_pm_get(dev_priv); | ||
2743 | intel_psr_irq_control(dev_priv, !!val); | ||
2689 | intel_runtime_pm_put(dev_priv); | 2744 | intel_runtime_pm_put(dev_priv); |
2745 | |||
2690 | return 0; | 2746 | return 0; |
2691 | } | 2747 | } |
2692 | 2748 | ||
2749 | static int | ||
2750 | i915_edp_psr_debug_get(void *data, u64 *val) | ||
2751 | { | ||
2752 | struct drm_i915_private *dev_priv = data; | ||
2753 | |||
2754 | if (!CAN_PSR(dev_priv)) | ||
2755 | return -ENODEV; | ||
2756 | |||
2757 | *val = READ_ONCE(dev_priv->psr.debug); | ||
2758 | return 0; | ||
2759 | } | ||
2760 | |||
2761 | DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops, | ||
2762 | i915_edp_psr_debug_get, i915_edp_psr_debug_set, | ||
2763 | "%llu\n"); | ||
2764 | |||
2693 | static int i915_sink_crc(struct seq_file *m, void *data) | 2765 | static int i915_sink_crc(struct seq_file *m, void *data) |
2694 | { | 2766 | { |
2695 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 2767 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
@@ -3296,6 +3368,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) | |||
3296 | seq_printf(m, " fp0: 0x%08x\n", pll->state.hw_state.fp0); | 3368 | seq_printf(m, " fp0: 0x%08x\n", pll->state.hw_state.fp0); |
3297 | seq_printf(m, " fp1: 0x%08x\n", pll->state.hw_state.fp1); | 3369 | seq_printf(m, " fp1: 0x%08x\n", pll->state.hw_state.fp1); |
3298 | seq_printf(m, " wrpll: 0x%08x\n", pll->state.hw_state.wrpll); | 3370 | seq_printf(m, " wrpll: 0x%08x\n", pll->state.hw_state.wrpll); |
3371 | seq_printf(m, " cfgcr0: 0x%08x\n", pll->state.hw_state.cfgcr0); | ||
3372 | seq_printf(m, " cfgcr1: 0x%08x\n", pll->state.hw_state.cfgcr1); | ||
3373 | seq_printf(m, " mg_refclkin_ctl: 0x%08x\n", | ||
3374 | pll->state.hw_state.mg_refclkin_ctl); | ||
3375 | seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n", | ||
3376 | pll->state.hw_state.mg_clktop2_coreclkctl1); | ||
3377 | seq_printf(m, " mg_clktop2_hsclkctl: 0x%08x\n", | ||
3378 | pll->state.hw_state.mg_clktop2_hsclkctl); | ||
3379 | seq_printf(m, " mg_pll_div0: 0x%08x\n", | ||
3380 | pll->state.hw_state.mg_pll_div0); | ||
3381 | seq_printf(m, " mg_pll_div1: 0x%08x\n", | ||
3382 | pll->state.hw_state.mg_pll_div1); | ||
3383 | seq_printf(m, " mg_pll_lf: 0x%08x\n", | ||
3384 | pll->state.hw_state.mg_pll_lf); | ||
3385 | seq_printf(m, " mg_pll_frac_lock: 0x%08x\n", | ||
3386 | pll->state.hw_state.mg_pll_frac_lock); | ||
3387 | seq_printf(m, " mg_pll_ssc: 0x%08x\n", | ||
3388 | pll->state.hw_state.mg_pll_ssc); | ||
3389 | seq_printf(m, " mg_pll_bias: 0x%08x\n", | ||
3390 | pll->state.hw_state.mg_pll_bias); | ||
3391 | seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n", | ||
3392 | pll->state.hw_state.mg_pll_tdc_coldst_bias); | ||
3299 | } | 3393 | } |
3300 | drm_modeset_unlock_all(dev); | 3394 | drm_modeset_unlock_all(dev); |
3301 | 3395 | ||
@@ -3304,24 +3398,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) | |||
3304 | 3398 | ||
3305 | static int i915_wa_registers(struct seq_file *m, void *unused) | 3399 | static int i915_wa_registers(struct seq_file *m, void *unused) |
3306 | { | 3400 | { |
3307 | int i; | ||
3308 | int ret; | ||
3309 | struct intel_engine_cs *engine; | ||
3310 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 3401 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
3311 | struct drm_device *dev = &dev_priv->drm; | ||
3312 | struct i915_workarounds *workarounds = &dev_priv->workarounds; | 3402 | struct i915_workarounds *workarounds = &dev_priv->workarounds; |
3313 | enum intel_engine_id id; | 3403 | int i; |
3314 | |||
3315 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
3316 | if (ret) | ||
3317 | return ret; | ||
3318 | 3404 | ||
3319 | intel_runtime_pm_get(dev_priv); | 3405 | intel_runtime_pm_get(dev_priv); |
3320 | 3406 | ||
3321 | seq_printf(m, "Workarounds applied: %d\n", workarounds->count); | 3407 | seq_printf(m, "Workarounds applied: %d\n", workarounds->count); |
3322 | for_each_engine(engine, dev_priv, id) | ||
3323 | seq_printf(m, "HW whitelist count for %s: %d\n", | ||
3324 | engine->name, workarounds->hw_whitelist_count[id]); | ||
3325 | for (i = 0; i < workarounds->count; ++i) { | 3408 | for (i = 0; i < workarounds->count; ++i) { |
3326 | i915_reg_t addr; | 3409 | i915_reg_t addr; |
3327 | u32 mask, value, read; | 3410 | u32 mask, value, read; |
@@ -3337,7 +3420,6 @@ static int i915_wa_registers(struct seq_file *m, void *unused) | |||
3337 | } | 3420 | } |
3338 | 3421 | ||
3339 | intel_runtime_pm_put(dev_priv); | 3422 | intel_runtime_pm_put(dev_priv); |
3340 | mutex_unlock(&dev->struct_mutex); | ||
3341 | 3423 | ||
3342 | return 0; | 3424 | return 0; |
3343 | } | 3425 | } |
@@ -4177,119 +4259,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops, | |||
4177 | "0x%08llx\n"); | 4259 | "0x%08llx\n"); |
4178 | 4260 | ||
4179 | static int | 4261 | static int |
4180 | i915_max_freq_get(void *data, u64 *val) | ||
4181 | { | ||
4182 | struct drm_i915_private *dev_priv = data; | ||
4183 | |||
4184 | if (INTEL_GEN(dev_priv) < 6) | ||
4185 | return -ENODEV; | ||
4186 | |||
4187 | *val = intel_gpu_freq(dev_priv, dev_priv->gt_pm.rps.max_freq_softlimit); | ||
4188 | return 0; | ||
4189 | } | ||
4190 | |||
4191 | static int | ||
4192 | i915_max_freq_set(void *data, u64 val) | ||
4193 | { | ||
4194 | struct drm_i915_private *dev_priv = data; | ||
4195 | struct intel_rps *rps = &dev_priv->gt_pm.rps; | ||
4196 | u32 hw_max, hw_min; | ||
4197 | int ret; | ||
4198 | |||
4199 | if (INTEL_GEN(dev_priv) < 6) | ||
4200 | return -ENODEV; | ||
4201 | |||
4202 | DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val); | ||
4203 | |||
4204 | ret = mutex_lock_interruptible(&dev_priv->pcu_lock); | ||
4205 | if (ret) | ||
4206 | return ret; | ||
4207 | |||
4208 | /* | ||
4209 | * Turbo will still be enabled, but won't go above the set value. | ||
4210 | */ | ||
4211 | val = intel_freq_opcode(dev_priv, val); | ||
4212 | |||
4213 | hw_max = rps->max_freq; | ||
4214 | hw_min = rps->min_freq; | ||
4215 | |||
4216 | if (val < hw_min || val > hw_max || val < rps->min_freq_softlimit) { | ||
4217 | mutex_unlock(&dev_priv->pcu_lock); | ||
4218 | return -EINVAL; | ||
4219 | } | ||
4220 | |||
4221 | rps->max_freq_softlimit = val; | ||
4222 | |||
4223 | if (intel_set_rps(dev_priv, val)) | ||
4224 | DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n"); | ||
4225 | |||
4226 | mutex_unlock(&dev_priv->pcu_lock); | ||
4227 | |||
4228 | return 0; | ||
4229 | } | ||
4230 | |||
4231 | DEFINE_SIMPLE_ATTRIBUTE(i915_max_freq_fops, | ||
4232 | i915_max_freq_get, i915_max_freq_set, | ||
4233 | "%llu\n"); | ||
4234 | |||
4235 | static int | ||
4236 | i915_min_freq_get(void *data, u64 *val) | ||
4237 | { | ||
4238 | struct drm_i915_private *dev_priv = data; | ||
4239 | |||
4240 | if (INTEL_GEN(dev_priv) < 6) | ||
4241 | return -ENODEV; | ||
4242 | |||
4243 | *val = intel_gpu_freq(dev_priv, dev_priv->gt_pm.rps.min_freq_softlimit); | ||
4244 | return 0; | ||
4245 | } | ||
4246 | |||
4247 | static int | ||
4248 | i915_min_freq_set(void *data, u64 val) | ||
4249 | { | ||
4250 | struct drm_i915_private *dev_priv = data; | ||
4251 | struct intel_rps *rps = &dev_priv->gt_pm.rps; | ||
4252 | u32 hw_max, hw_min; | ||
4253 | int ret; | ||
4254 | |||
4255 | if (INTEL_GEN(dev_priv) < 6) | ||
4256 | return -ENODEV; | ||
4257 | |||
4258 | DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val); | ||
4259 | |||
4260 | ret = mutex_lock_interruptible(&dev_priv->pcu_lock); | ||
4261 | if (ret) | ||
4262 | return ret; | ||
4263 | |||
4264 | /* | ||
4265 | * Turbo will still be enabled, but won't go below the set value. | ||
4266 | */ | ||
4267 | val = intel_freq_opcode(dev_priv, val); | ||
4268 | |||
4269 | hw_max = rps->max_freq; | ||
4270 | hw_min = rps->min_freq; | ||
4271 | |||
4272 | if (val < hw_min || | ||
4273 | val > hw_max || val > rps->max_freq_softlimit) { | ||
4274 | mutex_unlock(&dev_priv->pcu_lock); | ||
4275 | return -EINVAL; | ||
4276 | } | ||
4277 | |||
4278 | rps->min_freq_softlimit = val; | ||
4279 | |||
4280 | if (intel_set_rps(dev_priv, val)) | ||
4281 | DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n"); | ||
4282 | |||
4283 | mutex_unlock(&dev_priv->pcu_lock); | ||
4284 | |||
4285 | return 0; | ||
4286 | } | ||
4287 | |||
4288 | DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops, | ||
4289 | i915_min_freq_get, i915_min_freq_set, | ||
4290 | "%llu\n"); | ||
4291 | |||
4292 | static int | ||
4293 | i915_cache_sharing_get(void *data, u64 *val) | 4262 | i915_cache_sharing_get(void *data, u64 *val) |
4294 | { | 4263 | { |
4295 | struct drm_i915_private *dev_priv = data; | 4264 | struct drm_i915_private *dev_priv = data; |
@@ -4850,8 +4819,6 @@ static const struct i915_debugfs_files { | |||
4850 | const struct file_operations *fops; | 4819 | const struct file_operations *fops; |
4851 | } i915_debugfs_files[] = { | 4820 | } i915_debugfs_files[] = { |
4852 | {"i915_wedged", &i915_wedged_fops}, | 4821 | {"i915_wedged", &i915_wedged_fops}, |
4853 | {"i915_max_freq", &i915_max_freq_fops}, | ||
4854 | {"i915_min_freq", &i915_min_freq_fops}, | ||
4855 | {"i915_cache_sharing", &i915_cache_sharing_fops}, | 4822 | {"i915_cache_sharing", &i915_cache_sharing_fops}, |
4856 | {"i915_ring_missed_irq", &i915_ring_missed_irq_fops}, | 4823 | {"i915_ring_missed_irq", &i915_ring_missed_irq_fops}, |
4857 | {"i915_ring_test_irq", &i915_ring_test_irq_fops}, | 4824 | {"i915_ring_test_irq", &i915_ring_test_irq_fops}, |
@@ -4874,7 +4841,8 @@ static const struct i915_debugfs_files { | |||
4874 | {"i915_guc_log_relay", &i915_guc_log_relay_fops}, | 4841 | {"i915_guc_log_relay", &i915_guc_log_relay_fops}, |
4875 | {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, | 4842 | {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, |
4876 | {"i915_ipc_status", &i915_ipc_status_fops}, | 4843 | {"i915_ipc_status", &i915_ipc_status_fops}, |
4877 | {"i915_drrs_ctl", &i915_drrs_ctl_fops} | 4844 | {"i915_drrs_ctl", &i915_drrs_ctl_fops}, |
4845 | {"i915_edp_psr_debug", &i915_edp_psr_debug_fops} | ||
4878 | }; | 4846 | }; |
4879 | 4847 | ||
4880 | int i915_debugfs_register(struct drm_i915_private *dev_priv) | 4848 | int i915_debugfs_register(struct drm_i915_private *dev_priv) |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c471a7528a50..9c449b8d8eab 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -101,7 +101,13 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, | |||
101 | __builtin_return_address(0), &vaf); | 101 | __builtin_return_address(0), &vaf); |
102 | 102 | ||
103 | if (is_error && !shown_bug_once) { | 103 | if (is_error && !shown_bug_once) { |
104 | dev_notice(kdev, "%s", FDO_BUG_MSG); | 104 | /* |
105 | * Ask the user to file a bug report for the error, except | ||
106 | * if they may have caused the bug by fiddling with unsafe | ||
107 | * module parameters. | ||
108 | */ | ||
109 | if (!test_taint(TAINT_USER)) | ||
110 | dev_notice(kdev, "%s", FDO_BUG_MSG); | ||
105 | shown_bug_once = true; | 111 | shown_bug_once = true; |
106 | } | 112 | } |
107 | 113 | ||
@@ -2468,10 +2474,13 @@ static void vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, | |||
2468 | /* | 2474 | /* |
2469 | * RC6 transitioning can be delayed up to 2 msec (see | 2475 | * RC6 transitioning can be delayed up to 2 msec (see |
2470 | * valleyview_enable_rps), use 3 msec for safety. | 2476 | * valleyview_enable_rps), use 3 msec for safety. |
2477 | * | ||
2478 | * This can fail to turn off the rc6 if the GPU is stuck after a failed | ||
2479 | * reset and we are trying to force the machine to sleep. | ||
2471 | */ | 2480 | */ |
2472 | if (vlv_wait_for_pw_status(dev_priv, mask, val)) | 2481 | if (vlv_wait_for_pw_status(dev_priv, mask, val)) |
2473 | DRM_ERROR("timeout waiting for GT wells to go %s\n", | 2482 | DRM_DEBUG_DRIVER("timeout waiting for GT wells to go %s\n", |
2474 | onoff(wait_for_on)); | 2483 | onoff(wait_for_on)); |
2475 | } | 2484 | } |
2476 | 2485 | ||
2477 | static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv) | 2486 | static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e50d9589d6e3..34c125e2d90c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -72,9 +72,10 @@ | |||
72 | #include "i915_gem_fence_reg.h" | 72 | #include "i915_gem_fence_reg.h" |
73 | #include "i915_gem_object.h" | 73 | #include "i915_gem_object.h" |
74 | #include "i915_gem_gtt.h" | 74 | #include "i915_gem_gtt.h" |
75 | #include "i915_gem_timeline.h" | ||
76 | #include "i915_gpu_error.h" | 75 | #include "i915_gpu_error.h" |
77 | #include "i915_request.h" | 76 | #include "i915_request.h" |
77 | #include "i915_scheduler.h" | ||
78 | #include "i915_timeline.h" | ||
78 | #include "i915_vma.h" | 79 | #include "i915_vma.h" |
79 | 80 | ||
80 | #include "intel_gvt.h" | 81 | #include "intel_gvt.h" |
@@ -84,8 +85,8 @@ | |||
84 | 85 | ||
85 | #define DRIVER_NAME "i915" | 86 | #define DRIVER_NAME "i915" |
86 | #define DRIVER_DESC "Intel Graphics" | 87 | #define DRIVER_DESC "Intel Graphics" |
87 | #define DRIVER_DATE "20180413" | 88 | #define DRIVER_DATE "20180514" |
88 | #define DRIVER_TIMESTAMP 1523611258 | 89 | #define DRIVER_TIMESTAMP 1526300884 |
89 | 90 | ||
90 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and | 91 | /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and |
91 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions | 92 | * WARN_ON()) for hw state sanity checks to check for unexpected conditions |
@@ -609,6 +610,9 @@ struct i915_psr { | |||
609 | bool has_hw_tracking; | 610 | bool has_hw_tracking; |
610 | bool psr2_enabled; | 611 | bool psr2_enabled; |
611 | u8 sink_sync_latency; | 612 | u8 sink_sync_latency; |
613 | bool debug; | ||
614 | ktime_t last_entry_attempt; | ||
615 | ktime_t last_exit; | ||
612 | 616 | ||
613 | void (*enable_source)(struct intel_dp *, | 617 | void (*enable_source)(struct intel_dp *, |
614 | const struct intel_crtc_state *); | 618 | const struct intel_crtc_state *); |
@@ -1069,6 +1073,7 @@ struct intel_vbt_data { | |||
1069 | } edp; | 1073 | } edp; |
1070 | 1074 | ||
1071 | struct { | 1075 | struct { |
1076 | bool enable; | ||
1072 | bool full_link; | 1077 | bool full_link; |
1073 | bool require_aux_wakeup; | 1078 | bool require_aux_wakeup; |
1074 | int idle_frames; | 1079 | int idle_frames; |
@@ -1185,6 +1190,7 @@ struct skl_ddb_allocation { | |||
1185 | /* packed/y */ | 1190 | /* packed/y */ |
1186 | struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; | 1191 | struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; |
1187 | struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES]; | 1192 | struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES]; |
1193 | u8 enabled_slices; /* GEN11 has configurable 2 slices */ | ||
1188 | }; | 1194 | }; |
1189 | 1195 | ||
1190 | struct skl_ddb_values { | 1196 | struct skl_ddb_values { |
@@ -1297,7 +1303,6 @@ struct i915_wa_reg { | |||
1297 | struct i915_workarounds { | 1303 | struct i915_workarounds { |
1298 | struct i915_wa_reg reg[I915_MAX_WA_REGS]; | 1304 | struct i915_wa_reg reg[I915_MAX_WA_REGS]; |
1299 | u32 count; | 1305 | u32 count; |
1300 | u32 hw_whitelist_count[I915_NUM_ENGINES]; | ||
1301 | }; | 1306 | }; |
1302 | 1307 | ||
1303 | struct i915_virtual_gpu { | 1308 | struct i915_virtual_gpu { |
@@ -2056,8 +2061,11 @@ struct drm_i915_private { | |||
2056 | void (*cleanup_engine)(struct intel_engine_cs *engine); | 2061 | void (*cleanup_engine)(struct intel_engine_cs *engine); |
2057 | 2062 | ||
2058 | struct list_head timelines; | 2063 | struct list_head timelines; |
2059 | struct i915_gem_timeline global_timeline; | 2064 | |
2065 | struct list_head active_rings; | ||
2066 | struct list_head closed_vma; | ||
2060 | u32 active_requests; | 2067 | u32 active_requests; |
2068 | u32 request_serial; | ||
2061 | 2069 | ||
2062 | /** | 2070 | /** |
2063 | * Is the GPU currently considered idle, or busy executing | 2071 | * Is the GPU currently considered idle, or busy executing |
@@ -2462,6 +2470,15 @@ intel_info(const struct drm_i915_private *dev_priv) | |||
2462 | #define IS_CNL_REVID(p, since, until) \ | 2470 | #define IS_CNL_REVID(p, since, until) \ |
2463 | (IS_CANNONLAKE(p) && IS_REVID(p, since, until)) | 2471 | (IS_CANNONLAKE(p) && IS_REVID(p, since, until)) |
2464 | 2472 | ||
2473 | #define ICL_REVID_A0 0x0 | ||
2474 | #define ICL_REVID_A2 0x1 | ||
2475 | #define ICL_REVID_B0 0x3 | ||
2476 | #define ICL_REVID_B2 0x4 | ||
2477 | #define ICL_REVID_C0 0x5 | ||
2478 | |||
2479 | #define IS_ICL_REVID(p, since, until) \ | ||
2480 | (IS_ICELAKE(p) && IS_REVID(p, since, until)) | ||
2481 | |||
2465 | /* | 2482 | /* |
2466 | * The genX designation typically refers to the render engine, so render | 2483 | * The genX designation typically refers to the render engine, so render |
2467 | * capability related checks should use IS_GEN, while display and other checks | 2484 | * capability related checks should use IS_GEN, while display and other checks |
@@ -3159,7 +3176,7 @@ int i915_gem_object_wait(struct drm_i915_gem_object *obj, | |||
3159 | struct intel_rps_client *rps); | 3176 | struct intel_rps_client *rps); |
3160 | int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, | 3177 | int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, |
3161 | unsigned int flags, | 3178 | unsigned int flags, |
3162 | int priority); | 3179 | const struct i915_sched_attr *attr); |
3163 | #define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX | 3180 | #define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX |
3164 | 3181 | ||
3165 | int __must_check | 3182 | int __must_check |
@@ -3228,16 +3245,6 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id) | |||
3228 | return ctx; | 3245 | return ctx; |
3229 | } | 3246 | } |
3230 | 3247 | ||
3231 | static inline struct intel_timeline * | ||
3232 | i915_gem_context_lookup_timeline(struct i915_gem_context *ctx, | ||
3233 | struct intel_engine_cs *engine) | ||
3234 | { | ||
3235 | struct i915_address_space *vm; | ||
3236 | |||
3237 | vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base; | ||
3238 | return &vm->timeline.engine[engine->id]; | ||
3239 | } | ||
3240 | |||
3241 | int i915_perf_open_ioctl(struct drm_device *dev, void *data, | 3248 | int i915_perf_open_ioctl(struct drm_device *dev, void *data, |
3242 | struct drm_file *file); | 3249 | struct drm_file *file); |
3243 | int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, | 3250 | int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4c9d2a6f7d28..0a2070112b66 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -141,6 +141,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915) | |||
141 | { | 141 | { |
142 | lockdep_assert_held(&i915->drm.struct_mutex); | 142 | lockdep_assert_held(&i915->drm.struct_mutex); |
143 | GEM_BUG_ON(i915->gt.active_requests); | 143 | GEM_BUG_ON(i915->gt.active_requests); |
144 | GEM_BUG_ON(!list_empty(&i915->gt.active_rings)); | ||
144 | 145 | ||
145 | if (!i915->gt.awake) | 146 | if (!i915->gt.awake) |
146 | return I915_EPOCH_INVALID; | 147 | return I915_EPOCH_INVALID; |
@@ -161,9 +162,10 @@ static u32 __i915_gem_park(struct drm_i915_private *i915) | |||
161 | synchronize_irq(i915->drm.irq); | 162 | synchronize_irq(i915->drm.irq); |
162 | 163 | ||
163 | intel_engines_park(i915); | 164 | intel_engines_park(i915); |
164 | i915_gem_timelines_park(i915); | 165 | i915_timelines_park(i915); |
165 | 166 | ||
166 | i915_pmu_gt_parked(i915); | 167 | i915_pmu_gt_parked(i915); |
168 | i915_vma_parked(i915); | ||
167 | 169 | ||
168 | i915->gt.awake = false; | 170 | i915->gt.awake = false; |
169 | 171 | ||
@@ -564,7 +566,8 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, | |||
564 | return timeout; | 566 | return timeout; |
565 | } | 567 | } |
566 | 568 | ||
567 | static void __fence_set_priority(struct dma_fence *fence, int prio) | 569 | static void __fence_set_priority(struct dma_fence *fence, |
570 | const struct i915_sched_attr *attr) | ||
568 | { | 571 | { |
569 | struct i915_request *rq; | 572 | struct i915_request *rq; |
570 | struct intel_engine_cs *engine; | 573 | struct intel_engine_cs *engine; |
@@ -575,13 +578,16 @@ static void __fence_set_priority(struct dma_fence *fence, int prio) | |||
575 | rq = to_request(fence); | 578 | rq = to_request(fence); |
576 | engine = rq->engine; | 579 | engine = rq->engine; |
577 | 580 | ||
578 | rcu_read_lock(); | 581 | local_bh_disable(); |
582 | rcu_read_lock(); /* RCU serialisation for set-wedged protection */ | ||
579 | if (engine->schedule) | 583 | if (engine->schedule) |
580 | engine->schedule(rq, prio); | 584 | engine->schedule(rq, attr); |
581 | rcu_read_unlock(); | 585 | rcu_read_unlock(); |
586 | local_bh_enable(); /* kick the tasklets if queues were reprioritised */ | ||
582 | } | 587 | } |
583 | 588 | ||
584 | static void fence_set_priority(struct dma_fence *fence, int prio) | 589 | static void fence_set_priority(struct dma_fence *fence, |
590 | const struct i915_sched_attr *attr) | ||
585 | { | 591 | { |
586 | /* Recurse once into a fence-array */ | 592 | /* Recurse once into a fence-array */ |
587 | if (dma_fence_is_array(fence)) { | 593 | if (dma_fence_is_array(fence)) { |
@@ -589,16 +595,16 @@ static void fence_set_priority(struct dma_fence *fence, int prio) | |||
589 | int i; | 595 | int i; |
590 | 596 | ||
591 | for (i = 0; i < array->num_fences; i++) | 597 | for (i = 0; i < array->num_fences; i++) |
592 | __fence_set_priority(array->fences[i], prio); | 598 | __fence_set_priority(array->fences[i], attr); |
593 | } else { | 599 | } else { |
594 | __fence_set_priority(fence, prio); | 600 | __fence_set_priority(fence, attr); |
595 | } | 601 | } |
596 | } | 602 | } |
597 | 603 | ||
598 | int | 604 | int |
599 | i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, | 605 | i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, |
600 | unsigned int flags, | 606 | unsigned int flags, |
601 | int prio) | 607 | const struct i915_sched_attr *attr) |
602 | { | 608 | { |
603 | struct dma_fence *excl; | 609 | struct dma_fence *excl; |
604 | 610 | ||
@@ -613,7 +619,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, | |||
613 | return ret; | 619 | return ret; |
614 | 620 | ||
615 | for (i = 0; i < count; i++) { | 621 | for (i = 0; i < count; i++) { |
616 | fence_set_priority(shared[i], prio); | 622 | fence_set_priority(shared[i], attr); |
617 | dma_fence_put(shared[i]); | 623 | dma_fence_put(shared[i]); |
618 | } | 624 | } |
619 | 625 | ||
@@ -623,7 +629,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, | |||
623 | } | 629 | } |
624 | 630 | ||
625 | if (excl) { | 631 | if (excl) { |
626 | fence_set_priority(excl, prio); | 632 | fence_set_priority(excl, attr); |
627 | dma_fence_put(excl); | 633 | dma_fence_put(excl); |
628 | } | 634 | } |
629 | return 0; | 635 | return 0; |
@@ -2974,8 +2980,8 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) | |||
2974 | * extra delay for a recent interrupt is pointless. Hence, we do | 2980 | * extra delay for a recent interrupt is pointless. Hence, we do |
2975 | * not need an engine->irq_seqno_barrier() before the seqno reads. | 2981 | * not need an engine->irq_seqno_barrier() before the seqno reads. |
2976 | */ | 2982 | */ |
2977 | spin_lock_irqsave(&engine->timeline->lock, flags); | 2983 | spin_lock_irqsave(&engine->timeline.lock, flags); |
2978 | list_for_each_entry(request, &engine->timeline->requests, link) { | 2984 | list_for_each_entry(request, &engine->timeline.requests, link) { |
2979 | if (__i915_request_completed(request, request->global_seqno)) | 2985 | if (__i915_request_completed(request, request->global_seqno)) |
2980 | continue; | 2986 | continue; |
2981 | 2987 | ||
@@ -2986,7 +2992,7 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) | |||
2986 | active = request; | 2992 | active = request; |
2987 | break; | 2993 | break; |
2988 | } | 2994 | } |
2989 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 2995 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
2990 | 2996 | ||
2991 | return active; | 2997 | return active; |
2992 | } | 2998 | } |
@@ -3107,15 +3113,15 @@ static void engine_skip_context(struct i915_request *request) | |||
3107 | { | 3113 | { |
3108 | struct intel_engine_cs *engine = request->engine; | 3114 | struct intel_engine_cs *engine = request->engine; |
3109 | struct i915_gem_context *hung_ctx = request->ctx; | 3115 | struct i915_gem_context *hung_ctx = request->ctx; |
3110 | struct intel_timeline *timeline; | 3116 | struct i915_timeline *timeline = request->timeline; |
3111 | unsigned long flags; | 3117 | unsigned long flags; |
3112 | 3118 | ||
3113 | timeline = i915_gem_context_lookup_timeline(hung_ctx, engine); | 3119 | GEM_BUG_ON(timeline == &engine->timeline); |
3114 | 3120 | ||
3115 | spin_lock_irqsave(&engine->timeline->lock, flags); | 3121 | spin_lock_irqsave(&engine->timeline.lock, flags); |
3116 | spin_lock(&timeline->lock); | 3122 | spin_lock_nested(&timeline->lock, SINGLE_DEPTH_NESTING); |
3117 | 3123 | ||
3118 | list_for_each_entry_continue(request, &engine->timeline->requests, link) | 3124 | list_for_each_entry_continue(request, &engine->timeline.requests, link) |
3119 | if (request->ctx == hung_ctx) | 3125 | if (request->ctx == hung_ctx) |
3120 | skip_request(request); | 3126 | skip_request(request); |
3121 | 3127 | ||
@@ -3123,7 +3129,7 @@ static void engine_skip_context(struct i915_request *request) | |||
3123 | skip_request(request); | 3129 | skip_request(request); |
3124 | 3130 | ||
3125 | spin_unlock(&timeline->lock); | 3131 | spin_unlock(&timeline->lock); |
3126 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 3132 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
3127 | } | 3133 | } |
3128 | 3134 | ||
3129 | /* Returns the request if it was guilty of the hang */ | 3135 | /* Returns the request if it was guilty of the hang */ |
@@ -3180,11 +3186,11 @@ i915_gem_reset_request(struct intel_engine_cs *engine, | |||
3180 | dma_fence_set_error(&request->fence, -EAGAIN); | 3186 | dma_fence_set_error(&request->fence, -EAGAIN); |
3181 | 3187 | ||
3182 | /* Rewind the engine to replay the incomplete rq */ | 3188 | /* Rewind the engine to replay the incomplete rq */ |
3183 | spin_lock_irq(&engine->timeline->lock); | 3189 | spin_lock_irq(&engine->timeline.lock); |
3184 | request = list_prev_entry(request, link); | 3190 | request = list_prev_entry(request, link); |
3185 | if (&request->link == &engine->timeline->requests) | 3191 | if (&request->link == &engine->timeline.requests) |
3186 | request = NULL; | 3192 | request = NULL; |
3187 | spin_unlock_irq(&engine->timeline->lock); | 3193 | spin_unlock_irq(&engine->timeline.lock); |
3188 | } | 3194 | } |
3189 | } | 3195 | } |
3190 | 3196 | ||
@@ -3232,7 +3238,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv, | |||
3232 | stalled_mask & ENGINE_MASK(id)); | 3238 | stalled_mask & ENGINE_MASK(id)); |
3233 | ctx = fetch_and_zero(&engine->last_retired_context); | 3239 | ctx = fetch_and_zero(&engine->last_retired_context); |
3234 | if (ctx) | 3240 | if (ctx) |
3235 | engine->context_unpin(engine, ctx); | 3241 | intel_context_unpin(ctx, engine); |
3236 | 3242 | ||
3237 | /* | 3243 | /* |
3238 | * Ostensibily, we always want a context loaded for powersaving, | 3244 | * Ostensibily, we always want a context loaded for powersaving, |
@@ -3297,10 +3303,10 @@ static void nop_complete_submit_request(struct i915_request *request) | |||
3297 | request->fence.context, request->fence.seqno); | 3303 | request->fence.context, request->fence.seqno); |
3298 | dma_fence_set_error(&request->fence, -EIO); | 3304 | dma_fence_set_error(&request->fence, -EIO); |
3299 | 3305 | ||
3300 | spin_lock_irqsave(&request->engine->timeline->lock, flags); | 3306 | spin_lock_irqsave(&request->engine->timeline.lock, flags); |
3301 | __i915_request_submit(request); | 3307 | __i915_request_submit(request); |
3302 | intel_engine_init_global_seqno(request->engine, request->global_seqno); | 3308 | intel_engine_init_global_seqno(request->engine, request->global_seqno); |
3303 | spin_unlock_irqrestore(&request->engine->timeline->lock, flags); | 3309 | spin_unlock_irqrestore(&request->engine->timeline.lock, flags); |
3304 | } | 3310 | } |
3305 | 3311 | ||
3306 | void i915_gem_set_wedged(struct drm_i915_private *i915) | 3312 | void i915_gem_set_wedged(struct drm_i915_private *i915) |
@@ -3310,7 +3316,7 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3310 | 3316 | ||
3311 | GEM_TRACE("start\n"); | 3317 | GEM_TRACE("start\n"); |
3312 | 3318 | ||
3313 | if (drm_debug & DRM_UT_DRIVER) { | 3319 | if (GEM_SHOW_DEBUG()) { |
3314 | struct drm_printer p = drm_debug_printer(__func__); | 3320 | struct drm_printer p = drm_debug_printer(__func__); |
3315 | 3321 | ||
3316 | for_each_engine(engine, i915, id) | 3322 | for_each_engine(engine, i915, id) |
@@ -3369,10 +3375,10 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3369 | * (lockless) lookup doesn't try and wait upon the request as we | 3375 | * (lockless) lookup doesn't try and wait upon the request as we |
3370 | * reset it. | 3376 | * reset it. |
3371 | */ | 3377 | */ |
3372 | spin_lock_irqsave(&engine->timeline->lock, flags); | 3378 | spin_lock_irqsave(&engine->timeline.lock, flags); |
3373 | intel_engine_init_global_seqno(engine, | 3379 | intel_engine_init_global_seqno(engine, |
3374 | intel_engine_last_submit(engine)); | 3380 | intel_engine_last_submit(engine)); |
3375 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 3381 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
3376 | 3382 | ||
3377 | i915_gem_reset_finish_engine(engine); | 3383 | i915_gem_reset_finish_engine(engine); |
3378 | } | 3384 | } |
@@ -3384,8 +3390,7 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3384 | 3390 | ||
3385 | bool i915_gem_unset_wedged(struct drm_i915_private *i915) | 3391 | bool i915_gem_unset_wedged(struct drm_i915_private *i915) |
3386 | { | 3392 | { |
3387 | struct i915_gem_timeline *tl; | 3393 | struct i915_timeline *tl; |
3388 | int i; | ||
3389 | 3394 | ||
3390 | lockdep_assert_held(&i915->drm.struct_mutex); | 3395 | lockdep_assert_held(&i915->drm.struct_mutex); |
3391 | if (!test_bit(I915_WEDGED, &i915->gpu_error.flags)) | 3396 | if (!test_bit(I915_WEDGED, &i915->gpu_error.flags)) |
@@ -3404,29 +3409,27 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) | |||
3404 | * No more can be submitted until we reset the wedged bit. | 3409 | * No more can be submitted until we reset the wedged bit. |
3405 | */ | 3410 | */ |
3406 | list_for_each_entry(tl, &i915->gt.timelines, link) { | 3411 | list_for_each_entry(tl, &i915->gt.timelines, link) { |
3407 | for (i = 0; i < ARRAY_SIZE(tl->engine); i++) { | 3412 | struct i915_request *rq; |
3408 | struct i915_request *rq; | ||
3409 | 3413 | ||
3410 | rq = i915_gem_active_peek(&tl->engine[i].last_request, | 3414 | rq = i915_gem_active_peek(&tl->last_request, |
3411 | &i915->drm.struct_mutex); | 3415 | &i915->drm.struct_mutex); |
3412 | if (!rq) | 3416 | if (!rq) |
3413 | continue; | 3417 | continue; |
3414 | 3418 | ||
3415 | /* | 3419 | /* |
3416 | * We can't use our normal waiter as we want to | 3420 | * We can't use our normal waiter as we want to |
3417 | * avoid recursively trying to handle the current | 3421 | * avoid recursively trying to handle the current |
3418 | * reset. The basic dma_fence_default_wait() installs | 3422 | * reset. The basic dma_fence_default_wait() installs |
3419 | * a callback for dma_fence_signal(), which is | 3423 | * a callback for dma_fence_signal(), which is |
3420 | * triggered by our nop handler (indirectly, the | 3424 | * triggered by our nop handler (indirectly, the |
3421 | * callback enables the signaler thread which is | 3425 | * callback enables the signaler thread which is |
3422 | * woken by the nop_submit_request() advancing the seqno | 3426 | * woken by the nop_submit_request() advancing the seqno |
3423 | * and when the seqno passes the fence, the signaler | 3427 | * and when the seqno passes the fence, the signaler |
3424 | * then signals the fence waking us up). | 3428 | * then signals the fence waking us up). |
3425 | */ | 3429 | */ |
3426 | if (dma_fence_default_wait(&rq->fence, true, | 3430 | if (dma_fence_default_wait(&rq->fence, true, |
3427 | MAX_SCHEDULE_TIMEOUT) < 0) | 3431 | MAX_SCHEDULE_TIMEOUT) < 0) |
3428 | return false; | 3432 | return false; |
3429 | } | ||
3430 | } | 3433 | } |
3431 | i915_retire_requests(i915); | 3434 | i915_retire_requests(i915); |
3432 | GEM_BUG_ON(i915->gt.active_requests); | 3435 | GEM_BUG_ON(i915->gt.active_requests); |
@@ -3731,17 +3734,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | |||
3731 | return ret; | 3734 | return ret; |
3732 | } | 3735 | } |
3733 | 3736 | ||
3734 | static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags) | 3737 | static int wait_for_timeline(struct i915_timeline *tl, unsigned int flags) |
3735 | { | 3738 | { |
3736 | int ret, i; | 3739 | return i915_gem_active_wait(&tl->last_request, flags); |
3737 | |||
3738 | for (i = 0; i < ARRAY_SIZE(tl->engine); i++) { | ||
3739 | ret = i915_gem_active_wait(&tl->engine[i].last_request, flags); | ||
3740 | if (ret) | ||
3741 | return ret; | ||
3742 | } | ||
3743 | |||
3744 | return 0; | ||
3745 | } | 3740 | } |
3746 | 3741 | ||
3747 | static int wait_for_engines(struct drm_i915_private *i915) | 3742 | static int wait_for_engines(struct drm_i915_private *i915) |
@@ -3759,30 +3754,37 @@ static int wait_for_engines(struct drm_i915_private *i915) | |||
3759 | 3754 | ||
3760 | int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) | 3755 | int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags) |
3761 | { | 3756 | { |
3762 | int ret; | ||
3763 | |||
3764 | /* If the device is asleep, we have no requests outstanding */ | 3757 | /* If the device is asleep, we have no requests outstanding */ |
3765 | if (!READ_ONCE(i915->gt.awake)) | 3758 | if (!READ_ONCE(i915->gt.awake)) |
3766 | return 0; | 3759 | return 0; |
3767 | 3760 | ||
3768 | if (flags & I915_WAIT_LOCKED) { | 3761 | if (flags & I915_WAIT_LOCKED) { |
3769 | struct i915_gem_timeline *tl; | 3762 | struct i915_timeline *tl; |
3763 | int err; | ||
3770 | 3764 | ||
3771 | lockdep_assert_held(&i915->drm.struct_mutex); | 3765 | lockdep_assert_held(&i915->drm.struct_mutex); |
3772 | 3766 | ||
3773 | list_for_each_entry(tl, &i915->gt.timelines, link) { | 3767 | list_for_each_entry(tl, &i915->gt.timelines, link) { |
3774 | ret = wait_for_timeline(tl, flags); | 3768 | err = wait_for_timeline(tl, flags); |
3775 | if (ret) | 3769 | if (err) |
3776 | return ret; | 3770 | return err; |
3777 | } | 3771 | } |
3778 | i915_retire_requests(i915); | 3772 | i915_retire_requests(i915); |
3779 | 3773 | ||
3780 | ret = wait_for_engines(i915); | 3774 | return wait_for_engines(i915); |
3781 | } else { | 3775 | } else { |
3782 | ret = wait_for_timeline(&i915->gt.global_timeline, flags); | 3776 | struct intel_engine_cs *engine; |
3783 | } | 3777 | enum intel_engine_id id; |
3778 | int err; | ||
3784 | 3779 | ||
3785 | return ret; | 3780 | for_each_engine(engine, i915, id) { |
3781 | err = wait_for_timeline(&engine->timeline, flags); | ||
3782 | if (err) | ||
3783 | return err; | ||
3784 | } | ||
3785 | |||
3786 | return 0; | ||
3787 | } | ||
3786 | } | 3788 | } |
3787 | 3789 | ||
3788 | static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) | 3790 | static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) |
@@ -4796,7 +4798,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, | |||
4796 | &obj->vma_list, obj_link) { | 4798 | &obj->vma_list, obj_link) { |
4797 | GEM_BUG_ON(i915_vma_is_active(vma)); | 4799 | GEM_BUG_ON(i915_vma_is_active(vma)); |
4798 | vma->flags &= ~I915_VMA_PIN_MASK; | 4800 | vma->flags &= ~I915_VMA_PIN_MASK; |
4799 | i915_vma_close(vma); | 4801 | i915_vma_destroy(vma); |
4800 | } | 4802 | } |
4801 | GEM_BUG_ON(!list_empty(&obj->vma_list)); | 4803 | GEM_BUG_ON(!list_empty(&obj->vma_list)); |
4802 | GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree)); | 4804 | GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree)); |
@@ -4951,7 +4953,7 @@ static void assert_kernel_context_is_current(struct drm_i915_private *i915) | |||
4951 | enum intel_engine_id id; | 4953 | enum intel_engine_id id; |
4952 | 4954 | ||
4953 | for_each_engine(engine, i915, id) { | 4955 | for_each_engine(engine, i915, id) { |
4954 | GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline->last_request)); | 4956 | GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline.last_request)); |
4955 | GEM_BUG_ON(engine->last_retired_context != kernel_context); | 4957 | GEM_BUG_ON(engine->last_retired_context != kernel_context); |
4956 | } | 4958 | } |
4957 | } | 4959 | } |
@@ -5289,7 +5291,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) | |||
5289 | for_each_engine(engine, i915, id) { | 5291 | for_each_engine(engine, i915, id) { |
5290 | struct i915_vma *state; | 5292 | struct i915_vma *state; |
5291 | 5293 | ||
5292 | state = ctx->engine[id].state; | 5294 | state = to_intel_context(ctx, engine)->state; |
5293 | if (!state) | 5295 | if (!state) |
5294 | continue; | 5296 | continue; |
5295 | 5297 | ||
@@ -5597,12 +5599,9 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv) | |||
5597 | if (!dev_priv->priorities) | 5599 | if (!dev_priv->priorities) |
5598 | goto err_dependencies; | 5600 | goto err_dependencies; |
5599 | 5601 | ||
5600 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
5601 | INIT_LIST_HEAD(&dev_priv->gt.timelines); | 5602 | INIT_LIST_HEAD(&dev_priv->gt.timelines); |
5602 | err = i915_gem_timeline_init__global(dev_priv); | 5603 | INIT_LIST_HEAD(&dev_priv->gt.active_rings); |
5603 | mutex_unlock(&dev_priv->drm.struct_mutex); | 5604 | INIT_LIST_HEAD(&dev_priv->gt.closed_vma); |
5604 | if (err) | ||
5605 | goto err_priorities; | ||
5606 | 5605 | ||
5607 | i915_gem_init__mm(dev_priv); | 5606 | i915_gem_init__mm(dev_priv); |
5608 | 5607 | ||
@@ -5623,8 +5622,6 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv) | |||
5623 | 5622 | ||
5624 | return 0; | 5623 | return 0; |
5625 | 5624 | ||
5626 | err_priorities: | ||
5627 | kmem_cache_destroy(dev_priv->priorities); | ||
5628 | err_dependencies: | 5625 | err_dependencies: |
5629 | kmem_cache_destroy(dev_priv->dependencies); | 5626 | kmem_cache_destroy(dev_priv->dependencies); |
5630 | err_requests: | 5627 | err_requests: |
@@ -5645,11 +5642,7 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv) | |||
5645 | GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); | 5642 | GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); |
5646 | GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); | 5643 | GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); |
5647 | WARN_ON(dev_priv->mm.object_count); | 5644 | WARN_ON(dev_priv->mm.object_count); |
5648 | |||
5649 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
5650 | i915_gem_timeline_fini(&dev_priv->gt.global_timeline); | ||
5651 | WARN_ON(!list_empty(&dev_priv->gt.timelines)); | 5645 | WARN_ON(!list_empty(&dev_priv->gt.timelines)); |
5652 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
5653 | 5646 | ||
5654 | kmem_cache_destroy(dev_priv->priorities); | 5647 | kmem_cache_destroy(dev_priv->priorities); |
5655 | kmem_cache_destroy(dev_priv->dependencies); | 5648 | kmem_cache_destroy(dev_priv->dependencies); |
diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index deaf78d2ae8b..525920404ede 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h | |||
@@ -30,6 +30,9 @@ | |||
30 | struct drm_i915_private; | 30 | struct drm_i915_private; |
31 | 31 | ||
32 | #ifdef CONFIG_DRM_I915_DEBUG_GEM | 32 | #ifdef CONFIG_DRM_I915_DEBUG_GEM |
33 | |||
34 | #define GEM_SHOW_DEBUG() (drm_debug & DRM_UT_DRIVER) | ||
35 | |||
33 | #define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ | 36 | #define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ |
34 | pr_err("%s:%d GEM_BUG_ON(%s)\n", \ | 37 | pr_err("%s:%d GEM_BUG_ON(%s)\n", \ |
35 | __func__, __LINE__, __stringify(condition)); \ | 38 | __func__, __LINE__, __stringify(condition)); \ |
@@ -45,6 +48,9 @@ struct drm_i915_private; | |||
45 | #define GEM_DEBUG_BUG_ON(expr) GEM_BUG_ON(expr) | 48 | #define GEM_DEBUG_BUG_ON(expr) GEM_BUG_ON(expr) |
46 | 49 | ||
47 | #else | 50 | #else |
51 | |||
52 | #define GEM_SHOW_DEBUG() (0) | ||
53 | |||
48 | #define GEM_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) | 54 | #define GEM_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) |
49 | #define GEM_WARN_ON(expr) (BUILD_BUG_ON_INVALID(expr), 0) | 55 | #define GEM_WARN_ON(expr) (BUILD_BUG_ON_INVALID(expr), 0) |
50 | 56 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 9b3834a846e8..33f8a4b3c981 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -117,15 +117,15 @@ static void lut_close(struct i915_gem_context *ctx) | |||
117 | 117 | ||
118 | static void i915_gem_context_free(struct i915_gem_context *ctx) | 118 | static void i915_gem_context_free(struct i915_gem_context *ctx) |
119 | { | 119 | { |
120 | int i; | 120 | unsigned int n; |
121 | 121 | ||
122 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); | 122 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); |
123 | GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); | 123 | GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); |
124 | 124 | ||
125 | i915_ppgtt_put(ctx->ppgtt); | 125 | i915_ppgtt_put(ctx->ppgtt); |
126 | 126 | ||
127 | for (i = 0; i < I915_NUM_ENGINES; i++) { | 127 | for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) { |
128 | struct intel_context *ce = &ctx->engine[i]; | 128 | struct intel_context *ce = &ctx->__engine[n]; |
129 | 129 | ||
130 | if (!ce->state) | 130 | if (!ce->state) |
131 | continue; | 131 | continue; |
@@ -281,7 +281,7 @@ __create_hw_context(struct drm_i915_private *dev_priv, | |||
281 | kref_init(&ctx->ref); | 281 | kref_init(&ctx->ref); |
282 | list_add_tail(&ctx->link, &dev_priv->contexts.list); | 282 | list_add_tail(&ctx->link, &dev_priv->contexts.list); |
283 | ctx->i915 = dev_priv; | 283 | ctx->i915 = dev_priv; |
284 | ctx->priority = I915_PRIORITY_NORMAL; | 284 | ctx->sched.priority = I915_PRIORITY_NORMAL; |
285 | 285 | ||
286 | INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); | 286 | INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); |
287 | INIT_LIST_HEAD(&ctx->handles_list); | 287 | INIT_LIST_HEAD(&ctx->handles_list); |
@@ -431,7 +431,7 @@ i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio) | |||
431 | return ctx; | 431 | return ctx; |
432 | 432 | ||
433 | i915_gem_context_clear_bannable(ctx); | 433 | i915_gem_context_clear_bannable(ctx); |
434 | ctx->priority = prio; | 434 | ctx->sched.priority = prio; |
435 | ctx->ring_size = PAGE_SIZE; | 435 | ctx->ring_size = PAGE_SIZE; |
436 | 436 | ||
437 | GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); | 437 | GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); |
@@ -521,7 +521,7 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) | |||
521 | if (!engine->last_retired_context) | 521 | if (!engine->last_retired_context) |
522 | continue; | 522 | continue; |
523 | 523 | ||
524 | engine->context_unpin(engine, engine->last_retired_context); | 524 | intel_context_unpin(engine->last_retired_context, engine); |
525 | engine->last_retired_context = NULL; | 525 | engine->last_retired_context = NULL; |
526 | } | 526 | } |
527 | } | 527 | } |
@@ -577,19 +577,29 @@ void i915_gem_context_close(struct drm_file *file) | |||
577 | idr_destroy(&file_priv->context_idr); | 577 | idr_destroy(&file_priv->context_idr); |
578 | } | 578 | } |
579 | 579 | ||
580 | static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) | 580 | static struct i915_request * |
581 | last_request_on_engine(struct i915_timeline *timeline, | ||
582 | struct intel_engine_cs *engine) | ||
581 | { | 583 | { |
582 | struct i915_gem_timeline *timeline; | 584 | struct i915_request *rq; |
583 | 585 | ||
584 | list_for_each_entry(timeline, &engine->i915->gt.timelines, link) { | 586 | if (timeline == &engine->timeline) |
585 | struct intel_timeline *tl; | 587 | return NULL; |
586 | 588 | ||
587 | if (timeline == &engine->i915->gt.global_timeline) | 589 | rq = i915_gem_active_raw(&timeline->last_request, |
588 | continue; | 590 | &engine->i915->drm.struct_mutex); |
591 | if (rq && rq->engine == engine) | ||
592 | return rq; | ||
593 | |||
594 | return NULL; | ||
595 | } | ||
589 | 596 | ||
590 | tl = &timeline->engine[engine->id]; | 597 | static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) |
591 | if (i915_gem_active_peek(&tl->last_request, | 598 | { |
592 | &engine->i915->drm.struct_mutex)) | 599 | struct i915_timeline *timeline; |
600 | |||
601 | list_for_each_entry(timeline, &engine->i915->gt.timelines, link) { | ||
602 | if (last_request_on_engine(timeline, engine)) | ||
593 | return false; | 603 | return false; |
594 | } | 604 | } |
595 | 605 | ||
@@ -599,7 +609,7 @@ static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) | |||
599 | int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) | 609 | int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) |
600 | { | 610 | { |
601 | struct intel_engine_cs *engine; | 611 | struct intel_engine_cs *engine; |
602 | struct i915_gem_timeline *timeline; | 612 | struct i915_timeline *timeline; |
603 | enum intel_engine_id id; | 613 | enum intel_engine_id id; |
604 | 614 | ||
605 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 615 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
@@ -619,11 +629,8 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) | |||
619 | /* Queue this switch after all other activity */ | 629 | /* Queue this switch after all other activity */ |
620 | list_for_each_entry(timeline, &dev_priv->gt.timelines, link) { | 630 | list_for_each_entry(timeline, &dev_priv->gt.timelines, link) { |
621 | struct i915_request *prev; | 631 | struct i915_request *prev; |
622 | struct intel_timeline *tl; | ||
623 | 632 | ||
624 | tl = &timeline->engine[engine->id]; | 633 | prev = last_request_on_engine(timeline, engine); |
625 | prev = i915_gem_active_raw(&tl->last_request, | ||
626 | &dev_priv->drm.struct_mutex); | ||
627 | if (prev) | 634 | if (prev) |
628 | i915_sw_fence_await_sw_fence_gfp(&rq->submit, | 635 | i915_sw_fence_await_sw_fence_gfp(&rq->submit, |
629 | &prev->submit, | 636 | &prev->submit, |
@@ -753,7 +760,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, | |||
753 | args->value = i915_gem_context_is_bannable(ctx); | 760 | args->value = i915_gem_context_is_bannable(ctx); |
754 | break; | 761 | break; |
755 | case I915_CONTEXT_PARAM_PRIORITY: | 762 | case I915_CONTEXT_PARAM_PRIORITY: |
756 | args->value = ctx->priority; | 763 | args->value = ctx->sched.priority; |
757 | break; | 764 | break; |
758 | default: | 765 | default: |
759 | ret = -EINVAL; | 766 | ret = -EINVAL; |
@@ -826,7 +833,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, | |||
826 | !capable(CAP_SYS_NICE)) | 833 | !capable(CAP_SYS_NICE)) |
827 | ret = -EPERM; | 834 | ret = -EPERM; |
828 | else | 835 | else |
829 | ctx->priority = priority; | 836 | ctx->sched.priority = priority; |
830 | } | 837 | } |
831 | break; | 838 | break; |
832 | 839 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 7854262ddfd9..ace3b129c189 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h | |||
@@ -137,18 +137,7 @@ struct i915_gem_context { | |||
137 | */ | 137 | */ |
138 | u32 user_handle; | 138 | u32 user_handle; |
139 | 139 | ||
140 | /** | 140 | struct i915_sched_attr sched; |
141 | * @priority: execution and service priority | ||
142 | * | ||
143 | * All clients are equal, but some are more equal than others! | ||
144 | * | ||
145 | * Requests from a context with a greater (more positive) value of | ||
146 | * @priority will be executed before those with a lower @priority | ||
147 | * value, forming a simple QoS. | ||
148 | * | ||
149 | * The &drm_i915_private.kernel_context is assigned the lowest priority. | ||
150 | */ | ||
151 | int priority; | ||
152 | 141 | ||
153 | /** ggtt_offset_bias: placement restriction for context objects */ | 142 | /** ggtt_offset_bias: placement restriction for context objects */ |
154 | u32 ggtt_offset_bias; | 143 | u32 ggtt_offset_bias; |
@@ -160,7 +149,7 @@ struct i915_gem_context { | |||
160 | u32 *lrc_reg_state; | 149 | u32 *lrc_reg_state; |
161 | u64 lrc_desc; | 150 | u64 lrc_desc; |
162 | int pin_count; | 151 | int pin_count; |
163 | } engine[I915_NUM_ENGINES]; | 152 | } __engine[I915_NUM_ENGINES]; |
164 | 153 | ||
165 | /** ring_size: size for allocating the per-engine ring buffer */ | 154 | /** ring_size: size for allocating the per-engine ring buffer */ |
166 | u32 ring_size; | 155 | u32 ring_size; |
@@ -267,6 +256,34 @@ static inline bool i915_gem_context_is_kernel(struct i915_gem_context *ctx) | |||
267 | return !ctx->file_priv; | 256 | return !ctx->file_priv; |
268 | } | 257 | } |
269 | 258 | ||
259 | static inline struct intel_context * | ||
260 | to_intel_context(struct i915_gem_context *ctx, | ||
261 | const struct intel_engine_cs *engine) | ||
262 | { | ||
263 | return &ctx->__engine[engine->id]; | ||
264 | } | ||
265 | |||
266 | static inline struct intel_ring * | ||
267 | intel_context_pin(struct i915_gem_context *ctx, struct intel_engine_cs *engine) | ||
268 | { | ||
269 | return engine->context_pin(engine, ctx); | ||
270 | } | ||
271 | |||
272 | static inline void __intel_context_pin(struct i915_gem_context *ctx, | ||
273 | const struct intel_engine_cs *engine) | ||
274 | { | ||
275 | struct intel_context *ce = to_intel_context(ctx, engine); | ||
276 | |||
277 | GEM_BUG_ON(!ce->pin_count); | ||
278 | ce->pin_count++; | ||
279 | } | ||
280 | |||
281 | static inline void intel_context_unpin(struct i915_gem_context *ctx, | ||
282 | struct intel_engine_cs *engine) | ||
283 | { | ||
284 | engine->context_unpin(engine, ctx); | ||
285 | } | ||
286 | |||
270 | /* i915_gem_context.c */ | 287 | /* i915_gem_context.c */ |
271 | int __must_check i915_gem_contexts_init(struct drm_i915_private *dev_priv); | 288 | int __must_check i915_gem_contexts_init(struct drm_i915_private *dev_priv); |
272 | void i915_gem_contexts_lost(struct drm_i915_private *dev_priv); | 289 | void i915_gem_contexts_lost(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index c74f5df3fb5a..f627a8c47c58 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -762,7 +762,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) | |||
762 | } | 762 | } |
763 | 763 | ||
764 | /* transfer ref to ctx */ | 764 | /* transfer ref to ctx */ |
765 | vma->open_count++; | 765 | if (!vma->open_count++) |
766 | i915_vma_reopen(vma); | ||
766 | list_add(&lut->obj_link, &obj->lut_list); | 767 | list_add(&lut->obj_link, &obj->lut_list); |
767 | list_add(&lut->ctx_link, &eb->ctx->handles_list); | 768 | list_add(&lut->ctx_link, &eb->ctx->handles_list); |
768 | lut->ctx = eb->ctx; | 769 | lut->ctx = eb->ctx; |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 21d72f695adb..996ab2ad6c45 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -110,7 +110,8 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma); | |||
110 | 110 | ||
111 | static void gen6_ggtt_invalidate(struct drm_i915_private *dev_priv) | 111 | static void gen6_ggtt_invalidate(struct drm_i915_private *dev_priv) |
112 | { | 112 | { |
113 | /* Note that as an uncached mmio write, this should flush the | 113 | /* |
114 | * Note that as an uncached mmio write, this will flush the | ||
114 | * WCB of the writes into the GGTT before it triggers the invalidate. | 115 | * WCB of the writes into the GGTT before it triggers the invalidate. |
115 | */ | 116 | */ |
116 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); | 117 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
@@ -1161,6 +1162,27 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma, | |||
1161 | vaddr[idx.pde] |= GEN8_PDE_IPS_64K; | 1162 | vaddr[idx.pde] |= GEN8_PDE_IPS_64K; |
1162 | kunmap_atomic(vaddr); | 1163 | kunmap_atomic(vaddr); |
1163 | page_size = I915_GTT_PAGE_SIZE_64K; | 1164 | page_size = I915_GTT_PAGE_SIZE_64K; |
1165 | |||
1166 | /* | ||
1167 | * We write all 4K page entries, even when using 64K | ||
1168 | * pages. In order to verify that the HW isn't cheating | ||
1169 | * by using the 4K PTE instead of the 64K PTE, we want | ||
1170 | * to remove all the surplus entries. If the HW skipped | ||
1171 | * the 64K PTE, it will read/write into the scratch page | ||
1172 | * instead - which we detect as missing results during | ||
1173 | * selftests. | ||
1174 | */ | ||
1175 | if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) { | ||
1176 | u16 i; | ||
1177 | |||
1178 | encode = pte_encode | vma->vm->scratch_page.daddr; | ||
1179 | vaddr = kmap_atomic_px(pd->page_table[idx.pde]); | ||
1180 | |||
1181 | for (i = 1; i < index; i += 16) | ||
1182 | memset64(vaddr + i, encode, 15); | ||
1183 | |||
1184 | kunmap_atomic(vaddr); | ||
1185 | } | ||
1164 | } | 1186 | } |
1165 | 1187 | ||
1166 | vma->page_sizes.gtt |= page_size; | 1188 | vma->page_sizes.gtt |= page_size; |
@@ -2111,8 +2133,6 @@ static void i915_address_space_init(struct i915_address_space *vm, | |||
2111 | struct drm_i915_private *dev_priv, | 2133 | struct drm_i915_private *dev_priv, |
2112 | const char *name) | 2134 | const char *name) |
2113 | { | 2135 | { |
2114 | i915_gem_timeline_init(dev_priv, &vm->timeline, name); | ||
2115 | |||
2116 | drm_mm_init(&vm->mm, 0, vm->total); | 2136 | drm_mm_init(&vm->mm, 0, vm->total); |
2117 | vm->mm.head_node.color = I915_COLOR_UNEVICTABLE; | 2137 | vm->mm.head_node.color = I915_COLOR_UNEVICTABLE; |
2118 | 2138 | ||
@@ -2129,7 +2149,6 @@ static void i915_address_space_fini(struct i915_address_space *vm) | |||
2129 | if (pagevec_count(&vm->free_pages)) | 2149 | if (pagevec_count(&vm->free_pages)) |
2130 | vm_free_pages_release(vm, true); | 2150 | vm_free_pages_release(vm, true); |
2131 | 2151 | ||
2132 | i915_gem_timeline_fini(&vm->timeline); | ||
2133 | drm_mm_takedown(&vm->mm); | 2152 | drm_mm_takedown(&vm->mm); |
2134 | list_del(&vm->global_link); | 2153 | list_del(&vm->global_link); |
2135 | } | 2154 | } |
@@ -2140,15 +2159,15 @@ static void gtt_write_workarounds(struct drm_i915_private *dev_priv) | |||
2140 | * called on driver load and after a GPU reset, so you can place | 2159 | * called on driver load and after a GPU reset, so you can place |
2141 | * workarounds here even if they get overwritten by GPU reset. | 2160 | * workarounds here even if they get overwritten by GPU reset. |
2142 | */ | 2161 | */ |
2143 | /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl,cnl */ | 2162 | /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl,cnl,icl */ |
2144 | if (IS_BROADWELL(dev_priv)) | 2163 | if (IS_BROADWELL(dev_priv)) |
2145 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); | 2164 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); |
2146 | else if (IS_CHERRYVIEW(dev_priv)) | 2165 | else if (IS_CHERRYVIEW(dev_priv)) |
2147 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); | 2166 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); |
2148 | else if (IS_GEN9_BC(dev_priv) || IS_GEN10(dev_priv)) | ||
2149 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); | ||
2150 | else if (IS_GEN9_LP(dev_priv)) | 2167 | else if (IS_GEN9_LP(dev_priv)) |
2151 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); | 2168 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); |
2169 | else if (INTEL_GEN(dev_priv) >= 9) | ||
2170 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); | ||
2152 | 2171 | ||
2153 | /* | 2172 | /* |
2154 | * To support 64K PTEs we need to first enable the use of the | 2173 | * To support 64K PTEs we need to first enable the use of the |
@@ -2222,6 +2241,12 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv, | |||
2222 | 2241 | ||
2223 | void i915_ppgtt_close(struct i915_address_space *vm) | 2242 | void i915_ppgtt_close(struct i915_address_space *vm) |
2224 | { | 2243 | { |
2244 | GEM_BUG_ON(vm->closed); | ||
2245 | vm->closed = true; | ||
2246 | } | ||
2247 | |||
2248 | static void ppgtt_destroy_vma(struct i915_address_space *vm) | ||
2249 | { | ||
2225 | struct list_head *phases[] = { | 2250 | struct list_head *phases[] = { |
2226 | &vm->active_list, | 2251 | &vm->active_list, |
2227 | &vm->inactive_list, | 2252 | &vm->inactive_list, |
@@ -2229,15 +2254,12 @@ void i915_ppgtt_close(struct i915_address_space *vm) | |||
2229 | NULL, | 2254 | NULL, |
2230 | }, **phase; | 2255 | }, **phase; |
2231 | 2256 | ||
2232 | GEM_BUG_ON(vm->closed); | ||
2233 | vm->closed = true; | 2257 | vm->closed = true; |
2234 | |||
2235 | for (phase = phases; *phase; phase++) { | 2258 | for (phase = phases; *phase; phase++) { |
2236 | struct i915_vma *vma, *vn; | 2259 | struct i915_vma *vma, *vn; |
2237 | 2260 | ||
2238 | list_for_each_entry_safe(vma, vn, *phase, vm_link) | 2261 | list_for_each_entry_safe(vma, vn, *phase, vm_link) |
2239 | if (!i915_vma_is_closed(vma)) | 2262 | i915_vma_destroy(vma); |
2240 | i915_vma_close(vma); | ||
2241 | } | 2263 | } |
2242 | } | 2264 | } |
2243 | 2265 | ||
@@ -2248,7 +2270,8 @@ void i915_ppgtt_release(struct kref *kref) | |||
2248 | 2270 | ||
2249 | trace_i915_ppgtt_release(&ppgtt->base); | 2271 | trace_i915_ppgtt_release(&ppgtt->base); |
2250 | 2272 | ||
2251 | /* vmas should already be unbound and destroyed */ | 2273 | ppgtt_destroy_vma(&ppgtt->base); |
2274 | |||
2252 | GEM_BUG_ON(!list_empty(&ppgtt->base.active_list)); | 2275 | GEM_BUG_ON(!list_empty(&ppgtt->base.active_list)); |
2253 | GEM_BUG_ON(!list_empty(&ppgtt->base.inactive_list)); | 2276 | GEM_BUG_ON(!list_empty(&ppgtt->base.inactive_list)); |
2254 | GEM_BUG_ON(!list_empty(&ppgtt->base.unbound_list)); | 2277 | GEM_BUG_ON(!list_empty(&ppgtt->base.unbound_list)); |
@@ -2417,11 +2440,9 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, | |||
2417 | for_each_sgt_dma(addr, sgt_iter, vma->pages) | 2440 | for_each_sgt_dma(addr, sgt_iter, vma->pages) |
2418 | gen8_set_pte(gtt_entries++, pte_encode | addr); | 2441 | gen8_set_pte(gtt_entries++, pte_encode | addr); |
2419 | 2442 | ||
2420 | wmb(); | 2443 | /* |
2421 | 2444 | * We want to flush the TLBs only after we're certain all the PTE | |
2422 | /* This next bit makes the above posting read even more important. We | 2445 | * updates have finished. |
2423 | * want to flush the TLBs only after we're certain all the PTE updates | ||
2424 | * have finished. | ||
2425 | */ | 2446 | */ |
2426 | ggtt->invalidate(vm->i915); | 2447 | ggtt->invalidate(vm->i915); |
2427 | } | 2448 | } |
@@ -2459,11 +2480,10 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | |||
2459 | dma_addr_t addr; | 2480 | dma_addr_t addr; |
2460 | for_each_sgt_dma(addr, iter, vma->pages) | 2481 | for_each_sgt_dma(addr, iter, vma->pages) |
2461 | iowrite32(vm->pte_encode(addr, level, flags), &entries[i++]); | 2482 | iowrite32(vm->pte_encode(addr, level, flags), &entries[i++]); |
2462 | wmb(); | ||
2463 | 2483 | ||
2464 | /* This next bit makes the above posting read even more important. We | 2484 | /* |
2465 | * want to flush the TLBs only after we're certain all the PTE updates | 2485 | * We want to flush the TLBs only after we're certain all the PTE |
2466 | * have finished. | 2486 | * updates have finished. |
2467 | */ | 2487 | */ |
2468 | ggtt->invalidate(vm->i915); | 2488 | ggtt->invalidate(vm->i915); |
2469 | } | 2489 | } |
@@ -3325,14 +3345,10 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) | |||
3325 | DRM_ERROR("Can't set DMA mask/consistent mask (%d)\n", err); | 3345 | DRM_ERROR("Can't set DMA mask/consistent mask (%d)\n", err); |
3326 | 3346 | ||
3327 | pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); | 3347 | pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
3328 | 3348 | if (IS_CHERRYVIEW(dev_priv)) | |
3329 | if (INTEL_GEN(dev_priv) >= 9) { | ||
3330 | size = gen8_get_total_gtt_size(snb_gmch_ctl); | ||
3331 | } else if (IS_CHERRYVIEW(dev_priv)) { | ||
3332 | size = chv_get_total_gtt_size(snb_gmch_ctl); | 3349 | size = chv_get_total_gtt_size(snb_gmch_ctl); |
3333 | } else { | 3350 | else |
3334 | size = gen8_get_total_gtt_size(snb_gmch_ctl); | 3351 | size = gen8_get_total_gtt_size(snb_gmch_ctl); |
3335 | } | ||
3336 | 3352 | ||
3337 | ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT; | 3353 | ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT; |
3338 | ggtt->base.cleanup = gen6_gmch_remove; | 3354 | ggtt->base.cleanup = gen6_gmch_remove; |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 6efc017e8bb3..aec4f73574f4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h | |||
@@ -38,10 +38,9 @@ | |||
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/pagevec.h> | 39 | #include <linux/pagevec.h> |
40 | 40 | ||
41 | #include "i915_gem_timeline.h" | ||
42 | |||
43 | #include "i915_request.h" | 41 | #include "i915_request.h" |
44 | #include "i915_selftest.h" | 42 | #include "i915_selftest.h" |
43 | #include "i915_timeline.h" | ||
45 | 44 | ||
46 | #define I915_GTT_PAGE_SIZE_4K BIT(12) | 45 | #define I915_GTT_PAGE_SIZE_4K BIT(12) |
47 | #define I915_GTT_PAGE_SIZE_64K BIT(16) | 46 | #define I915_GTT_PAGE_SIZE_64K BIT(16) |
@@ -257,7 +256,6 @@ struct i915_pml4 { | |||
257 | 256 | ||
258 | struct i915_address_space { | 257 | struct i915_address_space { |
259 | struct drm_mm mm; | 258 | struct drm_mm mm; |
260 | struct i915_gem_timeline timeline; | ||
261 | struct drm_i915_private *i915; | 259 | struct drm_i915_private *i915; |
262 | struct device *dma; | 260 | struct device *dma; |
263 | /* Every address space belongs to a struct file - except for the global | 261 | /* Every address space belongs to a struct file - except for the global |
@@ -344,6 +342,7 @@ struct i915_address_space { | |||
344 | void (*clear_pages)(struct i915_vma *vma); | 342 | void (*clear_pages)(struct i915_vma *vma); |
345 | 343 | ||
346 | I915_SELFTEST_DECLARE(struct fault_attr fault_attr); | 344 | I915_SELFTEST_DECLARE(struct fault_attr fault_attr); |
345 | I915_SELFTEST_DECLARE(bool scrub_64K); | ||
347 | }; | 346 | }; |
348 | 347 | ||
349 | #define i915_is_ggtt(V) (!(V)->file) | 348 | #define i915_is_ggtt(V) (!(V)->file) |
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index af915d041281..ad949cc30928 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c | |||
@@ -51,6 +51,10 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, | |||
51 | if (!drm_mm_initialized(&dev_priv->mm.stolen)) | 51 | if (!drm_mm_initialized(&dev_priv->mm.stolen)) |
52 | return -ENODEV; | 52 | return -ENODEV; |
53 | 53 | ||
54 | /* WaSkipStolenMemoryFirstPage:bdw+ */ | ||
55 | if (INTEL_GEN(dev_priv) >= 8 && start < 4096) | ||
56 | start = 4096; | ||
57 | |||
54 | mutex_lock(&dev_priv->mm.stolen_lock); | 58 | mutex_lock(&dev_priv->mm.stolen_lock); |
55 | ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, | 59 | ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, |
56 | size, alignment, 0, | 60 | size, alignment, 0, |
@@ -343,7 +347,6 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | |||
343 | { | 347 | { |
344 | resource_size_t reserved_base, stolen_top; | 348 | resource_size_t reserved_base, stolen_top; |
345 | resource_size_t reserved_total, reserved_size; | 349 | resource_size_t reserved_total, reserved_size; |
346 | resource_size_t stolen_usable_start; | ||
347 | 350 | ||
348 | mutex_init(&dev_priv->mm.stolen_lock); | 351 | mutex_init(&dev_priv->mm.stolen_lock); |
349 | 352 | ||
@@ -435,17 +438,11 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) | |||
435 | (u64)resource_size(&dev_priv->dsm) >> 10, | 438 | (u64)resource_size(&dev_priv->dsm) >> 10, |
436 | ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); | 439 | ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); |
437 | 440 | ||
438 | stolen_usable_start = 0; | ||
439 | /* WaSkipStolenMemoryFirstPage:bdw+ */ | ||
440 | if (INTEL_GEN(dev_priv) >= 8) | ||
441 | stolen_usable_start = 4096; | ||
442 | |||
443 | dev_priv->stolen_usable_size = | 441 | dev_priv->stolen_usable_size = |
444 | resource_size(&dev_priv->dsm) - reserved_total - stolen_usable_start; | 442 | resource_size(&dev_priv->dsm) - reserved_total; |
445 | 443 | ||
446 | /* Basic memrange allocator for stolen space. */ | 444 | /* Basic memrange allocator for stolen space. */ |
447 | drm_mm_init(&dev_priv->mm.stolen, stolen_usable_start, | 445 | drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->stolen_usable_size); |
448 | dev_priv->stolen_usable_size); | ||
449 | 446 | ||
450 | return 0; | 447 | return 0; |
451 | } | 448 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c deleted file mode 100644 index e9fd87604067..000000000000 --- a/drivers/gpu/drm/i915/i915_gem_timeline.c +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "i915_drv.h" | ||
26 | #include "i915_syncmap.h" | ||
27 | |||
28 | static void __intel_timeline_init(struct intel_timeline *tl, | ||
29 | struct i915_gem_timeline *parent, | ||
30 | u64 context, | ||
31 | struct lock_class_key *lockclass, | ||
32 | const char *lockname) | ||
33 | { | ||
34 | tl->fence_context = context; | ||
35 | tl->common = parent; | ||
36 | spin_lock_init(&tl->lock); | ||
37 | lockdep_set_class_and_name(&tl->lock, lockclass, lockname); | ||
38 | init_request_active(&tl->last_request, NULL); | ||
39 | INIT_LIST_HEAD(&tl->requests); | ||
40 | i915_syncmap_init(&tl->sync); | ||
41 | } | ||
42 | |||
43 | static void __intel_timeline_fini(struct intel_timeline *tl) | ||
44 | { | ||
45 | GEM_BUG_ON(!list_empty(&tl->requests)); | ||
46 | |||
47 | i915_syncmap_free(&tl->sync); | ||
48 | } | ||
49 | |||
50 | static int __i915_gem_timeline_init(struct drm_i915_private *i915, | ||
51 | struct i915_gem_timeline *timeline, | ||
52 | const char *name, | ||
53 | struct lock_class_key *lockclass, | ||
54 | const char *lockname) | ||
55 | { | ||
56 | unsigned int i; | ||
57 | u64 fences; | ||
58 | |||
59 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
60 | |||
61 | /* | ||
62 | * Ideally we want a set of engines on a single leaf as we expect | ||
63 | * to mostly be tracking synchronisation between engines. It is not | ||
64 | * a huge issue if this is not the case, but we may want to mitigate | ||
65 | * any page crossing penalties if they become an issue. | ||
66 | */ | ||
67 | BUILD_BUG_ON(KSYNCMAP < I915_NUM_ENGINES); | ||
68 | |||
69 | timeline->i915 = i915; | ||
70 | timeline->name = kstrdup(name ?: "[kernel]", GFP_KERNEL); | ||
71 | if (!timeline->name) | ||
72 | return -ENOMEM; | ||
73 | |||
74 | list_add(&timeline->link, &i915->gt.timelines); | ||
75 | |||
76 | /* Called during early_init before we know how many engines there are */ | ||
77 | fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine)); | ||
78 | for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) | ||
79 | __intel_timeline_init(&timeline->engine[i], | ||
80 | timeline, fences++, | ||
81 | lockclass, lockname); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | int i915_gem_timeline_init(struct drm_i915_private *i915, | ||
87 | struct i915_gem_timeline *timeline, | ||
88 | const char *name) | ||
89 | { | ||
90 | static struct lock_class_key class; | ||
91 | |||
92 | return __i915_gem_timeline_init(i915, timeline, name, | ||
93 | &class, "&timeline->lock"); | ||
94 | } | ||
95 | |||
96 | int i915_gem_timeline_init__global(struct drm_i915_private *i915) | ||
97 | { | ||
98 | static struct lock_class_key class; | ||
99 | |||
100 | return __i915_gem_timeline_init(i915, | ||
101 | &i915->gt.global_timeline, | ||
102 | "[execution]", | ||
103 | &class, "&global_timeline->lock"); | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * i915_gem_timelines_park - called when the driver idles | ||
108 | * @i915: the drm_i915_private device | ||
109 | * | ||
110 | * When the driver is completely idle, we know that all of our sync points | ||
111 | * have been signaled and our tracking is then entirely redundant. Any request | ||
112 | * to wait upon an older sync point will be completed instantly as we know | ||
113 | * the fence is signaled and therefore we will not even look them up in the | ||
114 | * sync point map. | ||
115 | */ | ||
116 | void i915_gem_timelines_park(struct drm_i915_private *i915) | ||
117 | { | ||
118 | struct i915_gem_timeline *timeline; | ||
119 | int i; | ||
120 | |||
121 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
122 | |||
123 | list_for_each_entry(timeline, &i915->gt.timelines, link) { | ||
124 | for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) { | ||
125 | struct intel_timeline *tl = &timeline->engine[i]; | ||
126 | |||
127 | /* | ||
128 | * All known fences are completed so we can scrap | ||
129 | * the current sync point tracking and start afresh, | ||
130 | * any attempt to wait upon a previous sync point | ||
131 | * will be skipped as the fence was signaled. | ||
132 | */ | ||
133 | i915_syncmap_free(&tl->sync); | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | void i915_gem_timeline_fini(struct i915_gem_timeline *timeline) | ||
139 | { | ||
140 | int i; | ||
141 | |||
142 | lockdep_assert_held(&timeline->i915->drm.struct_mutex); | ||
143 | |||
144 | for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) | ||
145 | __intel_timeline_fini(&timeline->engine[i]); | ||
146 | |||
147 | list_del(&timeline->link); | ||
148 | kfree(timeline->name); | ||
149 | } | ||
150 | |||
151 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | ||
152 | #include "selftests/mock_timeline.c" | ||
153 | #include "selftests/i915_gem_timeline.c" | ||
154 | #endif | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index d596a8302ca3..854bd51b9478 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c | |||
@@ -778,6 +778,9 @@ i915_gem_userptr_ioctl(struct drm_device *dev, | |||
778 | I915_USERPTR_UNSYNCHRONIZED)) | 778 | I915_USERPTR_UNSYNCHRONIZED)) |
779 | return -EINVAL; | 779 | return -EINVAL; |
780 | 780 | ||
781 | if (!args->user_size) | ||
782 | return -EINVAL; | ||
783 | |||
781 | if (offset_in_page(args->user_ptr | args->user_size)) | 784 | if (offset_in_page(args->user_ptr | args->user_size)) |
782 | return -EINVAL; | 785 | return -EINVAL; |
783 | 786 | ||
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index effaf982b19b..df234dc23274 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c | |||
@@ -404,16 +404,17 @@ static const char *bannable(const struct drm_i915_error_context *ctx) | |||
404 | 404 | ||
405 | static void error_print_request(struct drm_i915_error_state_buf *m, | 405 | static void error_print_request(struct drm_i915_error_state_buf *m, |
406 | const char *prefix, | 406 | const char *prefix, |
407 | const struct drm_i915_error_request *erq) | 407 | const struct drm_i915_error_request *erq, |
408 | const unsigned long epoch) | ||
408 | { | 409 | { |
409 | if (!erq->seqno) | 410 | if (!erq->seqno) |
410 | return; | 411 | return; |
411 | 412 | ||
412 | err_printf(m, "%s pid %d, ban score %d, seqno %8x:%08x, prio %d, emitted %dms ago, head %08x, tail %08x\n", | 413 | err_printf(m, "%s pid %d, ban score %d, seqno %8x:%08x, prio %d, emitted %dms, start %08x, head %08x, tail %08x\n", |
413 | prefix, erq->pid, erq->ban_score, | 414 | prefix, erq->pid, erq->ban_score, |
414 | erq->context, erq->seqno, erq->priority, | 415 | erq->context, erq->seqno, erq->sched_attr.priority, |
415 | jiffies_to_msecs(jiffies - erq->jiffies), | 416 | jiffies_to_msecs(erq->jiffies - epoch), |
416 | erq->head, erq->tail); | 417 | erq->start, erq->head, erq->tail); |
417 | } | 418 | } |
418 | 419 | ||
419 | static void error_print_context(struct drm_i915_error_state_buf *m, | 420 | static void error_print_context(struct drm_i915_error_state_buf *m, |
@@ -422,12 +423,13 @@ static void error_print_context(struct drm_i915_error_state_buf *m, | |||
422 | { | 423 | { |
423 | err_printf(m, "%s%s[%d] user_handle %d hw_id %d, prio %d, ban score %d%s guilty %d active %d\n", | 424 | err_printf(m, "%s%s[%d] user_handle %d hw_id %d, prio %d, ban score %d%s guilty %d active %d\n", |
424 | header, ctx->comm, ctx->pid, ctx->handle, ctx->hw_id, | 425 | header, ctx->comm, ctx->pid, ctx->handle, ctx->hw_id, |
425 | ctx->priority, ctx->ban_score, bannable(ctx), | 426 | ctx->sched_attr.priority, ctx->ban_score, bannable(ctx), |
426 | ctx->guilty, ctx->active); | 427 | ctx->guilty, ctx->active); |
427 | } | 428 | } |
428 | 429 | ||
429 | static void error_print_engine(struct drm_i915_error_state_buf *m, | 430 | static void error_print_engine(struct drm_i915_error_state_buf *m, |
430 | const struct drm_i915_error_engine *ee) | 431 | const struct drm_i915_error_engine *ee, |
432 | const unsigned long epoch) | ||
431 | { | 433 | { |
432 | int n; | 434 | int n; |
433 | 435 | ||
@@ -497,14 +499,15 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, | |||
497 | err_printf(m, " hangcheck stall: %s\n", yesno(ee->hangcheck_stalled)); | 499 | err_printf(m, " hangcheck stall: %s\n", yesno(ee->hangcheck_stalled)); |
498 | err_printf(m, " hangcheck action: %s\n", | 500 | err_printf(m, " hangcheck action: %s\n", |
499 | hangcheck_action_to_str(ee->hangcheck_action)); | 501 | hangcheck_action_to_str(ee->hangcheck_action)); |
500 | err_printf(m, " hangcheck action timestamp: %lu, %u ms ago\n", | 502 | err_printf(m, " hangcheck action timestamp: %dms (%lu%s)\n", |
503 | jiffies_to_msecs(ee->hangcheck_timestamp - epoch), | ||
501 | ee->hangcheck_timestamp, | 504 | ee->hangcheck_timestamp, |
502 | jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); | 505 | ee->hangcheck_timestamp == epoch ? "; epoch" : ""); |
503 | err_printf(m, " engine reset count: %u\n", ee->reset_count); | 506 | err_printf(m, " engine reset count: %u\n", ee->reset_count); |
504 | 507 | ||
505 | for (n = 0; n < ee->num_ports; n++) { | 508 | for (n = 0; n < ee->num_ports; n++) { |
506 | err_printf(m, " ELSP[%d]:", n); | 509 | err_printf(m, " ELSP[%d]:", n); |
507 | error_print_request(m, " ", &ee->execlist[n]); | 510 | error_print_request(m, " ", &ee->execlist[n], epoch); |
508 | } | 511 | } |
509 | 512 | ||
510 | error_print_context(m, " Active context: ", &ee->context); | 513 | error_print_context(m, " Active context: ", &ee->context); |
@@ -650,6 +653,11 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
650 | ts = ktime_to_timespec64(error->uptime); | 653 | ts = ktime_to_timespec64(error->uptime); |
651 | err_printf(m, "Uptime: %lld s %ld us\n", | 654 | err_printf(m, "Uptime: %lld s %ld us\n", |
652 | (s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC); | 655 | (s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC); |
656 | err_printf(m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ); | ||
657 | err_printf(m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n", | ||
658 | error->capture, | ||
659 | jiffies_to_msecs(jiffies - error->capture), | ||
660 | jiffies_to_msecs(error->capture - error->epoch)); | ||
653 | 661 | ||
654 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { | 662 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { |
655 | if (error->engine[i].hangcheck_stalled && | 663 | if (error->engine[i].hangcheck_stalled && |
@@ -710,7 +718,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
710 | 718 | ||
711 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { | 719 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { |
712 | if (error->engine[i].engine_id != -1) | 720 | if (error->engine[i].engine_id != -1) |
713 | error_print_engine(m, &error->engine[i]); | 721 | error_print_engine(m, &error->engine[i], error->epoch); |
714 | } | 722 | } |
715 | 723 | ||
716 | for (i = 0; i < ARRAY_SIZE(error->active_vm); i++) { | 724 | for (i = 0; i < ARRAY_SIZE(error->active_vm); i++) { |
@@ -769,7 +777,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
769 | dev_priv->engine[i]->name, | 777 | dev_priv->engine[i]->name, |
770 | ee->num_requests); | 778 | ee->num_requests); |
771 | for (j = 0; j < ee->num_requests; j++) | 779 | for (j = 0; j < ee->num_requests; j++) |
772 | error_print_request(m, " ", &ee->requests[j]); | 780 | error_print_request(m, " ", |
781 | &ee->requests[j], | ||
782 | error->epoch); | ||
773 | } | 783 | } |
774 | 784 | ||
775 | if (IS_ERR(ee->waiters)) { | 785 | if (IS_ERR(ee->waiters)) { |
@@ -1278,10 +1288,11 @@ static void record_request(struct i915_request *request, | |||
1278 | struct drm_i915_error_request *erq) | 1288 | struct drm_i915_error_request *erq) |
1279 | { | 1289 | { |
1280 | erq->context = request->ctx->hw_id; | 1290 | erq->context = request->ctx->hw_id; |
1281 | erq->priority = request->priotree.priority; | 1291 | erq->sched_attr = request->sched.attr; |
1282 | erq->ban_score = atomic_read(&request->ctx->ban_score); | 1292 | erq->ban_score = atomic_read(&request->ctx->ban_score); |
1283 | erq->seqno = request->global_seqno; | 1293 | erq->seqno = request->global_seqno; |
1284 | erq->jiffies = request->emitted_jiffies; | 1294 | erq->jiffies = request->emitted_jiffies; |
1295 | erq->start = i915_ggtt_offset(request->ring->vma); | ||
1285 | erq->head = request->head; | 1296 | erq->head = request->head; |
1286 | erq->tail = request->tail; | 1297 | erq->tail = request->tail; |
1287 | 1298 | ||
@@ -1299,7 +1310,7 @@ static void engine_record_requests(struct intel_engine_cs *engine, | |||
1299 | 1310 | ||
1300 | count = 0; | 1311 | count = 0; |
1301 | request = first; | 1312 | request = first; |
1302 | list_for_each_entry_from(request, &engine->timeline->requests, link) | 1313 | list_for_each_entry_from(request, &engine->timeline.requests, link) |
1303 | count++; | 1314 | count++; |
1304 | if (!count) | 1315 | if (!count) |
1305 | return; | 1316 | return; |
@@ -1312,7 +1323,7 @@ static void engine_record_requests(struct intel_engine_cs *engine, | |||
1312 | 1323 | ||
1313 | count = 0; | 1324 | count = 0; |
1314 | request = first; | 1325 | request = first; |
1315 | list_for_each_entry_from(request, &engine->timeline->requests, link) { | 1326 | list_for_each_entry_from(request, &engine->timeline.requests, link) { |
1316 | if (count >= ee->num_requests) { | 1327 | if (count >= ee->num_requests) { |
1317 | /* | 1328 | /* |
1318 | * If the ring request list was changed in | 1329 | * If the ring request list was changed in |
@@ -1372,7 +1383,7 @@ static void record_context(struct drm_i915_error_context *e, | |||
1372 | 1383 | ||
1373 | e->handle = ctx->user_handle; | 1384 | e->handle = ctx->user_handle; |
1374 | e->hw_id = ctx->hw_id; | 1385 | e->hw_id = ctx->hw_id; |
1375 | e->priority = ctx->priority; | 1386 | e->sched_attr = ctx->sched; |
1376 | e->ban_score = atomic_read(&ctx->ban_score); | 1387 | e->ban_score = atomic_read(&ctx->ban_score); |
1377 | e->bannable = i915_gem_context_is_bannable(ctx); | 1388 | e->bannable = i915_gem_context_is_bannable(ctx); |
1378 | e->guilty = atomic_read(&ctx->guilty_count); | 1389 | e->guilty = atomic_read(&ctx->guilty_count); |
@@ -1472,7 +1483,8 @@ static void gem_record_rings(struct i915_gpu_state *error) | |||
1472 | 1483 | ||
1473 | ee->ctx = | 1484 | ee->ctx = |
1474 | i915_error_object_create(i915, | 1485 | i915_error_object_create(i915, |
1475 | request->ctx->engine[i].state); | 1486 | to_intel_context(request->ctx, |
1487 | engine)->state); | ||
1476 | 1488 | ||
1477 | error->simulated |= | 1489 | error->simulated |= |
1478 | i915_gem_context_no_error_capture(request->ctx); | 1490 | i915_gem_context_no_error_capture(request->ctx); |
@@ -1735,6 +1747,22 @@ static void capture_params(struct i915_gpu_state *error) | |||
1735 | #undef DUP | 1747 | #undef DUP |
1736 | } | 1748 | } |
1737 | 1749 | ||
1750 | static unsigned long capture_find_epoch(const struct i915_gpu_state *error) | ||
1751 | { | ||
1752 | unsigned long epoch = error->capture; | ||
1753 | int i; | ||
1754 | |||
1755 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { | ||
1756 | const struct drm_i915_error_engine *ee = &error->engine[i]; | ||
1757 | |||
1758 | if (ee->hangcheck_stalled && | ||
1759 | time_before(ee->hangcheck_timestamp, epoch)) | ||
1760 | epoch = ee->hangcheck_timestamp; | ||
1761 | } | ||
1762 | |||
1763 | return epoch; | ||
1764 | } | ||
1765 | |||
1738 | static int capture(void *data) | 1766 | static int capture(void *data) |
1739 | { | 1767 | { |
1740 | struct i915_gpu_state *error = data; | 1768 | struct i915_gpu_state *error = data; |
@@ -1743,6 +1771,7 @@ static int capture(void *data) | |||
1743 | error->boottime = ktime_get_boottime(); | 1771 | error->boottime = ktime_get_boottime(); |
1744 | error->uptime = ktime_sub(ktime_get(), | 1772 | error->uptime = ktime_sub(ktime_get(), |
1745 | error->i915->gt.last_init_time); | 1773 | error->i915->gt.last_init_time); |
1774 | error->capture = jiffies; | ||
1746 | 1775 | ||
1747 | capture_params(error); | 1776 | capture_params(error); |
1748 | capture_gen_state(error); | 1777 | capture_gen_state(error); |
@@ -1756,6 +1785,8 @@ static int capture(void *data) | |||
1756 | error->overlay = intel_overlay_capture_error_state(error->i915); | 1785 | error->overlay = intel_overlay_capture_error_state(error->i915); |
1757 | error->display = intel_display_capture_error_state(error->i915); | 1786 | error->display = intel_display_capture_error_state(error->i915); |
1758 | 1787 | ||
1788 | error->epoch = capture_find_epoch(error); | ||
1789 | |||
1759 | return 0; | 1790 | return 0; |
1760 | } | 1791 | } |
1761 | 1792 | ||
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index c05b6034d718..dac0f8c4c1cf 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "i915_gem.h" | 20 | #include "i915_gem.h" |
21 | #include "i915_gem_gtt.h" | 21 | #include "i915_gem_gtt.h" |
22 | #include "i915_params.h" | 22 | #include "i915_params.h" |
23 | #include "i915_scheduler.h" | ||
23 | 24 | ||
24 | struct drm_i915_private; | 25 | struct drm_i915_private; |
25 | struct intel_overlay_error_state; | 26 | struct intel_overlay_error_state; |
@@ -30,6 +31,8 @@ struct i915_gpu_state { | |||
30 | ktime_t time; | 31 | ktime_t time; |
31 | ktime_t boottime; | 32 | ktime_t boottime; |
32 | ktime_t uptime; | 33 | ktime_t uptime; |
34 | unsigned long capture; | ||
35 | unsigned long epoch; | ||
33 | 36 | ||
34 | struct drm_i915_private *i915; | 37 | struct drm_i915_private *i915; |
35 | 38 | ||
@@ -122,11 +125,11 @@ struct i915_gpu_state { | |||
122 | pid_t pid; | 125 | pid_t pid; |
123 | u32 handle; | 126 | u32 handle; |
124 | u32 hw_id; | 127 | u32 hw_id; |
125 | int priority; | ||
126 | int ban_score; | 128 | int ban_score; |
127 | int active; | 129 | int active; |
128 | int guilty; | 130 | int guilty; |
129 | bool bannable; | 131 | bool bannable; |
132 | struct i915_sched_attr sched_attr; | ||
130 | } context; | 133 | } context; |
131 | 134 | ||
132 | struct drm_i915_error_object { | 135 | struct drm_i915_error_object { |
@@ -147,11 +150,12 @@ struct i915_gpu_state { | |||
147 | long jiffies; | 150 | long jiffies; |
148 | pid_t pid; | 151 | pid_t pid; |
149 | u32 context; | 152 | u32 context; |
150 | int priority; | ||
151 | int ban_score; | 153 | int ban_score; |
152 | u32 seqno; | 154 | u32 seqno; |
155 | u32 start; | ||
153 | u32 head; | 156 | u32 head; |
154 | u32 tail; | 157 | u32 tail; |
158 | struct i915_sched_attr sched_attr; | ||
155 | } *requests, execlist[EXECLIST_MAX_PORTS]; | 159 | } *requests, execlist[EXECLIST_MAX_PORTS]; |
156 | unsigned int num_ports; | 160 | unsigned int num_ports; |
157 | 161 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b03d18561b55..f9bc3aaa90d0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -247,9 +247,9 @@ static u32 | |||
247 | gen11_gt_engine_identity(struct drm_i915_private * const i915, | 247 | gen11_gt_engine_identity(struct drm_i915_private * const i915, |
248 | const unsigned int bank, const unsigned int bit); | 248 | const unsigned int bank, const unsigned int bit); |
249 | 249 | ||
250 | static bool gen11_reset_one_iir(struct drm_i915_private * const i915, | 250 | bool gen11_reset_one_iir(struct drm_i915_private * const i915, |
251 | const unsigned int bank, | 251 | const unsigned int bank, |
252 | const unsigned int bit) | 252 | const unsigned int bit) |
253 | { | 253 | { |
254 | void __iomem * const regs = i915->regs; | 254 | void __iomem * const regs = i915->regs; |
255 | u32 dw; | 255 | u32 dw; |
@@ -2464,6 +2464,13 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, | |||
2464 | if (de_iir & DE_ERR_INT_IVB) | 2464 | if (de_iir & DE_ERR_INT_IVB) |
2465 | ivb_err_int_handler(dev_priv); | 2465 | ivb_err_int_handler(dev_priv); |
2466 | 2466 | ||
2467 | if (de_iir & DE_EDP_PSR_INT_HSW) { | ||
2468 | u32 psr_iir = I915_READ(EDP_PSR_IIR); | ||
2469 | |||
2470 | intel_psr_irq_handler(dev_priv, psr_iir); | ||
2471 | I915_WRITE(EDP_PSR_IIR, psr_iir); | ||
2472 | } | ||
2473 | |||
2467 | if (de_iir & DE_AUX_CHANNEL_A_IVB) | 2474 | if (de_iir & DE_AUX_CHANNEL_A_IVB) |
2468 | dp_aux_irq_handler(dev_priv); | 2475 | dp_aux_irq_handler(dev_priv); |
2469 | 2476 | ||
@@ -2593,11 +2600,25 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) | |||
2593 | if (master_ctl & GEN8_DE_MISC_IRQ) { | 2600 | if (master_ctl & GEN8_DE_MISC_IRQ) { |
2594 | iir = I915_READ(GEN8_DE_MISC_IIR); | 2601 | iir = I915_READ(GEN8_DE_MISC_IIR); |
2595 | if (iir) { | 2602 | if (iir) { |
2603 | bool found = false; | ||
2604 | |||
2596 | I915_WRITE(GEN8_DE_MISC_IIR, iir); | 2605 | I915_WRITE(GEN8_DE_MISC_IIR, iir); |
2597 | ret = IRQ_HANDLED; | 2606 | ret = IRQ_HANDLED; |
2598 | if (iir & GEN8_DE_MISC_GSE) | 2607 | |
2608 | if (iir & GEN8_DE_MISC_GSE) { | ||
2599 | intel_opregion_asle_intr(dev_priv); | 2609 | intel_opregion_asle_intr(dev_priv); |
2600 | else | 2610 | found = true; |
2611 | } | ||
2612 | |||
2613 | if (iir & GEN8_DE_EDP_PSR) { | ||
2614 | u32 psr_iir = I915_READ(EDP_PSR_IIR); | ||
2615 | |||
2616 | intel_psr_irq_handler(dev_priv, psr_iir); | ||
2617 | I915_WRITE(EDP_PSR_IIR, psr_iir); | ||
2618 | found = true; | ||
2619 | } | ||
2620 | |||
2621 | if (!found) | ||
2601 | DRM_ERROR("Unexpected DE Misc interrupt\n"); | 2622 | DRM_ERROR("Unexpected DE Misc interrupt\n"); |
2602 | } | 2623 | } |
2603 | else | 2624 | else |
@@ -3348,6 +3369,11 @@ static void ironlake_irq_reset(struct drm_device *dev) | |||
3348 | if (IS_GEN7(dev_priv)) | 3369 | if (IS_GEN7(dev_priv)) |
3349 | I915_WRITE(GEN7_ERR_INT, 0xffffffff); | 3370 | I915_WRITE(GEN7_ERR_INT, 0xffffffff); |
3350 | 3371 | ||
3372 | if (IS_HASWELL(dev_priv)) { | ||
3373 | I915_WRITE(EDP_PSR_IMR, 0xffffffff); | ||
3374 | I915_WRITE(EDP_PSR_IIR, 0xffffffff); | ||
3375 | } | ||
3376 | |||
3351 | gen5_gt_irq_reset(dev_priv); | 3377 | gen5_gt_irq_reset(dev_priv); |
3352 | 3378 | ||
3353 | ibx_irq_reset(dev_priv); | 3379 | ibx_irq_reset(dev_priv); |
@@ -3386,6 +3412,9 @@ static void gen8_irq_reset(struct drm_device *dev) | |||
3386 | 3412 | ||
3387 | gen8_gt_irq_reset(dev_priv); | 3413 | gen8_gt_irq_reset(dev_priv); |
3388 | 3414 | ||
3415 | I915_WRITE(EDP_PSR_IMR, 0xffffffff); | ||
3416 | I915_WRITE(EDP_PSR_IIR, 0xffffffff); | ||
3417 | |||
3389 | for_each_pipe(dev_priv, pipe) | 3418 | for_each_pipe(dev_priv, pipe) |
3390 | if (intel_display_power_is_enabled(dev_priv, | 3419 | if (intel_display_power_is_enabled(dev_priv, |
3391 | POWER_DOMAIN_PIPE(pipe))) | 3420 | POWER_DOMAIN_PIPE(pipe))) |
@@ -3762,6 +3791,12 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
3762 | DE_DP_A_HOTPLUG); | 3791 | DE_DP_A_HOTPLUG); |
3763 | } | 3792 | } |
3764 | 3793 | ||
3794 | if (IS_HASWELL(dev_priv)) { | ||
3795 | gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); | ||
3796 | intel_psr_irq_control(dev_priv, dev_priv->psr.debug); | ||
3797 | display_mask |= DE_EDP_PSR_INT_HSW; | ||
3798 | } | ||
3799 | |||
3765 | dev_priv->irq_mask = ~display_mask; | 3800 | dev_priv->irq_mask = ~display_mask; |
3766 | 3801 | ||
3767 | ibx_irq_pre_postinstall(dev); | 3802 | ibx_irq_pre_postinstall(dev); |
@@ -3872,7 +3907,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) | |||
3872 | uint32_t de_pipe_enables; | 3907 | uint32_t de_pipe_enables; |
3873 | u32 de_port_masked = GEN8_AUX_CHANNEL_A; | 3908 | u32 de_port_masked = GEN8_AUX_CHANNEL_A; |
3874 | u32 de_port_enables; | 3909 | u32 de_port_enables; |
3875 | u32 de_misc_masked = GEN8_DE_MISC_GSE; | 3910 | u32 de_misc_masked = GEN8_DE_MISC_GSE | GEN8_DE_EDP_PSR; |
3876 | enum pipe pipe; | 3911 | enum pipe pipe; |
3877 | 3912 | ||
3878 | if (INTEL_GEN(dev_priv) >= 9) { | 3913 | if (INTEL_GEN(dev_priv) >= 9) { |
@@ -3897,6 +3932,9 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) | |||
3897 | else if (IS_BROADWELL(dev_priv)) | 3932 | else if (IS_BROADWELL(dev_priv)) |
3898 | de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; | 3933 | de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; |
3899 | 3934 | ||
3935 | gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR); | ||
3936 | intel_psr_irq_control(dev_priv, dev_priv->psr.debug); | ||
3937 | |||
3900 | for_each_pipe(dev_priv, pipe) { | 3938 | for_each_pipe(dev_priv, pipe) { |
3901 | dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; | 3939 | dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; |
3902 | 3940 | ||
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 08108ce5be21..66ea3552c63e 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c | |||
@@ -164,6 +164,9 @@ i915_param_named_unsafe(guc_firmware_path, charp, 0400, | |||
164 | i915_param_named_unsafe(huc_firmware_path, charp, 0400, | 164 | i915_param_named_unsafe(huc_firmware_path, charp, 0400, |
165 | "HuC firmware path to use instead of the default one"); | 165 | "HuC firmware path to use instead of the default one"); |
166 | 166 | ||
167 | i915_param_named_unsafe(dmc_firmware_path, charp, 0400, | ||
168 | "DMC firmware path to use instead of the default one"); | ||
169 | |||
167 | i915_param_named_unsafe(enable_dp_mst, bool, 0600, | 170 | i915_param_named_unsafe(enable_dp_mst, bool, 0600, |
168 | "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); | 171 | "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); |
169 | 172 | ||
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index c96360398072..6684025b7af8 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h | |||
@@ -51,6 +51,7 @@ struct drm_printer; | |||
51 | param(int, guc_log_level, -1) \ | 51 | param(int, guc_log_level, -1) \ |
52 | param(char *, guc_firmware_path, NULL) \ | 52 | param(char *, guc_firmware_path, NULL) \ |
53 | param(char *, huc_firmware_path, NULL) \ | 53 | param(char *, huc_firmware_path, NULL) \ |
54 | param(char *, dmc_firmware_path, NULL) \ | ||
54 | param(int, mmio_debug, 0) \ | 55 | param(int, mmio_debug, 0) \ |
55 | param(int, edp_vswing, 0) \ | 56 | param(int, edp_vswing, 0) \ |
56 | param(int, reset, 2) \ | 57 | param(int, reset, 2) \ |
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index bfc906cd4e5e..019bd2d073ad 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c | |||
@@ -1234,7 +1234,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream) | |||
1234 | * | 1234 | * |
1235 | * NB: implied RCS engine... | 1235 | * NB: implied RCS engine... |
1236 | */ | 1236 | */ |
1237 | ring = engine->context_pin(engine, stream->ctx); | 1237 | ring = intel_context_pin(stream->ctx, engine); |
1238 | mutex_unlock(&dev_priv->drm.struct_mutex); | 1238 | mutex_unlock(&dev_priv->drm.struct_mutex); |
1239 | if (IS_ERR(ring)) | 1239 | if (IS_ERR(ring)) |
1240 | return PTR_ERR(ring); | 1240 | return PTR_ERR(ring); |
@@ -1246,7 +1246,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream) | |||
1246 | * with gen8+ and execlists | 1246 | * with gen8+ and execlists |
1247 | */ | 1247 | */ |
1248 | dev_priv->perf.oa.specific_ctx_id = | 1248 | dev_priv->perf.oa.specific_ctx_id = |
1249 | i915_ggtt_offset(stream->ctx->engine[engine->id].state); | 1249 | i915_ggtt_offset(to_intel_context(stream->ctx, engine)->state); |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | return 0; | 1252 | return 0; |
@@ -1271,7 +1271,7 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream) | |||
1271 | mutex_lock(&dev_priv->drm.struct_mutex); | 1271 | mutex_lock(&dev_priv->drm.struct_mutex); |
1272 | 1272 | ||
1273 | dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; | 1273 | dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; |
1274 | engine->context_unpin(engine, stream->ctx); | 1274 | intel_context_unpin(stream->ctx, engine); |
1275 | 1275 | ||
1276 | mutex_unlock(&dev_priv->drm.struct_mutex); | 1276 | mutex_unlock(&dev_priv->drm.struct_mutex); |
1277 | } | 1277 | } |
@@ -1695,7 +1695,7 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr | |||
1695 | const struct i915_oa_config *oa_config) | 1695 | const struct i915_oa_config *oa_config) |
1696 | { | 1696 | { |
1697 | struct intel_engine_cs *engine = dev_priv->engine[RCS]; | 1697 | struct intel_engine_cs *engine = dev_priv->engine[RCS]; |
1698 | struct i915_gem_timeline *timeline; | 1698 | struct i915_timeline *timeline; |
1699 | struct i915_request *rq; | 1699 | struct i915_request *rq; |
1700 | int ret; | 1700 | int ret; |
1701 | 1701 | ||
@@ -1716,15 +1716,11 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr | |||
1716 | /* Queue this switch after all other activity */ | 1716 | /* Queue this switch after all other activity */ |
1717 | list_for_each_entry(timeline, &dev_priv->gt.timelines, link) { | 1717 | list_for_each_entry(timeline, &dev_priv->gt.timelines, link) { |
1718 | struct i915_request *prev; | 1718 | struct i915_request *prev; |
1719 | struct intel_timeline *tl; | ||
1720 | 1719 | ||
1721 | tl = &timeline->engine[engine->id]; | 1720 | prev = i915_gem_active_raw(&timeline->last_request, |
1722 | prev = i915_gem_active_raw(&tl->last_request, | ||
1723 | &dev_priv->drm.struct_mutex); | 1721 | &dev_priv->drm.struct_mutex); |
1724 | if (prev) | 1722 | if (prev) |
1725 | i915_sw_fence_await_sw_fence_gfp(&rq->submit, | 1723 | i915_request_await_dma_fence(rq, &prev->fence); |
1726 | &prev->submit, | ||
1727 | GFP_KERNEL); | ||
1728 | } | 1724 | } |
1729 | 1725 | ||
1730 | i915_request_add(rq); | 1726 | i915_request_add(rq); |
@@ -1759,6 +1755,7 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr | |||
1759 | static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, | 1755 | static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, |
1760 | const struct i915_oa_config *oa_config) | 1756 | const struct i915_oa_config *oa_config) |
1761 | { | 1757 | { |
1758 | struct intel_engine_cs *engine = dev_priv->engine[RCS]; | ||
1762 | struct i915_gem_context *ctx; | 1759 | struct i915_gem_context *ctx; |
1763 | int ret; | 1760 | int ret; |
1764 | unsigned int wait_flags = I915_WAIT_LOCKED; | 1761 | unsigned int wait_flags = I915_WAIT_LOCKED; |
@@ -1789,7 +1786,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, | |||
1789 | 1786 | ||
1790 | /* Update all contexts now that we've stalled the submission. */ | 1787 | /* Update all contexts now that we've stalled the submission. */ |
1791 | list_for_each_entry(ctx, &dev_priv->contexts.list, link) { | 1788 | list_for_each_entry(ctx, &dev_priv->contexts.list, link) { |
1792 | struct intel_context *ce = &ctx->engine[RCS]; | 1789 | struct intel_context *ce = to_intel_context(ctx, engine); |
1793 | u32 *regs; | 1790 | u32 *regs; |
1794 | 1791 | ||
1795 | /* OA settings will be set upon first use */ | 1792 | /* OA settings will be set upon first use */ |
@@ -1963,11 +1960,19 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream) | |||
1963 | static void gen7_oa_disable(struct drm_i915_private *dev_priv) | 1960 | static void gen7_oa_disable(struct drm_i915_private *dev_priv) |
1964 | { | 1961 | { |
1965 | I915_WRITE(GEN7_OACONTROL, 0); | 1962 | I915_WRITE(GEN7_OACONTROL, 0); |
1963 | if (intel_wait_for_register(dev_priv, | ||
1964 | GEN7_OACONTROL, GEN7_OACONTROL_ENABLE, 0, | ||
1965 | 50)) | ||
1966 | DRM_ERROR("wait for OA to be disabled timed out\n"); | ||
1966 | } | 1967 | } |
1967 | 1968 | ||
1968 | static void gen8_oa_disable(struct drm_i915_private *dev_priv) | 1969 | static void gen8_oa_disable(struct drm_i915_private *dev_priv) |
1969 | { | 1970 | { |
1970 | I915_WRITE(GEN8_OACONTROL, 0); | 1971 | I915_WRITE(GEN8_OACONTROL, 0); |
1972 | if (intel_wait_for_register(dev_priv, | ||
1973 | GEN8_OACONTROL, GEN8_OA_COUNTER_ENABLE, 0, | ||
1974 | 50)) | ||
1975 | DRM_ERROR("wait for OA to be disabled timed out\n"); | ||
1971 | } | 1976 | } |
1972 | 1977 | ||
1973 | /** | 1978 | /** |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fb106026a1f4..f11bb213ec07 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -3840,6 +3840,7 @@ enum { | |||
3840 | #define SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4) | 3840 | #define SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4) |
3841 | #define SARBUNIT_CLKGATE_DIS (1 << 5) | 3841 | #define SARBUNIT_CLKGATE_DIS (1 << 5) |
3842 | #define RCCUNIT_CLKGATE_DIS (1 << 7) | 3842 | #define RCCUNIT_CLKGATE_DIS (1 << 7) |
3843 | #define MSCUNIT_CLKGATE_DIS (1 << 10) | ||
3843 | 3844 | ||
3844 | #define SUBSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9524) | 3845 | #define SUBSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9524) |
3845 | #define GWUNIT_CLKGATE_DIS (1 << 16) | 3846 | #define GWUNIT_CLKGATE_DIS (1 << 16) |
@@ -3847,6 +3848,9 @@ enum { | |||
3847 | #define UNSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9434) | 3848 | #define UNSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9434) |
3848 | #define VFUNIT_CLKGATE_DIS (1 << 20) | 3849 | #define VFUNIT_CLKGATE_DIS (1 << 20) |
3849 | 3850 | ||
3851 | #define INF_UNIT_LEVEL_CLKGATE _MMIO(0x9560) | ||
3852 | #define CGPSF_CLKGATE_DIS (1 << 3) | ||
3853 | |||
3850 | /* | 3854 | /* |
3851 | * Display engine regs | 3855 | * Display engine regs |
3852 | */ | 3856 | */ |
@@ -4026,6 +4030,13 @@ enum { | |||
4026 | #define EDP_PSR_TP1_TIME_0us (3<<4) | 4030 | #define EDP_PSR_TP1_TIME_0us (3<<4) |
4027 | #define EDP_PSR_IDLE_FRAME_SHIFT 0 | 4031 | #define EDP_PSR_IDLE_FRAME_SHIFT 0 |
4028 | 4032 | ||
4033 | /* Bspec claims those aren't shifted but stay at 0x64800 */ | ||
4034 | #define EDP_PSR_IMR _MMIO(0x64834) | ||
4035 | #define EDP_PSR_IIR _MMIO(0x64838) | ||
4036 | #define EDP_PSR_ERROR(trans) (1 << (((trans) * 8 + 10) & 31)) | ||
4037 | #define EDP_PSR_POST_EXIT(trans) (1 << (((trans) * 8 + 9) & 31)) | ||
4038 | #define EDP_PSR_PRE_ENTRY(trans) (1 << (((trans) * 8 + 8) & 31)) | ||
4039 | |||
4029 | #define EDP_PSR_AUX_CTL _MMIO(dev_priv->psr_mmio_base + 0x10) | 4040 | #define EDP_PSR_AUX_CTL _MMIO(dev_priv->psr_mmio_base + 0x10) |
4030 | #define EDP_PSR_AUX_CTL_TIME_OUT_MASK (3 << 26) | 4041 | #define EDP_PSR_AUX_CTL_TIME_OUT_MASK (3 << 26) |
4031 | #define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK (0x1f << 20) | 4042 | #define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK (0x1f << 20) |
@@ -4088,6 +4099,29 @@ enum { | |||
4088 | #define EDP_PSR2_IDLE_FRAME_MASK 0xf | 4099 | #define EDP_PSR2_IDLE_FRAME_MASK 0xf |
4089 | #define EDP_PSR2_IDLE_FRAME_SHIFT 0 | 4100 | #define EDP_PSR2_IDLE_FRAME_SHIFT 0 |
4090 | 4101 | ||
4102 | #define _PSR_EVENT_TRANS_A 0x60848 | ||
4103 | #define _PSR_EVENT_TRANS_B 0x61848 | ||
4104 | #define _PSR_EVENT_TRANS_C 0x62848 | ||
4105 | #define _PSR_EVENT_TRANS_D 0x63848 | ||
4106 | #define _PSR_EVENT_TRANS_EDP 0x6F848 | ||
4107 | #define PSR_EVENT(trans) _MMIO_TRANS2(trans, _PSR_EVENT_TRANS_A) | ||
4108 | #define PSR_EVENT_PSR2_WD_TIMER_EXPIRE (1 << 17) | ||
4109 | #define PSR_EVENT_PSR2_DISABLED (1 << 16) | ||
4110 | #define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN (1 << 15) | ||
4111 | #define PSR_EVENT_SU_CRC_FIFO_UNDERRUN (1 << 14) | ||
4112 | #define PSR_EVENT_GRAPHICS_RESET (1 << 12) | ||
4113 | #define PSR_EVENT_PCH_INTERRUPT (1 << 11) | ||
4114 | #define PSR_EVENT_MEMORY_UP (1 << 10) | ||
4115 | #define PSR_EVENT_FRONT_BUFFER_MODIFY (1 << 9) | ||
4116 | #define PSR_EVENT_WD_TIMER_EXPIRE (1 << 8) | ||
4117 | #define PSR_EVENT_PIPE_REGISTERS_UPDATE (1 << 6) | ||
4118 | #define PSR_EVENT_REGISTER_UPDATE (1 << 5) | ||
4119 | #define PSR_EVENT_HDCP_ENABLE (1 << 4) | ||
4120 | #define PSR_EVENT_KVMR_SESSION_ENABLE (1 << 3) | ||
4121 | #define PSR_EVENT_VBI_ENABLE (1 << 2) | ||
4122 | #define PSR_EVENT_LPSP_MODE_EXIT (1 << 1) | ||
4123 | #define PSR_EVENT_PSR_DISABLE (1 << 0) | ||
4124 | |||
4091 | #define EDP_PSR2_STATUS _MMIO(0x6f940) | 4125 | #define EDP_PSR2_STATUS _MMIO(0x6f940) |
4092 | #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) | 4126 | #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) |
4093 | #define EDP_PSR2_STATUS_STATE_SHIFT 28 | 4127 | #define EDP_PSR2_STATUS_STATE_SHIFT 28 |
@@ -6377,9 +6411,9 @@ enum { | |||
6377 | #define _PLANE_COLOR_CTL_1_A 0x701CC /* GLK+ */ | 6411 | #define _PLANE_COLOR_CTL_1_A 0x701CC /* GLK+ */ |
6378 | #define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */ | 6412 | #define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */ |
6379 | #define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ | 6413 | #define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */ |
6380 | #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) | 6414 | #define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-ICL */ |
6381 | #define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28) | 6415 | #define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28) |
6382 | #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) | 6416 | #define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) /* Pre-ICL */ |
6383 | #define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17) | 6417 | #define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17) |
6384 | #define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709 (1 << 17) | 6418 | #define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709 (1 << 17) |
6385 | #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17) | 6419 | #define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17) |
@@ -6474,6 +6508,9 @@ enum { | |||
6474 | 6508 | ||
6475 | #define _PLANE_BUF_CFG_1_B 0x7127c | 6509 | #define _PLANE_BUF_CFG_1_B 0x7127c |
6476 | #define _PLANE_BUF_CFG_2_B 0x7137c | 6510 | #define _PLANE_BUF_CFG_2_B 0x7137c |
6511 | #define SKL_DDB_ENTRY_MASK 0x3FF | ||
6512 | #define ICL_DDB_ENTRY_MASK 0x7FF | ||
6513 | #define DDB_ENTRY_END_SHIFT 16 | ||
6477 | #define _PLANE_BUF_CFG_1(pipe) \ | 6514 | #define _PLANE_BUF_CFG_1(pipe) \ |
6478 | _PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B) | 6515 | _PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B) |
6479 | #define _PLANE_BUF_CFG_2(pipe) \ | 6516 | #define _PLANE_BUF_CFG_2(pipe) \ |
@@ -6837,6 +6874,7 @@ enum { | |||
6837 | #define DE_PCH_EVENT_IVB (1<<28) | 6874 | #define DE_PCH_EVENT_IVB (1<<28) |
6838 | #define DE_DP_A_HOTPLUG_IVB (1<<27) | 6875 | #define DE_DP_A_HOTPLUG_IVB (1<<27) |
6839 | #define DE_AUX_CHANNEL_A_IVB (1<<26) | 6876 | #define DE_AUX_CHANNEL_A_IVB (1<<26) |
6877 | #define DE_EDP_PSR_INT_HSW (1<<19) | ||
6840 | #define DE_SPRITEC_FLIP_DONE_IVB (1<<14) | 6878 | #define DE_SPRITEC_FLIP_DONE_IVB (1<<14) |
6841 | #define DE_PLANEC_FLIP_DONE_IVB (1<<13) | 6879 | #define DE_PLANEC_FLIP_DONE_IVB (1<<13) |
6842 | #define DE_PIPEC_VBLANK_IVB (1<<10) | 6880 | #define DE_PIPEC_VBLANK_IVB (1<<10) |
@@ -6961,6 +6999,7 @@ enum { | |||
6961 | #define GEN8_DE_MISC_IIR _MMIO(0x44468) | 6999 | #define GEN8_DE_MISC_IIR _MMIO(0x44468) |
6962 | #define GEN8_DE_MISC_IER _MMIO(0x4446c) | 7000 | #define GEN8_DE_MISC_IER _MMIO(0x4446c) |
6963 | #define GEN8_DE_MISC_GSE (1 << 27) | 7001 | #define GEN8_DE_MISC_GSE (1 << 27) |
7002 | #define GEN8_DE_EDP_PSR (1 << 19) | ||
6964 | 7003 | ||
6965 | #define GEN8_PCU_ISR _MMIO(0x444e0) | 7004 | #define GEN8_PCU_ISR _MMIO(0x444e0) |
6966 | #define GEN8_PCU_IMR _MMIO(0x444e4) | 7005 | #define GEN8_PCU_IMR _MMIO(0x444e4) |
@@ -7191,18 +7230,22 @@ enum { | |||
7191 | #define GEN7_L3CNTLREG3 _MMIO(0xB024) | 7230 | #define GEN7_L3CNTLREG3 _MMIO(0xB024) |
7192 | 7231 | ||
7193 | #define GEN7_L3_CHICKEN_MODE_REGISTER _MMIO(0xB030) | 7232 | #define GEN7_L3_CHICKEN_MODE_REGISTER _MMIO(0xB030) |
7194 | #define GEN7_WA_L3_CHICKEN_MODE 0x20000000 | 7233 | #define GEN7_WA_L3_CHICKEN_MODE 0x20000000 |
7234 | #define GEN10_L3_CHICKEN_MODE_REGISTER _MMIO(0xB114) | ||
7235 | #define GEN11_I2M_WRITE_DISABLE (1 << 28) | ||
7195 | 7236 | ||
7196 | #define GEN7_L3SQCREG4 _MMIO(0xb034) | 7237 | #define GEN7_L3SQCREG4 _MMIO(0xb034) |
7197 | #define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27) | 7238 | #define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27) |
7198 | 7239 | ||
7199 | #define GEN8_L3SQCREG4 _MMIO(0xb118) | 7240 | #define GEN8_L3SQCREG4 _MMIO(0xb118) |
7200 | #define GEN8_LQSC_RO_PERF_DIS (1<<27) | 7241 | #define GEN11_LQSC_CLEAN_EVICT_DISABLE (1 << 6) |
7201 | #define GEN8_LQSC_FLUSH_COHERENT_LINES (1<<21) | 7242 | #define GEN8_LQSC_RO_PERF_DIS (1 << 27) |
7243 | #define GEN8_LQSC_FLUSH_COHERENT_LINES (1 << 21) | ||
7202 | 7244 | ||
7203 | /* GEN8 chicken */ | 7245 | /* GEN8 chicken */ |
7204 | #define HDC_CHICKEN0 _MMIO(0x7300) | 7246 | #define HDC_CHICKEN0 _MMIO(0x7300) |
7205 | #define CNL_HDC_CHICKEN0 _MMIO(0xE5F0) | 7247 | #define CNL_HDC_CHICKEN0 _MMIO(0xE5F0) |
7248 | #define ICL_HDC_MODE _MMIO(0xE5F4) | ||
7206 | #define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1<<15) | 7249 | #define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1<<15) |
7207 | #define HDC_FENCE_DEST_SLM_DISABLE (1<<14) | 7250 | #define HDC_FENCE_DEST_SLM_DISABLE (1<<14) |
7208 | #define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11) | 7251 | #define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11) |
@@ -7216,6 +7259,9 @@ enum { | |||
7216 | #define SLICE_ECO_CHICKEN0 _MMIO(0x7308) | 7259 | #define SLICE_ECO_CHICKEN0 _MMIO(0x7308) |
7217 | #define PIXEL_MASK_CAMMING_DISABLE (1 << 14) | 7260 | #define PIXEL_MASK_CAMMING_DISABLE (1 << 14) |
7218 | 7261 | ||
7262 | #define GEN9_WM_CHICKEN3 _MMIO(0x5588) | ||
7263 | #define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9) | ||
7264 | |||
7219 | /* WaCatErrorRejectionIssue */ | 7265 | /* WaCatErrorRejectionIssue */ |
7220 | #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030) | 7266 | #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030) |
7221 | #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) | 7267 | #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) |
@@ -8214,8 +8260,30 @@ enum { | |||
8214 | #define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4) | 8260 | #define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4) |
8215 | #define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6) | 8261 | #define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6) |
8216 | 8262 | ||
8217 | #define GEN8_GARBCNTL _MMIO(0xB004) | 8263 | #define GEN8_GARBCNTL _MMIO(0xB004) |
8218 | #define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7) | 8264 | #define GEN9_GAPS_TSV_CREDIT_DISABLE (1 << 7) |
8265 | #define GEN11_ARBITRATION_PRIO_ORDER_MASK (0x3f << 22) | ||
8266 | #define GEN11_HASH_CTRL_EXCL_MASK (0x7f << 0) | ||
8267 | #define GEN11_HASH_CTRL_EXCL_BIT0 (1 << 0) | ||
8268 | |||
8269 | #define GEN11_GLBLINVL _MMIO(0xB404) | ||
8270 | #define GEN11_BANK_HASH_ADDR_EXCL_MASK (0x7f << 5) | ||
8271 | #define GEN11_BANK_HASH_ADDR_EXCL_BIT0 (1 << 5) | ||
8272 | |||
8273 | #define GEN10_DFR_RATIO_EN_AND_CHICKEN _MMIO(0x9550) | ||
8274 | #define DFR_DISABLE (1 << 9) | ||
8275 | |||
8276 | #define GEN11_GACB_PERF_CTRL _MMIO(0x4B80) | ||
8277 | #define GEN11_HASH_CTRL_MASK (0x3 << 12 | 0xf << 0) | ||
8278 | #define GEN11_HASH_CTRL_BIT0 (1 << 0) | ||
8279 | #define GEN11_HASH_CTRL_BIT4 (1 << 12) | ||
8280 | |||
8281 | #define GEN11_LSN_UNSLCVC _MMIO(0xB43C) | ||
8282 | #define GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC (1 << 9) | ||
8283 | #define GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC (1 << 7) | ||
8284 | |||
8285 | #define GAMW_ECO_DEV_RW_IA_REG _MMIO(0x4080) | ||
8286 | #define GAMW_ECO_DEV_CTX_RELOAD_DISABLE (1 << 7) | ||
8219 | 8287 | ||
8220 | /* IVYBRIDGE DPF */ | 8288 | /* IVYBRIDGE DPF */ |
8221 | #define GEN7_L3CDERRST1(slice) _MMIO(0xB008 + (slice) * 0x200) /* L3CD Error Status 1 */ | 8289 | #define GEN7_L3CDERRST1(slice) _MMIO(0xB008 + (slice) * 0x200) /* L3CD Error Status 1 */ |
@@ -8724,6 +8792,12 @@ enum skl_power_gate { | |||
8724 | #define PORT_CLK_SEL_NONE (7<<29) | 8792 | #define PORT_CLK_SEL_NONE (7<<29) |
8725 | #define PORT_CLK_SEL_MASK (7<<29) | 8793 | #define PORT_CLK_SEL_MASK (7<<29) |
8726 | 8794 | ||
8795 | /* On ICL+ this is the same as PORT_CLK_SEL, but all bits change. */ | ||
8796 | #define DDI_CLK_SEL(port) PORT_CLK_SEL(port) | ||
8797 | #define DDI_CLK_SEL_NONE (0x0 << 28) | ||
8798 | #define DDI_CLK_SEL_MG (0x8 << 28) | ||
8799 | #define DDI_CLK_SEL_MASK (0xF << 28) | ||
8800 | |||
8727 | /* Transcoder clock selection */ | 8801 | /* Transcoder clock selection */ |
8728 | #define _TRANS_CLK_SEL_A 0x46140 | 8802 | #define _TRANS_CLK_SEL_A 0x46140 |
8729 | #define _TRANS_CLK_SEL_B 0x46144 | 8803 | #define _TRANS_CLK_SEL_B 0x46144 |
@@ -8854,6 +8928,7 @@ enum skl_power_gate { | |||
8854 | * CNL Clocks | 8928 | * CNL Clocks |
8855 | */ | 8929 | */ |
8856 | #define DPCLKA_CFGCR0 _MMIO(0x6C200) | 8930 | #define DPCLKA_CFGCR0 _MMIO(0x6C200) |
8931 | #define DPCLKA_CFGCR0_ICL _MMIO(0x164280) | ||
8857 | #define DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port) == PORT_F ? 23 : \ | 8932 | #define DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port) == PORT_F ? 23 : \ |
8858 | (port)+10)) | 8933 | (port)+10)) |
8859 | #define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port) == PORT_F ? 21 : \ | 8934 | #define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port) == PORT_F ? 21 : \ |
@@ -8870,10 +8945,141 @@ enum skl_power_gate { | |||
8870 | #define PLL_POWER_STATE (1 << 26) | 8945 | #define PLL_POWER_STATE (1 << 26) |
8871 | #define CNL_DPLL_ENABLE(pll) _MMIO_PLL(pll, DPLL0_ENABLE, DPLL1_ENABLE) | 8946 | #define CNL_DPLL_ENABLE(pll) _MMIO_PLL(pll, DPLL0_ENABLE, DPLL1_ENABLE) |
8872 | 8947 | ||
8948 | #define _MG_PLL1_ENABLE 0x46030 | ||
8949 | #define _MG_PLL2_ENABLE 0x46034 | ||
8950 | #define _MG_PLL3_ENABLE 0x46038 | ||
8951 | #define _MG_PLL4_ENABLE 0x4603C | ||
8952 | /* Bits are the same as DPLL0_ENABLE */ | ||
8953 | #define MG_PLL_ENABLE(port) _MMIO_PORT((port) - PORT_C, _MG_PLL1_ENABLE, \ | ||
8954 | _MG_PLL2_ENABLE) | ||
8955 | |||
8956 | #define _MG_REFCLKIN_CTL_PORT1 0x16892C | ||
8957 | #define _MG_REFCLKIN_CTL_PORT2 0x16992C | ||
8958 | #define _MG_REFCLKIN_CTL_PORT3 0x16A92C | ||
8959 | #define _MG_REFCLKIN_CTL_PORT4 0x16B92C | ||
8960 | #define MG_REFCLKIN_CTL_OD_2_MUX(x) ((x) << 8) | ||
8961 | #define MG_REFCLKIN_CTL(port) _MMIO_PORT((port) - PORT_C, \ | ||
8962 | _MG_REFCLKIN_CTL_PORT1, \ | ||
8963 | _MG_REFCLKIN_CTL_PORT2) | ||
8964 | |||
8965 | #define _MG_CLKTOP2_CORECLKCTL1_PORT1 0x1688D8 | ||
8966 | #define _MG_CLKTOP2_CORECLKCTL1_PORT2 0x1698D8 | ||
8967 | #define _MG_CLKTOP2_CORECLKCTL1_PORT3 0x16A8D8 | ||
8968 | #define _MG_CLKTOP2_CORECLKCTL1_PORT4 0x16B8D8 | ||
8969 | #define MG_CLKTOP2_CORECLKCTL1_B_DIVRATIO(x) ((x) << 16) | ||
8970 | #define MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(x) ((x) << 8) | ||
8971 | #define MG_CLKTOP2_CORECLKCTL1(port) _MMIO_PORT((port) - PORT_C, \ | ||
8972 | _MG_CLKTOP2_CORECLKCTL1_PORT1, \ | ||
8973 | _MG_CLKTOP2_CORECLKCTL1_PORT2) | ||
8974 | |||
8975 | #define _MG_CLKTOP2_HSCLKCTL_PORT1 0x1688D4 | ||
8976 | #define _MG_CLKTOP2_HSCLKCTL_PORT2 0x1698D4 | ||
8977 | #define _MG_CLKTOP2_HSCLKCTL_PORT3 0x16A8D4 | ||
8978 | #define _MG_CLKTOP2_HSCLKCTL_PORT4 0x16B8D4 | ||
8979 | #define MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(x) ((x) << 16) | ||
8980 | #define MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(x) ((x) << 14) | ||
8981 | #define MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO(x) ((x) << 12) | ||
8982 | #define MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(x) ((x) << 8) | ||
8983 | #define MG_CLKTOP2_HSCLKCTL(port) _MMIO_PORT((port) - PORT_C, \ | ||
8984 | _MG_CLKTOP2_HSCLKCTL_PORT1, \ | ||
8985 | _MG_CLKTOP2_HSCLKCTL_PORT2) | ||
8986 | |||
8987 | #define _MG_PLL_DIV0_PORT1 0x168A00 | ||
8988 | #define _MG_PLL_DIV0_PORT2 0x169A00 | ||
8989 | #define _MG_PLL_DIV0_PORT3 0x16AA00 | ||
8990 | #define _MG_PLL_DIV0_PORT4 0x16BA00 | ||
8991 | #define MG_PLL_DIV0_FRACNEN_H (1 << 30) | ||
8992 | #define MG_PLL_DIV0_FBDIV_FRAC(x) ((x) << 8) | ||
8993 | #define MG_PLL_DIV0_FBDIV_INT(x) ((x) << 0) | ||
8994 | #define MG_PLL_DIV0(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV0_PORT1, \ | ||
8995 | _MG_PLL_DIV0_PORT2) | ||
8996 | |||
8997 | #define _MG_PLL_DIV1_PORT1 0x168A04 | ||
8998 | #define _MG_PLL_DIV1_PORT2 0x169A04 | ||
8999 | #define _MG_PLL_DIV1_PORT3 0x16AA04 | ||
9000 | #define _MG_PLL_DIV1_PORT4 0x16BA04 | ||
9001 | #define MG_PLL_DIV1_IREF_NDIVRATIO(x) ((x) << 16) | ||
9002 | #define MG_PLL_DIV1_DITHER_DIV_1 (0 << 12) | ||
9003 | #define MG_PLL_DIV1_DITHER_DIV_2 (1 << 12) | ||
9004 | #define MG_PLL_DIV1_DITHER_DIV_4 (2 << 12) | ||
9005 | #define MG_PLL_DIV1_DITHER_DIV_8 (3 << 12) | ||
9006 | #define MG_PLL_DIV1_NDIVRATIO(x) ((x) << 4) | ||
9007 | #define MG_PLL_DIV1_FBPREDIV(x) ((x) << 0) | ||
9008 | #define MG_PLL_DIV1(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV1_PORT1, \ | ||
9009 | _MG_PLL_DIV1_PORT2) | ||
9010 | |||
9011 | #define _MG_PLL_LF_PORT1 0x168A08 | ||
9012 | #define _MG_PLL_LF_PORT2 0x169A08 | ||
9013 | #define _MG_PLL_LF_PORT3 0x16AA08 | ||
9014 | #define _MG_PLL_LF_PORT4 0x16BA08 | ||
9015 | #define MG_PLL_LF_TDCTARGETCNT(x) ((x) << 24) | ||
9016 | #define MG_PLL_LF_AFCCNTSEL_256 (0 << 20) | ||
9017 | #define MG_PLL_LF_AFCCNTSEL_512 (1 << 20) | ||
9018 | #define MG_PLL_LF_GAINCTRL(x) ((x) << 16) | ||
9019 | #define MG_PLL_LF_INT_COEFF(x) ((x) << 8) | ||
9020 | #define MG_PLL_LF_PROP_COEFF(x) ((x) << 0) | ||
9021 | #define MG_PLL_LF(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_LF_PORT1, \ | ||
9022 | _MG_PLL_LF_PORT2) | ||
9023 | |||
9024 | #define _MG_PLL_FRAC_LOCK_PORT1 0x168A0C | ||
9025 | #define _MG_PLL_FRAC_LOCK_PORT2 0x169A0C | ||
9026 | #define _MG_PLL_FRAC_LOCK_PORT3 0x16AA0C | ||
9027 | #define _MG_PLL_FRAC_LOCK_PORT4 0x16BA0C | ||
9028 | #define MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 (1 << 18) | ||
9029 | #define MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 (1 << 16) | ||
9030 | #define MG_PLL_FRAC_LOCK_LOCKTHRESH(x) ((x) << 11) | ||
9031 | #define MG_PLL_FRAC_LOCK_DCODITHEREN (1 << 10) | ||
9032 | #define MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN (1 << 8) | ||
9033 | #define MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(x) ((x) << 0) | ||
9034 | #define MG_PLL_FRAC_LOCK(port) _MMIO_PORT((port) - PORT_C, \ | ||
9035 | _MG_PLL_FRAC_LOCK_PORT1, \ | ||
9036 | _MG_PLL_FRAC_LOCK_PORT2) | ||
9037 | |||
9038 | #define _MG_PLL_SSC_PORT1 0x168A10 | ||
9039 | #define _MG_PLL_SSC_PORT2 0x169A10 | ||
9040 | #define _MG_PLL_SSC_PORT3 0x16AA10 | ||
9041 | #define _MG_PLL_SSC_PORT4 0x16BA10 | ||
9042 | #define MG_PLL_SSC_EN (1 << 28) | ||
9043 | #define MG_PLL_SSC_TYPE(x) ((x) << 26) | ||
9044 | #define MG_PLL_SSC_STEPLENGTH(x) ((x) << 16) | ||
9045 | #define MG_PLL_SSC_STEPNUM(x) ((x) << 10) | ||
9046 | #define MG_PLL_SSC_FLLEN (1 << 9) | ||
9047 | #define MG_PLL_SSC_STEPSIZE(x) ((x) << 0) | ||
9048 | #define MG_PLL_SSC(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_SSC_PORT1, \ | ||
9049 | _MG_PLL_SSC_PORT2) | ||
9050 | |||
9051 | #define _MG_PLL_BIAS_PORT1 0x168A14 | ||
9052 | #define _MG_PLL_BIAS_PORT2 0x169A14 | ||
9053 | #define _MG_PLL_BIAS_PORT3 0x16AA14 | ||
9054 | #define _MG_PLL_BIAS_PORT4 0x16BA14 | ||
9055 | #define MG_PLL_BIAS_BIAS_GB_SEL(x) ((x) << 30) | ||
9056 | #define MG_PLL_BIAS_INIT_DCOAMP(x) ((x) << 24) | ||
9057 | #define MG_PLL_BIAS_BIAS_BONUS(x) ((x) << 16) | ||
9058 | #define MG_PLL_BIAS_BIASCAL_EN (1 << 15) | ||
9059 | #define MG_PLL_BIAS_CTRIM(x) ((x) << 8) | ||
9060 | #define MG_PLL_BIAS_VREF_RDAC(x) ((x) << 5) | ||
9061 | #define MG_PLL_BIAS_IREFTRIM(x) ((x) << 0) | ||
9062 | #define MG_PLL_BIAS(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_BIAS_PORT1, \ | ||
9063 | _MG_PLL_BIAS_PORT2) | ||
9064 | |||
9065 | #define _MG_PLL_TDC_COLDST_BIAS_PORT1 0x168A18 | ||
9066 | #define _MG_PLL_TDC_COLDST_BIAS_PORT2 0x169A18 | ||
9067 | #define _MG_PLL_TDC_COLDST_BIAS_PORT3 0x16AA18 | ||
9068 | #define _MG_PLL_TDC_COLDST_BIAS_PORT4 0x16BA18 | ||
9069 | #define MG_PLL_TDC_COLDST_IREFINT_EN (1 << 27) | ||
9070 | #define MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(x) ((x) << 17) | ||
9071 | #define MG_PLL_TDC_COLDST_COLDSTART (1 << 16) | ||
9072 | #define MG_PLL_TDC_TDCOVCCORR_EN (1 << 2) | ||
9073 | #define MG_PLL_TDC_TDCSEL(x) ((x) << 0) | ||
9074 | #define MG_PLL_TDC_COLDST_BIAS(port) _MMIO_PORT((port) - PORT_C, \ | ||
9075 | _MG_PLL_TDC_COLDST_BIAS_PORT1, \ | ||
9076 | _MG_PLL_TDC_COLDST_BIAS_PORT2) | ||
9077 | |||
8873 | #define _CNL_DPLL0_CFGCR0 0x6C000 | 9078 | #define _CNL_DPLL0_CFGCR0 0x6C000 |
8874 | #define _CNL_DPLL1_CFGCR0 0x6C080 | 9079 | #define _CNL_DPLL1_CFGCR0 0x6C080 |
8875 | #define DPLL_CFGCR0_HDMI_MODE (1 << 30) | 9080 | #define DPLL_CFGCR0_HDMI_MODE (1 << 30) |
8876 | #define DPLL_CFGCR0_SSC_ENABLE (1 << 29) | 9081 | #define DPLL_CFGCR0_SSC_ENABLE (1 << 29) |
9082 | #define DPLL_CFGCR0_SSC_ENABLE_ICL (1 << 25) | ||
8877 | #define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25) | 9083 | #define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25) |
8878 | #define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25) | 9084 | #define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25) |
8879 | #define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25) | 9085 | #define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25) |
@@ -8907,8 +9113,19 @@ enum skl_power_gate { | |||
8907 | #define DPLL_CFGCR1_PDIV_5 (4 << 2) | 9113 | #define DPLL_CFGCR1_PDIV_5 (4 << 2) |
8908 | #define DPLL_CFGCR1_PDIV_7 (8 << 2) | 9114 | #define DPLL_CFGCR1_PDIV_7 (8 << 2) |
8909 | #define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0) | 9115 | #define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0) |
9116 | #define DPLL_CFGCR1_CENTRAL_FREQ_8400 (3 << 0) | ||
8910 | #define CNL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1) | 9117 | #define CNL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1) |
8911 | 9118 | ||
9119 | #define _ICL_DPLL0_CFGCR0 0x164000 | ||
9120 | #define _ICL_DPLL1_CFGCR0 0x164080 | ||
9121 | #define ICL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR0, \ | ||
9122 | _ICL_DPLL1_CFGCR0) | ||
9123 | |||
9124 | #define _ICL_DPLL0_CFGCR1 0x164004 | ||
9125 | #define _ICL_DPLL1_CFGCR1 0x164084 | ||
9126 | #define ICL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR1, \ | ||
9127 | _ICL_DPLL1_CFGCR1) | ||
9128 | |||
8912 | /* BXT display engine PLL */ | 9129 | /* BXT display engine PLL */ |
8913 | #define BXT_DE_PLL_CTL _MMIO(0x6d000) | 9130 | #define BXT_DE_PLL_CTL _MMIO(0x6d000) |
8914 | #define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */ | 9131 | #define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */ |
@@ -9680,6 +9897,13 @@ enum skl_power_gate { | |||
9680 | #define GEN9_MFX1_MOCS(i) _MMIO(0xca00 + (i) * 4) /* Media 1 MOCS registers */ | 9897 | #define GEN9_MFX1_MOCS(i) _MMIO(0xca00 + (i) * 4) /* Media 1 MOCS registers */ |
9681 | #define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ | 9898 | #define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ |
9682 | #define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ | 9899 | #define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ |
9900 | /* Media decoder 2 MOCS registers */ | ||
9901 | #define GEN11_MFX2_MOCS(i) _MMIO(0x10000 + (i) * 4) | ||
9902 | |||
9903 | #define GEN10_SCRATCH_LNCF2 _MMIO(0xb0a0) | ||
9904 | #define PMFLUSHDONE_LNICRSDROP (1 << 20) | ||
9905 | #define PMFLUSH_GAPL3UNBLOCK (1 << 21) | ||
9906 | #define PMFLUSHDONE_LNEBLK (1 << 22) | ||
9683 | 9907 | ||
9684 | /* gamt regs */ | 9908 | /* gamt regs */ |
9685 | #define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4) | 9909 | #define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4) |
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 9ca9c24b4421..8928894dd9c7 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c | |||
@@ -49,7 +49,7 @@ static const char *i915_fence_get_timeline_name(struct dma_fence *fence) | |||
49 | if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) | 49 | if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) |
50 | return "signaled"; | 50 | return "signaled"; |
51 | 51 | ||
52 | return to_request(fence)->timeline->common->name; | 52 | return to_request(fence)->timeline->name; |
53 | } | 53 | } |
54 | 54 | ||
55 | static bool i915_fence_signaled(struct dma_fence *fence) | 55 | static bool i915_fence_signaled(struct dma_fence *fence) |
@@ -125,22 +125,22 @@ i915_dependency_free(struct drm_i915_private *i915, | |||
125 | } | 125 | } |
126 | 126 | ||
127 | static void | 127 | static void |
128 | __i915_priotree_add_dependency(struct i915_priotree *pt, | 128 | __i915_sched_node_add_dependency(struct i915_sched_node *node, |
129 | struct i915_priotree *signal, | 129 | struct i915_sched_node *signal, |
130 | struct i915_dependency *dep, | 130 | struct i915_dependency *dep, |
131 | unsigned long flags) | 131 | unsigned long flags) |
132 | { | 132 | { |
133 | INIT_LIST_HEAD(&dep->dfs_link); | 133 | INIT_LIST_HEAD(&dep->dfs_link); |
134 | list_add(&dep->wait_link, &signal->waiters_list); | 134 | list_add(&dep->wait_link, &signal->waiters_list); |
135 | list_add(&dep->signal_link, &pt->signalers_list); | 135 | list_add(&dep->signal_link, &node->signalers_list); |
136 | dep->signaler = signal; | 136 | dep->signaler = signal; |
137 | dep->flags = flags; | 137 | dep->flags = flags; |
138 | } | 138 | } |
139 | 139 | ||
140 | static int | 140 | static int |
141 | i915_priotree_add_dependency(struct drm_i915_private *i915, | 141 | i915_sched_node_add_dependency(struct drm_i915_private *i915, |
142 | struct i915_priotree *pt, | 142 | struct i915_sched_node *node, |
143 | struct i915_priotree *signal) | 143 | struct i915_sched_node *signal) |
144 | { | 144 | { |
145 | struct i915_dependency *dep; | 145 | struct i915_dependency *dep; |
146 | 146 | ||
@@ -148,16 +148,18 @@ i915_priotree_add_dependency(struct drm_i915_private *i915, | |||
148 | if (!dep) | 148 | if (!dep) |
149 | return -ENOMEM; | 149 | return -ENOMEM; |
150 | 150 | ||
151 | __i915_priotree_add_dependency(pt, signal, dep, I915_DEPENDENCY_ALLOC); | 151 | __i915_sched_node_add_dependency(node, signal, dep, |
152 | I915_DEPENDENCY_ALLOC); | ||
152 | return 0; | 153 | return 0; |
153 | } | 154 | } |
154 | 155 | ||
155 | static void | 156 | static void |
156 | i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt) | 157 | i915_sched_node_fini(struct drm_i915_private *i915, |
158 | struct i915_sched_node *node) | ||
157 | { | 159 | { |
158 | struct i915_dependency *dep, *next; | 160 | struct i915_dependency *dep, *tmp; |
159 | 161 | ||
160 | GEM_BUG_ON(!list_empty(&pt->link)); | 162 | GEM_BUG_ON(!list_empty(&node->link)); |
161 | 163 | ||
162 | /* | 164 | /* |
163 | * Everyone we depended upon (the fences we wait to be signaled) | 165 | * Everyone we depended upon (the fences we wait to be signaled) |
@@ -165,8 +167,8 @@ i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt) | |||
165 | * However, retirement is run independently on each timeline and | 167 | * However, retirement is run independently on each timeline and |
166 | * so we may be called out-of-order. | 168 | * so we may be called out-of-order. |
167 | */ | 169 | */ |
168 | list_for_each_entry_safe(dep, next, &pt->signalers_list, signal_link) { | 170 | list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) { |
169 | GEM_BUG_ON(!i915_priotree_signaled(dep->signaler)); | 171 | GEM_BUG_ON(!i915_sched_node_signaled(dep->signaler)); |
170 | GEM_BUG_ON(!list_empty(&dep->dfs_link)); | 172 | GEM_BUG_ON(!list_empty(&dep->dfs_link)); |
171 | 173 | ||
172 | list_del(&dep->wait_link); | 174 | list_del(&dep->wait_link); |
@@ -175,8 +177,8 @@ i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt) | |||
175 | } | 177 | } |
176 | 178 | ||
177 | /* Remove ourselves from everyone who depends upon us */ | 179 | /* Remove ourselves from everyone who depends upon us */ |
178 | list_for_each_entry_safe(dep, next, &pt->waiters_list, wait_link) { | 180 | list_for_each_entry_safe(dep, tmp, &node->waiters_list, wait_link) { |
179 | GEM_BUG_ON(dep->signaler != pt); | 181 | GEM_BUG_ON(dep->signaler != node); |
180 | GEM_BUG_ON(!list_empty(&dep->dfs_link)); | 182 | GEM_BUG_ON(!list_empty(&dep->dfs_link)); |
181 | 183 | ||
182 | list_del(&dep->signal_link); | 184 | list_del(&dep->signal_link); |
@@ -186,17 +188,18 @@ i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt) | |||
186 | } | 188 | } |
187 | 189 | ||
188 | static void | 190 | static void |
189 | i915_priotree_init(struct i915_priotree *pt) | 191 | i915_sched_node_init(struct i915_sched_node *node) |
190 | { | 192 | { |
191 | INIT_LIST_HEAD(&pt->signalers_list); | 193 | INIT_LIST_HEAD(&node->signalers_list); |
192 | INIT_LIST_HEAD(&pt->waiters_list); | 194 | INIT_LIST_HEAD(&node->waiters_list); |
193 | INIT_LIST_HEAD(&pt->link); | 195 | INIT_LIST_HEAD(&node->link); |
194 | pt->priority = I915_PRIORITY_INVALID; | 196 | node->attr.priority = I915_PRIORITY_INVALID; |
195 | } | 197 | } |
196 | 198 | ||
197 | static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) | 199 | static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) |
198 | { | 200 | { |
199 | struct intel_engine_cs *engine; | 201 | struct intel_engine_cs *engine; |
202 | struct i915_timeline *timeline; | ||
200 | enum intel_engine_id id; | 203 | enum intel_engine_id id; |
201 | int ret; | 204 | int ret; |
202 | 205 | ||
@@ -211,34 +214,33 @@ static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) | |||
211 | 214 | ||
212 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ | 215 | /* If the seqno wraps around, we need to clear the breadcrumb rbtree */ |
213 | for_each_engine(engine, i915, id) { | 216 | for_each_engine(engine, i915, id) { |
214 | struct i915_gem_timeline *timeline; | ||
215 | struct intel_timeline *tl = engine->timeline; | ||
216 | |||
217 | GEM_TRACE("%s seqno %d (current %d) -> %d\n", | 217 | GEM_TRACE("%s seqno %d (current %d) -> %d\n", |
218 | engine->name, | 218 | engine->name, |
219 | tl->seqno, | 219 | engine->timeline.seqno, |
220 | intel_engine_get_seqno(engine), | 220 | intel_engine_get_seqno(engine), |
221 | seqno); | 221 | seqno); |
222 | 222 | ||
223 | if (!i915_seqno_passed(seqno, tl->seqno)) { | 223 | if (!i915_seqno_passed(seqno, engine->timeline.seqno)) { |
224 | /* Flush any waiters before we reuse the seqno */ | 224 | /* Flush any waiters before we reuse the seqno */ |
225 | intel_engine_disarm_breadcrumbs(engine); | 225 | intel_engine_disarm_breadcrumbs(engine); |
226 | intel_engine_init_hangcheck(engine); | ||
226 | GEM_BUG_ON(!list_empty(&engine->breadcrumbs.signals)); | 227 | GEM_BUG_ON(!list_empty(&engine->breadcrumbs.signals)); |
227 | } | 228 | } |
228 | 229 | ||
229 | /* Check we are idle before we fiddle with hw state! */ | 230 | /* Check we are idle before we fiddle with hw state! */ |
230 | GEM_BUG_ON(!intel_engine_is_idle(engine)); | 231 | GEM_BUG_ON(!intel_engine_is_idle(engine)); |
231 | GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request)); | 232 | GEM_BUG_ON(i915_gem_active_isset(&engine->timeline.last_request)); |
232 | 233 | ||
233 | /* Finally reset hw state */ | 234 | /* Finally reset hw state */ |
234 | intel_engine_init_global_seqno(engine, seqno); | 235 | intel_engine_init_global_seqno(engine, seqno); |
235 | tl->seqno = seqno; | 236 | engine->timeline.seqno = seqno; |
236 | |||
237 | list_for_each_entry(timeline, &i915->gt.timelines, link) | ||
238 | memset(timeline->engine[id].global_sync, 0, | ||
239 | sizeof(timeline->engine[id].global_sync)); | ||
240 | } | 237 | } |
241 | 238 | ||
239 | list_for_each_entry(timeline, &i915->gt.timelines, link) | ||
240 | memset(timeline->global_sync, 0, sizeof(timeline->global_sync)); | ||
241 | |||
242 | i915->gt.request_serial = seqno; | ||
243 | |||
242 | return 0; | 244 | return 0; |
243 | } | 245 | } |
244 | 246 | ||
@@ -255,18 +257,22 @@ int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno) | |||
255 | return reset_all_global_seqno(i915, seqno - 1); | 257 | return reset_all_global_seqno(i915, seqno - 1); |
256 | } | 258 | } |
257 | 259 | ||
258 | static int reserve_engine(struct intel_engine_cs *engine) | 260 | static int reserve_gt(struct drm_i915_private *i915) |
259 | { | 261 | { |
260 | struct drm_i915_private *i915 = engine->i915; | ||
261 | u32 active = ++engine->timeline->inflight_seqnos; | ||
262 | u32 seqno = engine->timeline->seqno; | ||
263 | int ret; | 262 | int ret; |
264 | 263 | ||
265 | /* Reservation is fine until we need to wrap around */ | 264 | /* |
266 | if (unlikely(add_overflows(seqno, active))) { | 265 | * Reservation is fine until we may need to wrap around |
266 | * | ||
267 | * By incrementing the serial for every request, we know that no | ||
268 | * individual engine may exceed that serial (as each is reset to 0 | ||
269 | * on any wrap). This protects even the most pessimistic of migrations | ||
270 | * of every request from all engines onto just one. | ||
271 | */ | ||
272 | while (unlikely(++i915->gt.request_serial == 0)) { | ||
267 | ret = reset_all_global_seqno(i915, 0); | 273 | ret = reset_all_global_seqno(i915, 0); |
268 | if (ret) { | 274 | if (ret) { |
269 | engine->timeline->inflight_seqnos--; | 275 | i915->gt.request_serial--; |
270 | return ret; | 276 | return ret; |
271 | } | 277 | } |
272 | } | 278 | } |
@@ -277,15 +283,11 @@ static int reserve_engine(struct intel_engine_cs *engine) | |||
277 | return 0; | 283 | return 0; |
278 | } | 284 | } |
279 | 285 | ||
280 | static void unreserve_engine(struct intel_engine_cs *engine) | 286 | static void unreserve_gt(struct drm_i915_private *i915) |
281 | { | 287 | { |
282 | struct drm_i915_private *i915 = engine->i915; | 288 | GEM_BUG_ON(!i915->gt.active_requests); |
283 | |||
284 | if (!--i915->gt.active_requests) | 289 | if (!--i915->gt.active_requests) |
285 | i915_gem_park(i915); | 290 | i915_gem_park(i915); |
286 | |||
287 | GEM_BUG_ON(!engine->timeline->inflight_seqnos); | ||
288 | engine->timeline->inflight_seqnos--; | ||
289 | } | 291 | } |
290 | 292 | ||
291 | void i915_gem_retire_noop(struct i915_gem_active *active, | 293 | void i915_gem_retire_noop(struct i915_gem_active *active, |
@@ -296,6 +298,7 @@ void i915_gem_retire_noop(struct i915_gem_active *active, | |||
296 | 298 | ||
297 | static void advance_ring(struct i915_request *request) | 299 | static void advance_ring(struct i915_request *request) |
298 | { | 300 | { |
301 | struct intel_ring *ring = request->ring; | ||
299 | unsigned int tail; | 302 | unsigned int tail; |
300 | 303 | ||
301 | /* | 304 | /* |
@@ -307,7 +310,8 @@ static void advance_ring(struct i915_request *request) | |||
307 | * Note this requires that we are always called in request | 310 | * Note this requires that we are always called in request |
308 | * completion order. | 311 | * completion order. |
309 | */ | 312 | */ |
310 | if (list_is_last(&request->ring_link, &request->ring->request_list)) { | 313 | GEM_BUG_ON(!list_is_first(&request->ring_link, &ring->request_list)); |
314 | if (list_is_last(&request->ring_link, &ring->request_list)) { | ||
311 | /* | 315 | /* |
312 | * We may race here with execlists resubmitting this request | 316 | * We may race here with execlists resubmitting this request |
313 | * as we retire it. The resubmission will move the ring->tail | 317 | * as we retire it. The resubmission will move the ring->tail |
@@ -317,12 +321,13 @@ static void advance_ring(struct i915_request *request) | |||
317 | * noops - they are safe to be replayed on a reset. | 321 | * noops - they are safe to be replayed on a reset. |
318 | */ | 322 | */ |
319 | tail = READ_ONCE(request->tail); | 323 | tail = READ_ONCE(request->tail); |
324 | list_del(&ring->active_link); | ||
320 | } else { | 325 | } else { |
321 | tail = request->postfix; | 326 | tail = request->postfix; |
322 | } | 327 | } |
323 | list_del(&request->ring_link); | 328 | list_del_init(&request->ring_link); |
324 | 329 | ||
325 | request->ring->head = tail; | 330 | ring->head = tail; |
326 | } | 331 | } |
327 | 332 | ||
328 | static void free_capture_list(struct i915_request *request) | 333 | static void free_capture_list(struct i915_request *request) |
@@ -338,31 +343,84 @@ static void free_capture_list(struct i915_request *request) | |||
338 | } | 343 | } |
339 | } | 344 | } |
340 | 345 | ||
346 | static void __retire_engine_request(struct intel_engine_cs *engine, | ||
347 | struct i915_request *rq) | ||
348 | { | ||
349 | GEM_TRACE("%s(%s) fence %llx:%d, global=%d, current %d\n", | ||
350 | __func__, engine->name, | ||
351 | rq->fence.context, rq->fence.seqno, | ||
352 | rq->global_seqno, | ||
353 | intel_engine_get_seqno(engine)); | ||
354 | |||
355 | GEM_BUG_ON(!i915_request_completed(rq)); | ||
356 | |||
357 | local_irq_disable(); | ||
358 | |||
359 | spin_lock(&engine->timeline.lock); | ||
360 | GEM_BUG_ON(!list_is_first(&rq->link, &engine->timeline.requests)); | ||
361 | list_del_init(&rq->link); | ||
362 | spin_unlock(&engine->timeline.lock); | ||
363 | |||
364 | spin_lock(&rq->lock); | ||
365 | if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) | ||
366 | dma_fence_signal_locked(&rq->fence); | ||
367 | if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags)) | ||
368 | intel_engine_cancel_signaling(rq); | ||
369 | if (rq->waitboost) { | ||
370 | GEM_BUG_ON(!atomic_read(&rq->i915->gt_pm.rps.num_waiters)); | ||
371 | atomic_dec(&rq->i915->gt_pm.rps.num_waiters); | ||
372 | } | ||
373 | spin_unlock(&rq->lock); | ||
374 | |||
375 | local_irq_enable(); | ||
376 | |||
377 | /* | ||
378 | * The backing object for the context is done after switching to the | ||
379 | * *next* context. Therefore we cannot retire the previous context until | ||
380 | * the next context has already started running. However, since we | ||
381 | * cannot take the required locks at i915_request_submit() we | ||
382 | * defer the unpinning of the active context to now, retirement of | ||
383 | * the subsequent request. | ||
384 | */ | ||
385 | if (engine->last_retired_context) | ||
386 | intel_context_unpin(engine->last_retired_context, engine); | ||
387 | engine->last_retired_context = rq->ctx; | ||
388 | } | ||
389 | |||
390 | static void __retire_engine_upto(struct intel_engine_cs *engine, | ||
391 | struct i915_request *rq) | ||
392 | { | ||
393 | struct i915_request *tmp; | ||
394 | |||
395 | if (list_empty(&rq->link)) | ||
396 | return; | ||
397 | |||
398 | do { | ||
399 | tmp = list_first_entry(&engine->timeline.requests, | ||
400 | typeof(*tmp), link); | ||
401 | |||
402 | GEM_BUG_ON(tmp->engine != engine); | ||
403 | __retire_engine_request(engine, tmp); | ||
404 | } while (tmp != rq); | ||
405 | } | ||
406 | |||
341 | static void i915_request_retire(struct i915_request *request) | 407 | static void i915_request_retire(struct i915_request *request) |
342 | { | 408 | { |
343 | struct intel_engine_cs *engine = request->engine; | ||
344 | struct i915_gem_active *active, *next; | 409 | struct i915_gem_active *active, *next; |
345 | 410 | ||
346 | GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n", | 411 | GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n", |
347 | engine->name, | 412 | request->engine->name, |
348 | request->fence.context, request->fence.seqno, | 413 | request->fence.context, request->fence.seqno, |
349 | request->global_seqno, | 414 | request->global_seqno, |
350 | intel_engine_get_seqno(engine)); | 415 | intel_engine_get_seqno(request->engine)); |
351 | 416 | ||
352 | lockdep_assert_held(&request->i915->drm.struct_mutex); | 417 | lockdep_assert_held(&request->i915->drm.struct_mutex); |
353 | GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); | 418 | GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); |
354 | GEM_BUG_ON(!i915_request_completed(request)); | 419 | GEM_BUG_ON(!i915_request_completed(request)); |
355 | GEM_BUG_ON(!request->i915->gt.active_requests); | ||
356 | 420 | ||
357 | trace_i915_request_retire(request); | 421 | trace_i915_request_retire(request); |
358 | 422 | ||
359 | spin_lock_irq(&engine->timeline->lock); | ||
360 | list_del_init(&request->link); | ||
361 | spin_unlock_irq(&engine->timeline->lock); | ||
362 | |||
363 | unreserve_engine(request->engine); | ||
364 | advance_ring(request); | 423 | advance_ring(request); |
365 | |||
366 | free_capture_list(request); | 424 | free_capture_list(request); |
367 | 425 | ||
368 | /* | 426 | /* |
@@ -398,65 +456,53 @@ static void i915_request_retire(struct i915_request *request) | |||
398 | 456 | ||
399 | /* Retirement decays the ban score as it is a sign of ctx progress */ | 457 | /* Retirement decays the ban score as it is a sign of ctx progress */ |
400 | atomic_dec_if_positive(&request->ctx->ban_score); | 458 | atomic_dec_if_positive(&request->ctx->ban_score); |
459 | intel_context_unpin(request->ctx, request->engine); | ||
401 | 460 | ||
402 | /* | 461 | __retire_engine_upto(request->engine, request); |
403 | * The backing object for the context is done after switching to the | ||
404 | * *next* context. Therefore we cannot retire the previous context until | ||
405 | * the next context has already started running. However, since we | ||
406 | * cannot take the required locks at i915_request_submit() we | ||
407 | * defer the unpinning of the active context to now, retirement of | ||
408 | * the subsequent request. | ||
409 | */ | ||
410 | if (engine->last_retired_context) | ||
411 | engine->context_unpin(engine, engine->last_retired_context); | ||
412 | engine->last_retired_context = request->ctx; | ||
413 | 462 | ||
414 | spin_lock_irq(&request->lock); | 463 | unreserve_gt(request->i915); |
415 | if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags)) | ||
416 | dma_fence_signal_locked(&request->fence); | ||
417 | if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) | ||
418 | intel_engine_cancel_signaling(request); | ||
419 | if (request->waitboost) { | ||
420 | GEM_BUG_ON(!atomic_read(&request->i915->gt_pm.rps.num_waiters)); | ||
421 | atomic_dec(&request->i915->gt_pm.rps.num_waiters); | ||
422 | } | ||
423 | spin_unlock_irq(&request->lock); | ||
424 | 464 | ||
425 | i915_priotree_fini(request->i915, &request->priotree); | 465 | i915_sched_node_fini(request->i915, &request->sched); |
426 | i915_request_put(request); | 466 | i915_request_put(request); |
427 | } | 467 | } |
428 | 468 | ||
429 | void i915_request_retire_upto(struct i915_request *rq) | 469 | void i915_request_retire_upto(struct i915_request *rq) |
430 | { | 470 | { |
431 | struct intel_engine_cs *engine = rq->engine; | 471 | struct intel_ring *ring = rq->ring; |
432 | struct i915_request *tmp; | 472 | struct i915_request *tmp; |
433 | 473 | ||
474 | GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n", | ||
475 | rq->engine->name, | ||
476 | rq->fence.context, rq->fence.seqno, | ||
477 | rq->global_seqno, | ||
478 | intel_engine_get_seqno(rq->engine)); | ||
479 | |||
434 | lockdep_assert_held(&rq->i915->drm.struct_mutex); | 480 | lockdep_assert_held(&rq->i915->drm.struct_mutex); |
435 | GEM_BUG_ON(!i915_request_completed(rq)); | 481 | GEM_BUG_ON(!i915_request_completed(rq)); |
436 | 482 | ||
437 | if (list_empty(&rq->link)) | 483 | if (list_empty(&rq->ring_link)) |
438 | return; | 484 | return; |
439 | 485 | ||
440 | do { | 486 | do { |
441 | tmp = list_first_entry(&engine->timeline->requests, | 487 | tmp = list_first_entry(&ring->request_list, |
442 | typeof(*tmp), link); | 488 | typeof(*tmp), ring_link); |
443 | 489 | ||
444 | i915_request_retire(tmp); | 490 | i915_request_retire(tmp); |
445 | } while (tmp != rq); | 491 | } while (tmp != rq); |
446 | } | 492 | } |
447 | 493 | ||
448 | static u32 timeline_get_seqno(struct intel_timeline *tl) | 494 | static u32 timeline_get_seqno(struct i915_timeline *tl) |
449 | { | 495 | { |
450 | return ++tl->seqno; | 496 | return ++tl->seqno; |
451 | } | 497 | } |
452 | 498 | ||
453 | static void move_to_timeline(struct i915_request *request, | 499 | static void move_to_timeline(struct i915_request *request, |
454 | struct intel_timeline *timeline) | 500 | struct i915_timeline *timeline) |
455 | { | 501 | { |
456 | GEM_BUG_ON(request->timeline == request->engine->timeline); | 502 | GEM_BUG_ON(request->timeline == &request->engine->timeline); |
457 | lockdep_assert_held(&request->engine->timeline->lock); | 503 | lockdep_assert_held(&request->engine->timeline.lock); |
458 | 504 | ||
459 | spin_lock(&request->timeline->lock); | 505 | spin_lock_nested(&request->timeline->lock, SINGLE_DEPTH_NESTING); |
460 | list_move_tail(&request->link, &timeline->requests); | 506 | list_move_tail(&request->link, &timeline->requests); |
461 | spin_unlock(&request->timeline->lock); | 507 | spin_unlock(&request->timeline->lock); |
462 | } | 508 | } |
@@ -469,15 +515,15 @@ void __i915_request_submit(struct i915_request *request) | |||
469 | GEM_TRACE("%s fence %llx:%d -> global=%d, current %d\n", | 515 | GEM_TRACE("%s fence %llx:%d -> global=%d, current %d\n", |
470 | engine->name, | 516 | engine->name, |
471 | request->fence.context, request->fence.seqno, | 517 | request->fence.context, request->fence.seqno, |
472 | engine->timeline->seqno + 1, | 518 | engine->timeline.seqno + 1, |
473 | intel_engine_get_seqno(engine)); | 519 | intel_engine_get_seqno(engine)); |
474 | 520 | ||
475 | GEM_BUG_ON(!irqs_disabled()); | 521 | GEM_BUG_ON(!irqs_disabled()); |
476 | lockdep_assert_held(&engine->timeline->lock); | 522 | lockdep_assert_held(&engine->timeline.lock); |
477 | 523 | ||
478 | GEM_BUG_ON(request->global_seqno); | 524 | GEM_BUG_ON(request->global_seqno); |
479 | 525 | ||
480 | seqno = timeline_get_seqno(engine->timeline); | 526 | seqno = timeline_get_seqno(&engine->timeline); |
481 | GEM_BUG_ON(!seqno); | 527 | GEM_BUG_ON(!seqno); |
482 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); | 528 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); |
483 | 529 | ||
@@ -492,7 +538,7 @@ void __i915_request_submit(struct i915_request *request) | |||
492 | request->ring->vaddr + request->postfix); | 538 | request->ring->vaddr + request->postfix); |
493 | 539 | ||
494 | /* Transfer from per-context onto the global per-engine timeline */ | 540 | /* Transfer from per-context onto the global per-engine timeline */ |
495 | move_to_timeline(request, engine->timeline); | 541 | move_to_timeline(request, &engine->timeline); |
496 | 542 | ||
497 | trace_i915_request_execute(request); | 543 | trace_i915_request_execute(request); |
498 | 544 | ||
@@ -505,11 +551,11 @@ void i915_request_submit(struct i915_request *request) | |||
505 | unsigned long flags; | 551 | unsigned long flags; |
506 | 552 | ||
507 | /* Will be called from irq-context when using foreign fences. */ | 553 | /* Will be called from irq-context when using foreign fences. */ |
508 | spin_lock_irqsave(&engine->timeline->lock, flags); | 554 | spin_lock_irqsave(&engine->timeline.lock, flags); |
509 | 555 | ||
510 | __i915_request_submit(request); | 556 | __i915_request_submit(request); |
511 | 557 | ||
512 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 558 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
513 | } | 559 | } |
514 | 560 | ||
515 | void __i915_request_unsubmit(struct i915_request *request) | 561 | void __i915_request_unsubmit(struct i915_request *request) |
@@ -523,17 +569,17 @@ void __i915_request_unsubmit(struct i915_request *request) | |||
523 | intel_engine_get_seqno(engine)); | 569 | intel_engine_get_seqno(engine)); |
524 | 570 | ||
525 | GEM_BUG_ON(!irqs_disabled()); | 571 | GEM_BUG_ON(!irqs_disabled()); |
526 | lockdep_assert_held(&engine->timeline->lock); | 572 | lockdep_assert_held(&engine->timeline.lock); |
527 | 573 | ||
528 | /* | 574 | /* |
529 | * Only unwind in reverse order, required so that the per-context list | 575 | * Only unwind in reverse order, required so that the per-context list |
530 | * is kept in seqno/ring order. | 576 | * is kept in seqno/ring order. |
531 | */ | 577 | */ |
532 | GEM_BUG_ON(!request->global_seqno); | 578 | GEM_BUG_ON(!request->global_seqno); |
533 | GEM_BUG_ON(request->global_seqno != engine->timeline->seqno); | 579 | GEM_BUG_ON(request->global_seqno != engine->timeline.seqno); |
534 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), | 580 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), |
535 | request->global_seqno)); | 581 | request->global_seqno)); |
536 | engine->timeline->seqno--; | 582 | engine->timeline.seqno--; |
537 | 583 | ||
538 | /* We may be recursing from the signal callback of another i915 fence */ | 584 | /* We may be recursing from the signal callback of another i915 fence */ |
539 | spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); | 585 | spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); |
@@ -560,11 +606,11 @@ void i915_request_unsubmit(struct i915_request *request) | |||
560 | unsigned long flags; | 606 | unsigned long flags; |
561 | 607 | ||
562 | /* Will be called from irq-context when using foreign fences. */ | 608 | /* Will be called from irq-context when using foreign fences. */ |
563 | spin_lock_irqsave(&engine->timeline->lock, flags); | 609 | spin_lock_irqsave(&engine->timeline.lock, flags); |
564 | 610 | ||
565 | __i915_request_unsubmit(request); | 611 | __i915_request_unsubmit(request); |
566 | 612 | ||
567 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 613 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
568 | } | 614 | } |
569 | 615 | ||
570 | static int __i915_sw_fence_call | 616 | static int __i915_sw_fence_call |
@@ -635,12 +681,12 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) | |||
635 | * GGTT space, so do this first before we reserve a seqno for | 681 | * GGTT space, so do this first before we reserve a seqno for |
636 | * ourselves. | 682 | * ourselves. |
637 | */ | 683 | */ |
638 | ring = engine->context_pin(engine, ctx); | 684 | ring = intel_context_pin(ctx, engine); |
639 | if (IS_ERR(ring)) | 685 | if (IS_ERR(ring)) |
640 | return ERR_CAST(ring); | 686 | return ERR_CAST(ring); |
641 | GEM_BUG_ON(!ring); | 687 | GEM_BUG_ON(!ring); |
642 | 688 | ||
643 | ret = reserve_engine(engine); | 689 | ret = reserve_gt(i915); |
644 | if (ret) | 690 | if (ret) |
645 | goto err_unpin; | 691 | goto err_unpin; |
646 | 692 | ||
@@ -648,10 +694,10 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) | |||
648 | if (ret) | 694 | if (ret) |
649 | goto err_unreserve; | 695 | goto err_unreserve; |
650 | 696 | ||
651 | /* Move the oldest request to the slab-cache (if not in use!) */ | 697 | /* Move our oldest request to the slab-cache (if not in use!) */ |
652 | rq = list_first_entry_or_null(&engine->timeline->requests, | 698 | rq = list_first_entry(&ring->request_list, typeof(*rq), ring_link); |
653 | typeof(*rq), link); | 699 | if (!list_is_last(&rq->ring_link, &ring->request_list) && |
654 | if (rq && i915_request_completed(rq)) | 700 | i915_request_completed(rq)) |
655 | i915_request_retire(rq); | 701 | i915_request_retire(rq); |
656 | 702 | ||
657 | /* | 703 | /* |
@@ -711,8 +757,13 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) | |||
711 | } | 757 | } |
712 | } | 758 | } |
713 | 759 | ||
714 | rq->timeline = i915_gem_context_lookup_timeline(ctx, engine); | 760 | INIT_LIST_HEAD(&rq->active_list); |
715 | GEM_BUG_ON(rq->timeline == engine->timeline); | 761 | rq->i915 = i915; |
762 | rq->engine = engine; | ||
763 | rq->ctx = ctx; | ||
764 | rq->ring = ring; | ||
765 | rq->timeline = ring->timeline; | ||
766 | GEM_BUG_ON(rq->timeline == &engine->timeline); | ||
716 | 767 | ||
717 | spin_lock_init(&rq->lock); | 768 | spin_lock_init(&rq->lock); |
718 | dma_fence_init(&rq->fence, | 769 | dma_fence_init(&rq->fence, |
@@ -725,13 +776,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) | |||
725 | i915_sw_fence_init(&i915_request_get(rq)->submit, submit_notify); | 776 | i915_sw_fence_init(&i915_request_get(rq)->submit, submit_notify); |
726 | init_waitqueue_head(&rq->execute); | 777 | init_waitqueue_head(&rq->execute); |
727 | 778 | ||
728 | i915_priotree_init(&rq->priotree); | 779 | i915_sched_node_init(&rq->sched); |
729 | |||
730 | INIT_LIST_HEAD(&rq->active_list); | ||
731 | rq->i915 = i915; | ||
732 | rq->engine = engine; | ||
733 | rq->ctx = ctx; | ||
734 | rq->ring = ring; | ||
735 | 780 | ||
736 | /* No zalloc, must clear what we need by hand */ | 781 | /* No zalloc, must clear what we need by hand */ |
737 | rq->global_seqno = 0; | 782 | rq->global_seqno = 0; |
@@ -768,6 +813,9 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) | |||
768 | if (ret) | 813 | if (ret) |
769 | goto err_unwind; | 814 | goto err_unwind; |
770 | 815 | ||
816 | /* Keep a second pin for the dual retirement along engine and ring */ | ||
817 | __intel_context_pin(rq->ctx, engine); | ||
818 | |||
771 | /* Check that we didn't interrupt ourselves with a new request */ | 819 | /* Check that we didn't interrupt ourselves with a new request */ |
772 | GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno); | 820 | GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno); |
773 | return rq; | 821 | return rq; |
@@ -777,14 +825,14 @@ err_unwind: | |||
777 | 825 | ||
778 | /* Make sure we didn't add ourselves to external state before freeing */ | 826 | /* Make sure we didn't add ourselves to external state before freeing */ |
779 | GEM_BUG_ON(!list_empty(&rq->active_list)); | 827 | GEM_BUG_ON(!list_empty(&rq->active_list)); |
780 | GEM_BUG_ON(!list_empty(&rq->priotree.signalers_list)); | 828 | GEM_BUG_ON(!list_empty(&rq->sched.signalers_list)); |
781 | GEM_BUG_ON(!list_empty(&rq->priotree.waiters_list)); | 829 | GEM_BUG_ON(!list_empty(&rq->sched.waiters_list)); |
782 | 830 | ||
783 | kmem_cache_free(i915->requests, rq); | 831 | kmem_cache_free(i915->requests, rq); |
784 | err_unreserve: | 832 | err_unreserve: |
785 | unreserve_engine(engine); | 833 | unreserve_gt(i915); |
786 | err_unpin: | 834 | err_unpin: |
787 | engine->context_unpin(engine, ctx); | 835 | intel_context_unpin(ctx, engine); |
788 | return ERR_PTR(ret); | 836 | return ERR_PTR(ret); |
789 | } | 837 | } |
790 | 838 | ||
@@ -800,9 +848,9 @@ i915_request_await_request(struct i915_request *to, struct i915_request *from) | |||
800 | return 0; | 848 | return 0; |
801 | 849 | ||
802 | if (to->engine->schedule) { | 850 | if (to->engine->schedule) { |
803 | ret = i915_priotree_add_dependency(to->i915, | 851 | ret = i915_sched_node_add_dependency(to->i915, |
804 | &to->priotree, | 852 | &to->sched, |
805 | &from->priotree); | 853 | &from->sched); |
806 | if (ret < 0) | 854 | if (ret < 0) |
807 | return ret; | 855 | return ret; |
808 | } | 856 | } |
@@ -880,7 +928,7 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence) | |||
880 | 928 | ||
881 | /* Squash repeated waits to the same timelines */ | 929 | /* Squash repeated waits to the same timelines */ |
882 | if (fence->context != rq->i915->mm.unordered_timeline && | 930 | if (fence->context != rq->i915->mm.unordered_timeline && |
883 | intel_timeline_sync_is_later(rq->timeline, fence)) | 931 | i915_timeline_sync_is_later(rq->timeline, fence)) |
884 | continue; | 932 | continue; |
885 | 933 | ||
886 | if (dma_fence_is_i915(fence)) | 934 | if (dma_fence_is_i915(fence)) |
@@ -894,7 +942,7 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence) | |||
894 | 942 | ||
895 | /* Record the latest fence used against each timeline */ | 943 | /* Record the latest fence used against each timeline */ |
896 | if (fence->context != rq->i915->mm.unordered_timeline) | 944 | if (fence->context != rq->i915->mm.unordered_timeline) |
897 | intel_timeline_sync_set(rq->timeline, fence); | 945 | i915_timeline_sync_set(rq->timeline, fence); |
898 | } while (--nchild); | 946 | } while (--nchild); |
899 | 947 | ||
900 | return 0; | 948 | return 0; |
@@ -971,7 +1019,7 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) | |||
971 | { | 1019 | { |
972 | struct intel_engine_cs *engine = request->engine; | 1020 | struct intel_engine_cs *engine = request->engine; |
973 | struct intel_ring *ring = request->ring; | 1021 | struct intel_ring *ring = request->ring; |
974 | struct intel_timeline *timeline = request->timeline; | 1022 | struct i915_timeline *timeline = request->timeline; |
975 | struct i915_request *prev; | 1023 | struct i915_request *prev; |
976 | u32 *cs; | 1024 | u32 *cs; |
977 | int err; | 1025 | int err; |
@@ -1033,10 +1081,10 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) | |||
1033 | i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, | 1081 | i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, |
1034 | &request->submitq); | 1082 | &request->submitq); |
1035 | if (engine->schedule) | 1083 | if (engine->schedule) |
1036 | __i915_priotree_add_dependency(&request->priotree, | 1084 | __i915_sched_node_add_dependency(&request->sched, |
1037 | &prev->priotree, | 1085 | &prev->sched, |
1038 | &request->dep, | 1086 | &request->dep, |
1039 | 0); | 1087 | 0); |
1040 | } | 1088 | } |
1041 | 1089 | ||
1042 | spin_lock_irq(&timeline->lock); | 1090 | spin_lock_irq(&timeline->lock); |
@@ -1047,6 +1095,8 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) | |||
1047 | i915_gem_active_set(&timeline->last_request, request); | 1095 | i915_gem_active_set(&timeline->last_request, request); |
1048 | 1096 | ||
1049 | list_add_tail(&request->ring_link, &ring->request_list); | 1097 | list_add_tail(&request->ring_link, &ring->request_list); |
1098 | if (list_is_first(&request->ring_link, &ring->request_list)) | ||
1099 | list_add(&ring->active_link, &request->i915->gt.active_rings); | ||
1050 | request->emitted_jiffies = jiffies; | 1100 | request->emitted_jiffies = jiffies; |
1051 | 1101 | ||
1052 | /* | 1102 | /* |
@@ -1060,12 +1110,11 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) | |||
1060 | * decide whether to preempt the entire chain so that it is ready to | 1110 | * decide whether to preempt the entire chain so that it is ready to |
1061 | * run at the earliest possible convenience. | 1111 | * run at the earliest possible convenience. |
1062 | */ | 1112 | */ |
1063 | rcu_read_lock(); | 1113 | local_bh_disable(); |
1114 | rcu_read_lock(); /* RCU serialisation for set-wedged protection */ | ||
1064 | if (engine->schedule) | 1115 | if (engine->schedule) |
1065 | engine->schedule(request, request->ctx->priority); | 1116 | engine->schedule(request, &request->ctx->sched); |
1066 | rcu_read_unlock(); | 1117 | rcu_read_unlock(); |
1067 | |||
1068 | local_bh_disable(); | ||
1069 | i915_sw_fence_commit(&request->submit); | 1118 | i915_sw_fence_commit(&request->submit); |
1070 | local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ | 1119 | local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ |
1071 | 1120 | ||
@@ -1354,38 +1403,30 @@ complete: | |||
1354 | return timeout; | 1403 | return timeout; |
1355 | } | 1404 | } |
1356 | 1405 | ||
1357 | static void engine_retire_requests(struct intel_engine_cs *engine) | 1406 | static void ring_retire_requests(struct intel_ring *ring) |
1358 | { | 1407 | { |
1359 | struct i915_request *request, *next; | 1408 | struct i915_request *request, *next; |
1360 | u32 seqno = intel_engine_get_seqno(engine); | ||
1361 | LIST_HEAD(retire); | ||
1362 | 1409 | ||
1363 | spin_lock_irq(&engine->timeline->lock); | ||
1364 | list_for_each_entry_safe(request, next, | 1410 | list_for_each_entry_safe(request, next, |
1365 | &engine->timeline->requests, link) { | 1411 | &ring->request_list, ring_link) { |
1366 | if (!i915_seqno_passed(seqno, request->global_seqno)) | 1412 | if (!i915_request_completed(request)) |
1367 | break; | 1413 | break; |
1368 | 1414 | ||
1369 | list_move_tail(&request->link, &retire); | ||
1370 | } | ||
1371 | spin_unlock_irq(&engine->timeline->lock); | ||
1372 | |||
1373 | list_for_each_entry_safe(request, next, &retire, link) | ||
1374 | i915_request_retire(request); | 1415 | i915_request_retire(request); |
1416 | } | ||
1375 | } | 1417 | } |
1376 | 1418 | ||
1377 | void i915_retire_requests(struct drm_i915_private *i915) | 1419 | void i915_retire_requests(struct drm_i915_private *i915) |
1378 | { | 1420 | { |
1379 | struct intel_engine_cs *engine; | 1421 | struct intel_ring *ring, *tmp; |
1380 | enum intel_engine_id id; | ||
1381 | 1422 | ||
1382 | lockdep_assert_held(&i915->drm.struct_mutex); | 1423 | lockdep_assert_held(&i915->drm.struct_mutex); |
1383 | 1424 | ||
1384 | if (!i915->gt.active_requests) | 1425 | if (!i915->gt.active_requests) |
1385 | return; | 1426 | return; |
1386 | 1427 | ||
1387 | for_each_engine(engine, i915, id) | 1428 | list_for_each_entry_safe(ring, tmp, &i915->gt.active_rings, active_link) |
1388 | engine_retire_requests(engine); | 1429 | ring_retire_requests(ring); |
1389 | } | 1430 | } |
1390 | 1431 | ||
1391 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | 1432 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 7d6eb82eeb91..eddbd4245cb3 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h | |||
@@ -28,13 +28,16 @@ | |||
28 | #include <linux/dma-fence.h> | 28 | #include <linux/dma-fence.h> |
29 | 29 | ||
30 | #include "i915_gem.h" | 30 | #include "i915_gem.h" |
31 | #include "i915_scheduler.h" | ||
31 | #include "i915_sw_fence.h" | 32 | #include "i915_sw_fence.h" |
33 | #include "i915_scheduler.h" | ||
32 | 34 | ||
33 | #include <uapi/drm/i915_drm.h> | 35 | #include <uapi/drm/i915_drm.h> |
34 | 36 | ||
35 | struct drm_file; | 37 | struct drm_file; |
36 | struct drm_i915_gem_object; | 38 | struct drm_i915_gem_object; |
37 | struct i915_request; | 39 | struct i915_request; |
40 | struct i915_timeline; | ||
38 | 41 | ||
39 | struct intel_wait { | 42 | struct intel_wait { |
40 | struct rb_node node; | 43 | struct rb_node node; |
@@ -48,44 +51,6 @@ struct intel_signal_node { | |||
48 | struct list_head link; | 51 | struct list_head link; |
49 | }; | 52 | }; |
50 | 53 | ||
51 | struct i915_dependency { | ||
52 | struct i915_priotree *signaler; | ||
53 | struct list_head signal_link; | ||
54 | struct list_head wait_link; | ||
55 | struct list_head dfs_link; | ||
56 | unsigned long flags; | ||
57 | #define I915_DEPENDENCY_ALLOC BIT(0) | ||
58 | }; | ||
59 | |||
60 | /* | ||
61 | * "People assume that time is a strict progression of cause to effect, but | ||
62 | * actually, from a nonlinear, non-subjective viewpoint, it's more like a big | ||
63 | * ball of wibbly-wobbly, timey-wimey ... stuff." -The Doctor, 2015 | ||
64 | * | ||
65 | * Requests exist in a complex web of interdependencies. Each request | ||
66 | * has to wait for some other request to complete before it is ready to be run | ||
67 | * (e.g. we have to wait until the pixels have been rendering into a texture | ||
68 | * before we can copy from it). We track the readiness of a request in terms | ||
69 | * of fences, but we also need to keep the dependency tree for the lifetime | ||
70 | * of the request (beyond the life of an individual fence). We use the tree | ||
71 | * at various points to reorder the requests whilst keeping the requests | ||
72 | * in order with respect to their various dependencies. | ||
73 | */ | ||
74 | struct i915_priotree { | ||
75 | struct list_head signalers_list; /* those before us, we depend upon */ | ||
76 | struct list_head waiters_list; /* those after us, they depend upon us */ | ||
77 | struct list_head link; | ||
78 | int priority; | ||
79 | }; | ||
80 | |||
81 | enum { | ||
82 | I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1, | ||
83 | I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY, | ||
84 | I915_PRIORITY_MAX = I915_CONTEXT_MAX_USER_PRIORITY + 1, | ||
85 | |||
86 | I915_PRIORITY_INVALID = INT_MIN | ||
87 | }; | ||
88 | |||
89 | struct i915_capture_list { | 54 | struct i915_capture_list { |
90 | struct i915_capture_list *next; | 55 | struct i915_capture_list *next; |
91 | struct i915_vma *vma; | 56 | struct i915_vma *vma; |
@@ -131,7 +96,7 @@ struct i915_request { | |||
131 | struct i915_gem_context *ctx; | 96 | struct i915_gem_context *ctx; |
132 | struct intel_engine_cs *engine; | 97 | struct intel_engine_cs *engine; |
133 | struct intel_ring *ring; | 98 | struct intel_ring *ring; |
134 | struct intel_timeline *timeline; | 99 | struct i915_timeline *timeline; |
135 | struct intel_signal_node signaling; | 100 | struct intel_signal_node signaling; |
136 | 101 | ||
137 | /* | 102 | /* |
@@ -154,7 +119,7 @@ struct i915_request { | |||
154 | * to retirement), i.e. bidirectional dependency information for the | 119 | * to retirement), i.e. bidirectional dependency information for the |
155 | * request not tied to individual fences. | 120 | * request not tied to individual fences. |
156 | */ | 121 | */ |
157 | struct i915_priotree priotree; | 122 | struct i915_sched_node sched; |
158 | struct i915_dependency dep; | 123 | struct i915_dependency dep; |
159 | 124 | ||
160 | /** | 125 | /** |
@@ -343,10 +308,10 @@ static inline bool i915_request_started(const struct i915_request *rq) | |||
343 | seqno - 1); | 308 | seqno - 1); |
344 | } | 309 | } |
345 | 310 | ||
346 | static inline bool i915_priotree_signaled(const struct i915_priotree *pt) | 311 | static inline bool i915_sched_node_signaled(const struct i915_sched_node *node) |
347 | { | 312 | { |
348 | const struct i915_request *rq = | 313 | const struct i915_request *rq = |
349 | container_of(pt, const struct i915_request, priotree); | 314 | container_of(node, const struct i915_request, sched); |
350 | 315 | ||
351 | return i915_request_completed(rq); | 316 | return i915_request_completed(rq); |
352 | } | 317 | } |
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h new file mode 100644 index 000000000000..70a42220358d --- /dev/null +++ b/drivers/gpu/drm/i915/i915_scheduler.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #ifndef _I915_SCHEDULER_H_ | ||
8 | #define _I915_SCHEDULER_H_ | ||
9 | |||
10 | #include <linux/bitops.h> | ||
11 | |||
12 | #include <uapi/drm/i915_drm.h> | ||
13 | |||
14 | enum { | ||
15 | I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1, | ||
16 | I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY, | ||
17 | I915_PRIORITY_MAX = I915_CONTEXT_MAX_USER_PRIORITY + 1, | ||
18 | |||
19 | I915_PRIORITY_INVALID = INT_MIN | ||
20 | }; | ||
21 | |||
22 | struct i915_sched_attr { | ||
23 | /** | ||
24 | * @priority: execution and service priority | ||
25 | * | ||
26 | * All clients are equal, but some are more equal than others! | ||
27 | * | ||
28 | * Requests from a context with a greater (more positive) value of | ||
29 | * @priority will be executed before those with a lower @priority | ||
30 | * value, forming a simple QoS. | ||
31 | * | ||
32 | * The &drm_i915_private.kernel_context is assigned the lowest priority. | ||
33 | */ | ||
34 | int priority; | ||
35 | }; | ||
36 | |||
37 | /* | ||
38 | * "People assume that time is a strict progression of cause to effect, but | ||
39 | * actually, from a nonlinear, non-subjective viewpoint, it's more like a big | ||
40 | * ball of wibbly-wobbly, timey-wimey ... stuff." -The Doctor, 2015 | ||
41 | * | ||
42 | * Requests exist in a complex web of interdependencies. Each request | ||
43 | * has to wait for some other request to complete before it is ready to be run | ||
44 | * (e.g. we have to wait until the pixels have been rendering into a texture | ||
45 | * before we can copy from it). We track the readiness of a request in terms | ||
46 | * of fences, but we also need to keep the dependency tree for the lifetime | ||
47 | * of the request (beyond the life of an individual fence). We use the tree | ||
48 | * at various points to reorder the requests whilst keeping the requests | ||
49 | * in order with respect to their various dependencies. | ||
50 | * | ||
51 | * There is no active component to the "scheduler". As we know the dependency | ||
52 | * DAG of each request, we are able to insert it into a sorted queue when it | ||
53 | * is ready, and are able to reorder its portion of the graph to accommodate | ||
54 | * dynamic priority changes. | ||
55 | */ | ||
56 | struct i915_sched_node { | ||
57 | struct list_head signalers_list; /* those before us, we depend upon */ | ||
58 | struct list_head waiters_list; /* those after us, they depend upon us */ | ||
59 | struct list_head link; | ||
60 | struct i915_sched_attr attr; | ||
61 | }; | ||
62 | |||
63 | struct i915_dependency { | ||
64 | struct i915_sched_node *signaler; | ||
65 | struct list_head signal_link; | ||
66 | struct list_head wait_link; | ||
67 | struct list_head dfs_link; | ||
68 | unsigned long flags; | ||
69 | #define I915_DEPENDENCY_ALLOC BIT(0) | ||
70 | }; | ||
71 | |||
72 | #endif /* _I915_SCHEDULER_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/i915_timeline.c b/drivers/gpu/drm/i915/i915_timeline.c new file mode 100644 index 000000000000..4667cc08c416 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_timeline.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2016-2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "i915_drv.h" | ||
8 | |||
9 | #include "i915_timeline.h" | ||
10 | #include "i915_syncmap.h" | ||
11 | |||
12 | void i915_timeline_init(struct drm_i915_private *i915, | ||
13 | struct i915_timeline *timeline, | ||
14 | const char *name) | ||
15 | { | ||
16 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
17 | |||
18 | /* | ||
19 | * Ideally we want a set of engines on a single leaf as we expect | ||
20 | * to mostly be tracking synchronisation between engines. It is not | ||
21 | * a huge issue if this is not the case, but we may want to mitigate | ||
22 | * any page crossing penalties if they become an issue. | ||
23 | */ | ||
24 | BUILD_BUG_ON(KSYNCMAP < I915_NUM_ENGINES); | ||
25 | |||
26 | timeline->name = name; | ||
27 | |||
28 | list_add(&timeline->link, &i915->gt.timelines); | ||
29 | |||
30 | /* Called during early_init before we know how many engines there are */ | ||
31 | |||
32 | timeline->fence_context = dma_fence_context_alloc(1); | ||
33 | |||
34 | spin_lock_init(&timeline->lock); | ||
35 | |||
36 | init_request_active(&timeline->last_request, NULL); | ||
37 | INIT_LIST_HEAD(&timeline->requests); | ||
38 | |||
39 | i915_syncmap_init(&timeline->sync); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * i915_timelines_park - called when the driver idles | ||
44 | * @i915: the drm_i915_private device | ||
45 | * | ||
46 | * When the driver is completely idle, we know that all of our sync points | ||
47 | * have been signaled and our tracking is then entirely redundant. Any request | ||
48 | * to wait upon an older sync point will be completed instantly as we know | ||
49 | * the fence is signaled and therefore we will not even look them up in the | ||
50 | * sync point map. | ||
51 | */ | ||
52 | void i915_timelines_park(struct drm_i915_private *i915) | ||
53 | { | ||
54 | struct i915_timeline *timeline; | ||
55 | |||
56 | lockdep_assert_held(&i915->drm.struct_mutex); | ||
57 | |||
58 | list_for_each_entry(timeline, &i915->gt.timelines, link) { | ||
59 | /* | ||
60 | * All known fences are completed so we can scrap | ||
61 | * the current sync point tracking and start afresh, | ||
62 | * any attempt to wait upon a previous sync point | ||
63 | * will be skipped as the fence was signaled. | ||
64 | */ | ||
65 | i915_syncmap_free(&timeline->sync); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | void i915_timeline_fini(struct i915_timeline *timeline) | ||
70 | { | ||
71 | GEM_BUG_ON(!list_empty(&timeline->requests)); | ||
72 | |||
73 | i915_syncmap_free(&timeline->sync); | ||
74 | |||
75 | list_del(&timeline->link); | ||
76 | } | ||
77 | |||
78 | struct i915_timeline * | ||
79 | i915_timeline_create(struct drm_i915_private *i915, const char *name) | ||
80 | { | ||
81 | struct i915_timeline *timeline; | ||
82 | |||
83 | timeline = kzalloc(sizeof(*timeline), GFP_KERNEL); | ||
84 | if (!timeline) | ||
85 | return ERR_PTR(-ENOMEM); | ||
86 | |||
87 | i915_timeline_init(i915, timeline, name); | ||
88 | kref_init(&timeline->kref); | ||
89 | |||
90 | return timeline; | ||
91 | } | ||
92 | |||
93 | void __i915_timeline_free(struct kref *kref) | ||
94 | { | ||
95 | struct i915_timeline *timeline = | ||
96 | container_of(kref, typeof(*timeline), kref); | ||
97 | |||
98 | i915_timeline_fini(timeline); | ||
99 | kfree(timeline); | ||
100 | } | ||
101 | |||
102 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | ||
103 | #include "selftests/mock_timeline.c" | ||
104 | #include "selftests/i915_timeline.c" | ||
105 | #endif | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_timeline.h index 33e01bf6aa36..dc2a4632faa7 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.h +++ b/drivers/gpu/drm/i915/i915_timeline.h | |||
@@ -22,27 +22,20 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #ifndef I915_GEM_TIMELINE_H | 25 | #ifndef I915_TIMELINE_H |
26 | #define I915_GEM_TIMELINE_H | 26 | #define I915_TIMELINE_H |
27 | 27 | ||
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/kref.h> | ||
29 | 30 | ||
30 | #include "i915_request.h" | 31 | #include "i915_request.h" |
31 | #include "i915_syncmap.h" | 32 | #include "i915_syncmap.h" |
32 | #include "i915_utils.h" | 33 | #include "i915_utils.h" |
33 | 34 | ||
34 | struct i915_gem_timeline; | 35 | struct i915_timeline { |
35 | |||
36 | struct intel_timeline { | ||
37 | u64 fence_context; | 36 | u64 fence_context; |
38 | u32 seqno; | 37 | u32 seqno; |
39 | 38 | ||
40 | /** | ||
41 | * Count of outstanding requests, from the time they are constructed | ||
42 | * to the moment they are retired. Loosely coupled to hardware. | ||
43 | */ | ||
44 | u32 inflight_seqnos; | ||
45 | |||
46 | spinlock_t lock; | 39 | spinlock_t lock; |
47 | 40 | ||
48 | /** | 41 | /** |
@@ -77,47 +70,57 @@ struct intel_timeline { | |||
77 | */ | 70 | */ |
78 | u32 global_sync[I915_NUM_ENGINES]; | 71 | u32 global_sync[I915_NUM_ENGINES]; |
79 | 72 | ||
80 | struct i915_gem_timeline *common; | ||
81 | }; | ||
82 | |||
83 | struct i915_gem_timeline { | ||
84 | struct list_head link; | 73 | struct list_head link; |
85 | |||
86 | struct drm_i915_private *i915; | ||
87 | const char *name; | 74 | const char *name; |
88 | 75 | ||
89 | struct intel_timeline engine[I915_NUM_ENGINES]; | 76 | struct kref kref; |
90 | }; | 77 | }; |
91 | 78 | ||
92 | int i915_gem_timeline_init(struct drm_i915_private *i915, | 79 | void i915_timeline_init(struct drm_i915_private *i915, |
93 | struct i915_gem_timeline *tl, | 80 | struct i915_timeline *tl, |
94 | const char *name); | 81 | const char *name); |
95 | int i915_gem_timeline_init__global(struct drm_i915_private *i915); | 82 | void i915_timeline_fini(struct i915_timeline *tl); |
96 | void i915_gem_timelines_park(struct drm_i915_private *i915); | 83 | |
97 | void i915_gem_timeline_fini(struct i915_gem_timeline *tl); | 84 | struct i915_timeline * |
85 | i915_timeline_create(struct drm_i915_private *i915, const char *name); | ||
98 | 86 | ||
99 | static inline int __intel_timeline_sync_set(struct intel_timeline *tl, | 87 | static inline struct i915_timeline * |
100 | u64 context, u32 seqno) | 88 | i915_timeline_get(struct i915_timeline *timeline) |
89 | { | ||
90 | kref_get(&timeline->kref); | ||
91 | return timeline; | ||
92 | } | ||
93 | |||
94 | void __i915_timeline_free(struct kref *kref); | ||
95 | static inline void i915_timeline_put(struct i915_timeline *timeline) | ||
96 | { | ||
97 | kref_put(&timeline->kref, __i915_timeline_free); | ||
98 | } | ||
99 | |||
100 | static inline int __i915_timeline_sync_set(struct i915_timeline *tl, | ||
101 | u64 context, u32 seqno) | ||
101 | { | 102 | { |
102 | return i915_syncmap_set(&tl->sync, context, seqno); | 103 | return i915_syncmap_set(&tl->sync, context, seqno); |
103 | } | 104 | } |
104 | 105 | ||
105 | static inline int intel_timeline_sync_set(struct intel_timeline *tl, | 106 | static inline int i915_timeline_sync_set(struct i915_timeline *tl, |
106 | const struct dma_fence *fence) | 107 | const struct dma_fence *fence) |
107 | { | 108 | { |
108 | return __intel_timeline_sync_set(tl, fence->context, fence->seqno); | 109 | return __i915_timeline_sync_set(tl, fence->context, fence->seqno); |
109 | } | 110 | } |
110 | 111 | ||
111 | static inline bool __intel_timeline_sync_is_later(struct intel_timeline *tl, | 112 | static inline bool __i915_timeline_sync_is_later(struct i915_timeline *tl, |
112 | u64 context, u32 seqno) | 113 | u64 context, u32 seqno) |
113 | { | 114 | { |
114 | return i915_syncmap_is_later(&tl->sync, context, seqno); | 115 | return i915_syncmap_is_later(&tl->sync, context, seqno); |
115 | } | 116 | } |
116 | 117 | ||
117 | static inline bool intel_timeline_sync_is_later(struct intel_timeline *tl, | 118 | static inline bool i915_timeline_sync_is_later(struct i915_timeline *tl, |
118 | const struct dma_fence *fence) | 119 | const struct dma_fence *fence) |
119 | { | 120 | { |
120 | return __intel_timeline_sync_is_later(tl, fence->context, fence->seqno); | 121 | return __i915_timeline_sync_is_later(tl, fence->context, fence->seqno); |
121 | } | 122 | } |
122 | 123 | ||
124 | void i915_timelines_park(struct drm_i915_private *i915); | ||
125 | |||
123 | #endif | 126 | #endif |
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 408827bf5d96..8cc3a256f29d 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h | |||
@@ -679,45 +679,68 @@ DEFINE_EVENT(i915_request, i915_request_execute, | |||
679 | TP_ARGS(rq) | 679 | TP_ARGS(rq) |
680 | ); | 680 | ); |
681 | 681 | ||
682 | DECLARE_EVENT_CLASS(i915_request_hw, | 682 | TRACE_EVENT(i915_request_in, |
683 | TP_PROTO(struct i915_request *rq, unsigned int port), | 683 | TP_PROTO(struct i915_request *rq, unsigned int port), |
684 | TP_ARGS(rq, port), | 684 | TP_ARGS(rq, port), |
685 | 685 | ||
686 | TP_STRUCT__entry( | 686 | TP_STRUCT__entry( |
687 | __field(u32, dev) | 687 | __field(u32, dev) |
688 | __field(u32, hw_id) | 688 | __field(u32, hw_id) |
689 | __field(u32, ring) | 689 | __field(u32, ring) |
690 | __field(u32, ctx) | 690 | __field(u32, ctx) |
691 | __field(u32, seqno) | 691 | __field(u32, seqno) |
692 | __field(u32, global_seqno) | 692 | __field(u32, global_seqno) |
693 | __field(u32, port) | 693 | __field(u32, port) |
694 | ), | 694 | __field(u32, prio) |
695 | 695 | ), | |
696 | TP_fast_assign( | 696 | |
697 | __entry->dev = rq->i915->drm.primary->index; | 697 | TP_fast_assign( |
698 | __entry->hw_id = rq->ctx->hw_id; | 698 | __entry->dev = rq->i915->drm.primary->index; |
699 | __entry->ring = rq->engine->id; | 699 | __entry->hw_id = rq->ctx->hw_id; |
700 | __entry->ctx = rq->fence.context; | 700 | __entry->ring = rq->engine->id; |
701 | __entry->seqno = rq->fence.seqno; | 701 | __entry->ctx = rq->fence.context; |
702 | __entry->global_seqno = rq->global_seqno; | 702 | __entry->seqno = rq->fence.seqno; |
703 | __entry->port = port; | 703 | __entry->global_seqno = rq->global_seqno; |
704 | ), | 704 | __entry->prio = rq->sched.attr.priority; |
705 | 705 | __entry->port = port; | |
706 | TP_printk("dev=%u, hw_id=%u, ring=%u, ctx=%u, seqno=%u, global=%u, port=%u", | 706 | ), |
707 | __entry->dev, __entry->hw_id, __entry->ring, | ||
708 | __entry->ctx, __entry->seqno, | ||
709 | __entry->global_seqno, __entry->port) | ||
710 | ); | ||
711 | 707 | ||
712 | DEFINE_EVENT(i915_request_hw, i915_request_in, | 708 | TP_printk("dev=%u, hw_id=%u, ring=%u, ctx=%u, seqno=%u, prio=%u, global=%u, port=%u", |
713 | TP_PROTO(struct i915_request *rq, unsigned int port), | 709 | __entry->dev, __entry->hw_id, __entry->ring, __entry->ctx, |
714 | TP_ARGS(rq, port) | 710 | __entry->seqno, __entry->prio, __entry->global_seqno, |
711 | __entry->port) | ||
715 | ); | 712 | ); |
716 | 713 | ||
717 | DEFINE_EVENT(i915_request, i915_request_out, | 714 | TRACE_EVENT(i915_request_out, |
718 | TP_PROTO(struct i915_request *rq), | 715 | TP_PROTO(struct i915_request *rq), |
719 | TP_ARGS(rq) | 716 | TP_ARGS(rq), |
717 | |||
718 | TP_STRUCT__entry( | ||
719 | __field(u32, dev) | ||
720 | __field(u32, hw_id) | ||
721 | __field(u32, ring) | ||
722 | __field(u32, ctx) | ||
723 | __field(u32, seqno) | ||
724 | __field(u32, global_seqno) | ||
725 | __field(u32, completed) | ||
726 | ), | ||
727 | |||
728 | TP_fast_assign( | ||
729 | __entry->dev = rq->i915->drm.primary->index; | ||
730 | __entry->hw_id = rq->ctx->hw_id; | ||
731 | __entry->ring = rq->engine->id; | ||
732 | __entry->ctx = rq->fence.context; | ||
733 | __entry->seqno = rq->fence.seqno; | ||
734 | __entry->global_seqno = rq->global_seqno; | ||
735 | __entry->completed = i915_request_completed(rq); | ||
736 | ), | ||
737 | |||
738 | TP_printk("dev=%u, hw_id=%u, ring=%u, ctx=%u, seqno=%u, global=%u, completed?=%u", | ||
739 | __entry->dev, __entry->hw_id, __entry->ring, | ||
740 | __entry->ctx, __entry->seqno, | ||
741 | __entry->global_seqno, __entry->completed) | ||
720 | ); | 742 | ); |
743 | |||
721 | #else | 744 | #else |
722 | #if !defined(TRACE_HEADER_MULTI_READ) | 745 | #if !defined(TRACE_HEADER_MULTI_READ) |
723 | static inline void | 746 | static inline void |
@@ -811,42 +834,6 @@ DEFINE_EVENT(i915_request, i915_request_wait_end, | |||
811 | TP_ARGS(rq) | 834 | TP_ARGS(rq) |
812 | ); | 835 | ); |
813 | 836 | ||
814 | TRACE_EVENT(i915_flip_request, | ||
815 | TP_PROTO(int plane, struct drm_i915_gem_object *obj), | ||
816 | |||
817 | TP_ARGS(plane, obj), | ||
818 | |||
819 | TP_STRUCT__entry( | ||
820 | __field(int, plane) | ||
821 | __field(struct drm_i915_gem_object *, obj) | ||
822 | ), | ||
823 | |||
824 | TP_fast_assign( | ||
825 | __entry->plane = plane; | ||
826 | __entry->obj = obj; | ||
827 | ), | ||
828 | |||
829 | TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj) | ||
830 | ); | ||
831 | |||
832 | TRACE_EVENT(i915_flip_complete, | ||
833 | TP_PROTO(int plane, struct drm_i915_gem_object *obj), | ||
834 | |||
835 | TP_ARGS(plane, obj), | ||
836 | |||
837 | TP_STRUCT__entry( | ||
838 | __field(int, plane) | ||
839 | __field(struct drm_i915_gem_object *, obj) | ||
840 | ), | ||
841 | |||
842 | TP_fast_assign( | ||
843 | __entry->plane = plane; | ||
844 | __entry->obj = obj; | ||
845 | ), | ||
846 | |||
847 | TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj) | ||
848 | ); | ||
849 | |||
850 | TRACE_EVENT_CONDITION(i915_reg_rw, | 837 | TRACE_EVENT_CONDITION(i915_reg_rw, |
851 | TP_PROTO(bool write, i915_reg_t reg, u64 val, int len, bool trace), | 838 | TP_PROTO(bool write, i915_reg_t reg, u64 val, int len, bool trace), |
852 | 839 | ||
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 0695717522ea..00165ad55fb3 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h | |||
@@ -120,6 +120,12 @@ static inline u64 ptr_to_u64(const void *ptr) | |||
120 | 120 | ||
121 | #include <linux/list.h> | 121 | #include <linux/list.h> |
122 | 122 | ||
123 | static inline int list_is_first(const struct list_head *list, | ||
124 | const struct list_head *head) | ||
125 | { | ||
126 | return head->next == list; | ||
127 | } | ||
128 | |||
123 | static inline void __list_del_many(struct list_head *head, | 129 | static inline void __list_del_many(struct list_head *head, |
124 | struct list_head *first) | 130 | struct list_head *first) |
125 | { | 131 | { |
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 4bda3bd29bf5..9324d476e0a7 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c | |||
@@ -46,8 +46,6 @@ i915_vma_retire(struct i915_gem_active *active, struct i915_request *rq) | |||
46 | 46 | ||
47 | GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); | 47 | GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); |
48 | list_move_tail(&vma->vm_link, &vma->vm->inactive_list); | 48 | list_move_tail(&vma->vm_link, &vma->vm->inactive_list); |
49 | if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma))) | ||
50 | WARN_ON(i915_vma_unbind(vma)); | ||
51 | 49 | ||
52 | GEM_BUG_ON(!i915_gem_object_is_active(obj)); | 50 | GEM_BUG_ON(!i915_gem_object_is_active(obj)); |
53 | if (--obj->active_count) | 51 | if (--obj->active_count) |
@@ -232,7 +230,6 @@ i915_vma_instance(struct drm_i915_gem_object *obj, | |||
232 | if (!vma) | 230 | if (!vma) |
233 | vma = vma_create(obj, vm, view); | 231 | vma = vma_create(obj, vm, view); |
234 | 232 | ||
235 | GEM_BUG_ON(!IS_ERR(vma) && i915_vma_is_closed(vma)); | ||
236 | GEM_BUG_ON(!IS_ERR(vma) && i915_vma_compare(vma, vm, view)); | 233 | GEM_BUG_ON(!IS_ERR(vma) && i915_vma_compare(vma, vm, view)); |
237 | GEM_BUG_ON(!IS_ERR(vma) && vma_lookup(obj, vm, view) != vma); | 234 | GEM_BUG_ON(!IS_ERR(vma) && vma_lookup(obj, vm, view) != vma); |
238 | return vma; | 235 | return vma; |
@@ -684,13 +681,43 @@ err_unpin: | |||
684 | return ret; | 681 | return ret; |
685 | } | 682 | } |
686 | 683 | ||
687 | static void i915_vma_destroy(struct i915_vma *vma) | 684 | void i915_vma_close(struct i915_vma *vma) |
685 | { | ||
686 | lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); | ||
687 | |||
688 | GEM_BUG_ON(i915_vma_is_closed(vma)); | ||
689 | vma->flags |= I915_VMA_CLOSED; | ||
690 | |||
691 | /* | ||
692 | * We defer actually closing, unbinding and destroying the VMA until | ||
693 | * the next idle point, or if the object is freed in the meantime. By | ||
694 | * postponing the unbind, we allow for it to be resurrected by the | ||
695 | * client, avoiding the work required to rebind the VMA. This is | ||
696 | * advantageous for DRI, where the client/server pass objects | ||
697 | * between themselves, temporarily opening a local VMA to the | ||
698 | * object, and then closing it again. The same object is then reused | ||
699 | * on the next frame (or two, depending on the depth of the swap queue) | ||
700 | * causing us to rebind the VMA once more. This ends up being a lot | ||
701 | * of wasted work for the steady state. | ||
702 | */ | ||
703 | list_add_tail(&vma->closed_link, &vma->vm->i915->gt.closed_vma); | ||
704 | } | ||
705 | |||
706 | void i915_vma_reopen(struct i915_vma *vma) | ||
707 | { | ||
708 | lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); | ||
709 | |||
710 | if (vma->flags & I915_VMA_CLOSED) { | ||
711 | vma->flags &= ~I915_VMA_CLOSED; | ||
712 | list_del(&vma->closed_link); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | static void __i915_vma_destroy(struct i915_vma *vma) | ||
688 | { | 717 | { |
689 | int i; | 718 | int i; |
690 | 719 | ||
691 | GEM_BUG_ON(vma->node.allocated); | 720 | GEM_BUG_ON(vma->node.allocated); |
692 | GEM_BUG_ON(i915_vma_is_active(vma)); | ||
693 | GEM_BUG_ON(!i915_vma_is_closed(vma)); | ||
694 | GEM_BUG_ON(vma->fence); | 721 | GEM_BUG_ON(vma->fence); |
695 | 722 | ||
696 | for (i = 0; i < ARRAY_SIZE(vma->last_read); i++) | 723 | for (i = 0; i < ARRAY_SIZE(vma->last_read); i++) |
@@ -699,6 +726,7 @@ static void i915_vma_destroy(struct i915_vma *vma) | |||
699 | 726 | ||
700 | list_del(&vma->obj_link); | 727 | list_del(&vma->obj_link); |
701 | list_del(&vma->vm_link); | 728 | list_del(&vma->vm_link); |
729 | rb_erase(&vma->obj_node, &vma->obj->vma_tree); | ||
702 | 730 | ||
703 | if (!i915_vma_is_ggtt(vma)) | 731 | if (!i915_vma_is_ggtt(vma)) |
704 | i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); | 732 | i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); |
@@ -706,15 +734,30 @@ static void i915_vma_destroy(struct i915_vma *vma) | |||
706 | kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma); | 734 | kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma); |
707 | } | 735 | } |
708 | 736 | ||
709 | void i915_vma_close(struct i915_vma *vma) | 737 | void i915_vma_destroy(struct i915_vma *vma) |
710 | { | 738 | { |
711 | GEM_BUG_ON(i915_vma_is_closed(vma)); | 739 | lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); |
712 | vma->flags |= I915_VMA_CLOSED; | ||
713 | 740 | ||
714 | rb_erase(&vma->obj_node, &vma->obj->vma_tree); | 741 | GEM_BUG_ON(i915_vma_is_active(vma)); |
742 | GEM_BUG_ON(i915_vma_is_pinned(vma)); | ||
743 | |||
744 | if (i915_vma_is_closed(vma)) | ||
745 | list_del(&vma->closed_link); | ||
746 | |||
747 | WARN_ON(i915_vma_unbind(vma)); | ||
748 | __i915_vma_destroy(vma); | ||
749 | } | ||
750 | |||
751 | void i915_vma_parked(struct drm_i915_private *i915) | ||
752 | { | ||
753 | struct i915_vma *vma, *next; | ||
715 | 754 | ||
716 | if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma)) | 755 | list_for_each_entry_safe(vma, next, &i915->gt.closed_vma, closed_link) { |
717 | WARN_ON(i915_vma_unbind(vma)); | 756 | GEM_BUG_ON(!i915_vma_is_closed(vma)); |
757 | i915_vma_destroy(vma); | ||
758 | } | ||
759 | |||
760 | GEM_BUG_ON(!list_empty(&i915->gt.closed_vma)); | ||
718 | } | 761 | } |
719 | 762 | ||
720 | static void __i915_vma_iounmap(struct i915_vma *vma) | 763 | static void __i915_vma_iounmap(struct i915_vma *vma) |
@@ -804,7 +847,7 @@ int i915_vma_unbind(struct i915_vma *vma) | |||
804 | return -EBUSY; | 847 | return -EBUSY; |
805 | 848 | ||
806 | if (!drm_mm_node_allocated(&vma->node)) | 849 | if (!drm_mm_node_allocated(&vma->node)) |
807 | goto destroy; | 850 | return 0; |
808 | 851 | ||
809 | GEM_BUG_ON(obj->bind_count == 0); | 852 | GEM_BUG_ON(obj->bind_count == 0); |
810 | GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); | 853 | GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); |
@@ -841,10 +884,6 @@ int i915_vma_unbind(struct i915_vma *vma) | |||
841 | 884 | ||
842 | i915_vma_remove(vma); | 885 | i915_vma_remove(vma); |
843 | 886 | ||
844 | destroy: | ||
845 | if (unlikely(i915_vma_is_closed(vma))) | ||
846 | i915_vma_destroy(vma); | ||
847 | |||
848 | return 0; | 887 | return 0; |
849 | } | 888 | } |
850 | 889 | ||
diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 8c5022095418..fc4294cfaa91 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h | |||
@@ -119,6 +119,8 @@ struct i915_vma { | |||
119 | /** This vma's place in the eviction list */ | 119 | /** This vma's place in the eviction list */ |
120 | struct list_head evict_link; | 120 | struct list_head evict_link; |
121 | 121 | ||
122 | struct list_head closed_link; | ||
123 | |||
122 | /** | 124 | /** |
123 | * Used for performing relocations during execbuffer insertion. | 125 | * Used for performing relocations during execbuffer insertion. |
124 | */ | 126 | */ |
@@ -285,6 +287,8 @@ void i915_vma_revoke_mmap(struct i915_vma *vma); | |||
285 | int __must_check i915_vma_unbind(struct i915_vma *vma); | 287 | int __must_check i915_vma_unbind(struct i915_vma *vma); |
286 | void i915_vma_unlink_ctx(struct i915_vma *vma); | 288 | void i915_vma_unlink_ctx(struct i915_vma *vma); |
287 | void i915_vma_close(struct i915_vma *vma); | 289 | void i915_vma_close(struct i915_vma *vma); |
290 | void i915_vma_reopen(struct i915_vma *vma); | ||
291 | void i915_vma_destroy(struct i915_vma *vma); | ||
288 | 292 | ||
289 | int __i915_vma_do_pin(struct i915_vma *vma, | 293 | int __i915_vma_do_pin(struct i915_vma *vma, |
290 | u64 size, u64 alignment, u64 flags); | 294 | u64 size, u64 alignment, u64 flags); |
@@ -408,6 +412,8 @@ i915_vma_unpin_fence(struct i915_vma *vma) | |||
408 | __i915_vma_unpin_fence(vma); | 412 | __i915_vma_unpin_fence(vma); |
409 | } | 413 | } |
410 | 414 | ||
415 | void i915_vma_parked(struct drm_i915_private *i915); | ||
416 | |||
411 | #define for_each_until(cond) if (cond) break; else | 417 | #define for_each_until(cond) if (cond) break; else |
412 | 418 | ||
413 | /** | 419 | /** |
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 7481ce85746b..6d068786eb41 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c | |||
@@ -183,11 +183,16 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ | |||
183 | } | 183 | } |
184 | 184 | ||
185 | /* FIXME pre-g4x don't work like this */ | 185 | /* FIXME pre-g4x don't work like this */ |
186 | if (intel_state->base.visible) | 186 | if (state->visible) |
187 | crtc_state->active_planes |= BIT(intel_plane->id); | 187 | crtc_state->active_planes |= BIT(intel_plane->id); |
188 | else | 188 | else |
189 | crtc_state->active_planes &= ~BIT(intel_plane->id); | 189 | crtc_state->active_planes &= ~BIT(intel_plane->id); |
190 | 190 | ||
191 | if (state->visible && state->fb->format->format == DRM_FORMAT_NV12) | ||
192 | crtc_state->nv12_planes |= BIT(intel_plane->id); | ||
193 | else | ||
194 | crtc_state->nv12_planes &= ~BIT(intel_plane->id); | ||
195 | |||
191 | return intel_plane_atomic_calc_changes(old_crtc_state, | 196 | return intel_plane_atomic_calc_changes(old_crtc_state, |
192 | &crtc_state->base, | 197 | &crtc_state->base, |
193 | old_plane_state, | 198 | old_plane_state, |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 702d3fab97fc..54270bdde100 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -530,6 +530,7 @@ parse_driver_features(struct drm_i915_private *dev_priv, | |||
530 | */ | 530 | */ |
531 | if (!driver->drrs_enabled) | 531 | if (!driver->drrs_enabled) |
532 | dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; | 532 | dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; |
533 | dev_priv->vbt.psr.enable = driver->psr_enabled; | ||
533 | } | 534 | } |
534 | 535 | ||
535 | static void | 536 | static void |
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 671a6d61e29d..18e643df523e 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c | |||
@@ -82,7 +82,7 @@ static unsigned long wait_timeout(void) | |||
82 | 82 | ||
83 | static noinline void missed_breadcrumb(struct intel_engine_cs *engine) | 83 | static noinline void missed_breadcrumb(struct intel_engine_cs *engine) |
84 | { | 84 | { |
85 | if (drm_debug & DRM_UT_DRIVER) { | 85 | if (GEM_SHOW_DEBUG()) { |
86 | struct drm_printer p = drm_debug_printer(__func__); | 86 | struct drm_printer p = drm_debug_printer(__func__); |
87 | 87 | ||
88 | intel_engine_dump(engine, &p, | 88 | intel_engine_dump(engine, &p, |
@@ -130,11 +130,12 @@ static void intel_breadcrumbs_hangcheck(struct timer_list *t) | |||
130 | 130 | ||
131 | static void intel_breadcrumbs_fake_irq(struct timer_list *t) | 131 | static void intel_breadcrumbs_fake_irq(struct timer_list *t) |
132 | { | 132 | { |
133 | struct intel_engine_cs *engine = from_timer(engine, t, | 133 | struct intel_engine_cs *engine = |
134 | breadcrumbs.fake_irq); | 134 | from_timer(engine, t, breadcrumbs.fake_irq); |
135 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | 135 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
136 | 136 | ||
137 | /* The timer persists in case we cannot enable interrupts, | 137 | /* |
138 | * The timer persists in case we cannot enable interrupts, | ||
138 | * or if we have previously seen seqno/interrupt incoherency | 139 | * or if we have previously seen seqno/interrupt incoherency |
139 | * ("missed interrupt" syndrome, better known as a "missed breadcrumb"). | 140 | * ("missed interrupt" syndrome, better known as a "missed breadcrumb"). |
140 | * Here the worker will wake up every jiffie in order to kick the | 141 | * Here the worker will wake up every jiffie in order to kick the |
@@ -148,6 +149,12 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t) | |||
148 | if (!b->irq_armed) | 149 | if (!b->irq_armed) |
149 | return; | 150 | return; |
150 | 151 | ||
152 | /* If the user has disabled the fake-irq, restore the hangchecking */ | ||
153 | if (!test_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings)) { | ||
154 | mod_timer(&b->hangcheck, wait_timeout()); | ||
155 | return; | ||
156 | } | ||
157 | |||
151 | mod_timer(&b->fake_irq, jiffies + 1); | 158 | mod_timer(&b->fake_irq, jiffies + 1); |
152 | } | 159 | } |
153 | 160 | ||
@@ -831,8 +838,8 @@ static void cancel_fake_irq(struct intel_engine_cs *engine) | |||
831 | { | 838 | { |
832 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | 839 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
833 | 840 | ||
841 | del_timer_sync(&b->fake_irq); /* may queue b->hangcheck */ | ||
834 | del_timer_sync(&b->hangcheck); | 842 | del_timer_sync(&b->hangcheck); |
835 | del_timer_sync(&b->fake_irq); | ||
836 | clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); | 843 | clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); |
837 | } | 844 | } |
838 | 845 | ||
@@ -840,15 +847,22 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) | |||
840 | { | 847 | { |
841 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | 848 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
842 | 849 | ||
843 | cancel_fake_irq(engine); | ||
844 | spin_lock_irq(&b->irq_lock); | 850 | spin_lock_irq(&b->irq_lock); |
845 | 851 | ||
852 | /* | ||
853 | * Leave the fake_irq timer enabled (if it is running), but clear the | ||
854 | * bit so that it turns itself off on its next wake up and goes back | ||
855 | * to the long hangcheck interval if still required. | ||
856 | */ | ||
857 | clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); | ||
858 | |||
846 | if (b->irq_enabled) | 859 | if (b->irq_enabled) |
847 | irq_enable(engine); | 860 | irq_enable(engine); |
848 | else | 861 | else |
849 | irq_disable(engine); | 862 | irq_disable(engine); |
850 | 863 | ||
851 | /* We set the IRQ_BREADCRUMB bit when we enable the irq presuming the | 864 | /* |
865 | * We set the IRQ_BREADCRUMB bit when we enable the irq presuming the | ||
852 | * GPU is active and may have already executed the MI_USER_INTERRUPT | 866 | * GPU is active and may have already executed the MI_USER_INTERRUPT |
853 | * before the CPU is ready to receive. However, the engine is currently | 867 | * before the CPU is ready to receive. However, the engine is currently |
854 | * idle (we haven't started it yet), there is no possibility for a | 868 | * idle (we haven't started it yet), there is no possibility for a |
@@ -857,9 +871,6 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) | |||
857 | */ | 871 | */ |
858 | clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted); | 872 | clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted); |
859 | 873 | ||
860 | if (b->irq_armed) | ||
861 | enable_fake_irq(b); | ||
862 | |||
863 | spin_unlock_irq(&b->irq_lock); | 874 | spin_unlock_irq(&b->irq_lock); |
864 | } | 875 | } |
865 | 876 | ||
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index 32d24c69da3c..704ddb4d3ca7 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c | |||
@@ -2302,9 +2302,44 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state) | |||
2302 | return 0; | 2302 | return 0; |
2303 | } | 2303 | } |
2304 | 2304 | ||
2305 | static int skl_dpll0_vco(struct intel_atomic_state *intel_state) | ||
2306 | { | ||
2307 | struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev); | ||
2308 | struct intel_crtc *crtc; | ||
2309 | struct intel_crtc_state *crtc_state; | ||
2310 | int vco, i; | ||
2311 | |||
2312 | vco = intel_state->cdclk.logical.vco; | ||
2313 | if (!vco) | ||
2314 | vco = dev_priv->skl_preferred_vco_freq; | ||
2315 | |||
2316 | for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { | ||
2317 | if (!crtc_state->base.enable) | ||
2318 | continue; | ||
2319 | |||
2320 | if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) | ||
2321 | continue; | ||
2322 | |||
2323 | /* | ||
2324 | * DPLL0 VCO may need to be adjusted to get the correct | ||
2325 | * clock for eDP. This will affect cdclk as well. | ||
2326 | */ | ||
2327 | switch (crtc_state->port_clock / 2) { | ||
2328 | case 108000: | ||
2329 | case 216000: | ||
2330 | vco = 8640000; | ||
2331 | break; | ||
2332 | default: | ||
2333 | vco = 8100000; | ||
2334 | break; | ||
2335 | } | ||
2336 | } | ||
2337 | |||
2338 | return vco; | ||
2339 | } | ||
2340 | |||
2305 | static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) | 2341 | static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) |
2306 | { | 2342 | { |
2307 | struct drm_i915_private *dev_priv = to_i915(state->dev); | ||
2308 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | 2343 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); |
2309 | int min_cdclk, cdclk, vco; | 2344 | int min_cdclk, cdclk, vco; |
2310 | 2345 | ||
@@ -2312,9 +2347,7 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) | |||
2312 | if (min_cdclk < 0) | 2347 | if (min_cdclk < 0) |
2313 | return min_cdclk; | 2348 | return min_cdclk; |
2314 | 2349 | ||
2315 | vco = intel_state->cdclk.logical.vco; | 2350 | vco = skl_dpll0_vco(intel_state); |
2316 | if (!vco) | ||
2317 | vco = dev_priv->skl_preferred_vco_freq; | ||
2318 | 2351 | ||
2319 | /* | 2352 | /* |
2320 | * FIXME should also account for plane ratio | 2353 | * FIXME should also account for plane ratio |
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index f9550ea46c26..cf9b600cca79 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c | |||
@@ -298,7 +298,10 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, | |||
298 | 298 | ||
299 | csr->version = css_header->version; | 299 | csr->version = css_header->version; |
300 | 300 | ||
301 | if (IS_CANNONLAKE(dev_priv)) { | 301 | if (csr->fw_path == i915_modparams.dmc_firmware_path) { |
302 | /* Bypass version check for firmware override. */ | ||
303 | required_version = csr->version; | ||
304 | } else if (IS_CANNONLAKE(dev_priv)) { | ||
302 | required_version = CNL_CSR_VERSION_REQUIRED; | 305 | required_version = CNL_CSR_VERSION_REQUIRED; |
303 | } else if (IS_GEMINILAKE(dev_priv)) { | 306 | } else if (IS_GEMINILAKE(dev_priv)) { |
304 | required_version = GLK_CSR_VERSION_REQUIRED; | 307 | required_version = GLK_CSR_VERSION_REQUIRED; |
@@ -453,7 +456,9 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) | |||
453 | if (!HAS_CSR(dev_priv)) | 456 | if (!HAS_CSR(dev_priv)) |
454 | return; | 457 | return; |
455 | 458 | ||
456 | if (IS_CANNONLAKE(dev_priv)) | 459 | if (i915_modparams.dmc_firmware_path) |
460 | csr->fw_path = i915_modparams.dmc_firmware_path; | ||
461 | else if (IS_CANNONLAKE(dev_priv)) | ||
457 | csr->fw_path = I915_CSR_CNL; | 462 | csr->fw_path = I915_CSR_CNL; |
458 | else if (IS_GEMINILAKE(dev_priv)) | 463 | else if (IS_GEMINILAKE(dev_priv)) |
459 | csr->fw_path = I915_CSR_GLK; | 464 | csr->fw_path = I915_CSR_GLK; |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 92cb26b18a9b..b98ac0541f19 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -870,6 +870,45 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) | |||
870 | } | 870 | } |
871 | } | 871 | } |
872 | 872 | ||
873 | static const struct icl_combo_phy_ddi_buf_trans * | ||
874 | icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port, | ||
875 | int type, int *n_entries) | ||
876 | { | ||
877 | u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK; | ||
878 | |||
879 | if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { | ||
880 | switch (voltage) { | ||
881 | case VOLTAGE_INFO_0_85V: | ||
882 | *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V); | ||
883 | return icl_combo_phy_ddi_translations_edp_0_85V; | ||
884 | case VOLTAGE_INFO_0_95V: | ||
885 | *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V); | ||
886 | return icl_combo_phy_ddi_translations_edp_0_95V; | ||
887 | case VOLTAGE_INFO_1_05V: | ||
888 | *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V); | ||
889 | return icl_combo_phy_ddi_translations_edp_1_05V; | ||
890 | default: | ||
891 | MISSING_CASE(voltage); | ||
892 | return NULL; | ||
893 | } | ||
894 | } else { | ||
895 | switch (voltage) { | ||
896 | case VOLTAGE_INFO_0_85V: | ||
897 | *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V); | ||
898 | return icl_combo_phy_ddi_translations_dp_hdmi_0_85V; | ||
899 | case VOLTAGE_INFO_0_95V: | ||
900 | *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V); | ||
901 | return icl_combo_phy_ddi_translations_dp_hdmi_0_95V; | ||
902 | case VOLTAGE_INFO_1_05V: | ||
903 | *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V); | ||
904 | return icl_combo_phy_ddi_translations_dp_hdmi_1_05V; | ||
905 | default: | ||
906 | MISSING_CASE(voltage); | ||
907 | return NULL; | ||
908 | } | ||
909 | } | ||
910 | } | ||
911 | |||
873 | static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) | 912 | static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) |
874 | { | 913 | { |
875 | int n_entries, level, default_entry; | 914 | int n_entries, level, default_entry; |
@@ -1013,6 +1052,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) | |||
1013 | } | 1052 | } |
1014 | } | 1053 | } |
1015 | 1054 | ||
1055 | static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder, | ||
1056 | const struct intel_shared_dpll *pll) | ||
1057 | { | ||
1058 | const enum intel_dpll_id id = pll->info->id; | ||
1059 | |||
1060 | switch (id) { | ||
1061 | default: | ||
1062 | MISSING_CASE(id); | ||
1063 | case DPLL_ID_ICL_DPLL0: | ||
1064 | case DPLL_ID_ICL_DPLL1: | ||
1065 | return DDI_CLK_SEL_NONE; | ||
1066 | case DPLL_ID_ICL_MGPLL1: | ||
1067 | case DPLL_ID_ICL_MGPLL2: | ||
1068 | case DPLL_ID_ICL_MGPLL3: | ||
1069 | case DPLL_ID_ICL_MGPLL4: | ||
1070 | return DDI_CLK_SEL_MG; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1016 | /* Starting with Haswell, different DDI ports can work in FDI mode for | 1074 | /* Starting with Haswell, different DDI ports can work in FDI mode for |
1017 | * connection to the PCH-located connectors. For this, it is necessary to train | 1075 | * connection to the PCH-located connectors. For this, it is necessary to train |
1018 | * both the DDI port and PCH receiver for the desired DDI buffer settings. | 1076 | * both the DDI port and PCH receiver for the desired DDI buffer settings. |
@@ -2025,7 +2083,13 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) | |||
2025 | enum port port = encoder->port; | 2083 | enum port port = encoder->port; |
2026 | int n_entries; | 2084 | int n_entries; |
2027 | 2085 | ||
2028 | if (IS_CANNONLAKE(dev_priv)) { | 2086 | if (IS_ICELAKE(dev_priv)) { |
2087 | if (port == PORT_A || port == PORT_B) | ||
2088 | icl_get_combo_buf_trans(dev_priv, port, encoder->type, | ||
2089 | &n_entries); | ||
2090 | else | ||
2091 | n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations); | ||
2092 | } else if (IS_CANNONLAKE(dev_priv)) { | ||
2029 | if (encoder->type == INTEL_OUTPUT_EDP) | 2093 | if (encoder->type == INTEL_OUTPUT_EDP) |
2030 | cnl_get_buf_trans_edp(dev_priv, &n_entries); | 2094 | cnl_get_buf_trans_edp(dev_priv, &n_entries); |
2031 | else | 2095 | else |
@@ -2182,6 +2246,146 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, | |||
2182 | I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); | 2246 | I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); |
2183 | } | 2247 | } |
2184 | 2248 | ||
2249 | static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, | ||
2250 | u32 level, enum port port, int type) | ||
2251 | { | ||
2252 | const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL; | ||
2253 | u32 n_entries, val; | ||
2254 | int ln; | ||
2255 | |||
2256 | ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type, | ||
2257 | &n_entries); | ||
2258 | if (!ddi_translations) | ||
2259 | return; | ||
2260 | |||
2261 | if (level >= n_entries) { | ||
2262 | DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1); | ||
2263 | level = n_entries - 1; | ||
2264 | } | ||
2265 | |||
2266 | /* Set PORT_TX_DW5 Rterm Sel to 110b. */ | ||
2267 | val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); | ||
2268 | val &= ~RTERM_SELECT_MASK; | ||
2269 | val |= RTERM_SELECT(0x6); | ||
2270 | I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); | ||
2271 | |||
2272 | /* Program PORT_TX_DW5 */ | ||
2273 | val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); | ||
2274 | /* Set DisableTap2 and DisableTap3 if MIPI DSI | ||
2275 | * Clear DisableTap2 and DisableTap3 for all other Ports | ||
2276 | */ | ||
2277 | if (type == INTEL_OUTPUT_DSI) { | ||
2278 | val |= TAP2_DISABLE; | ||
2279 | val |= TAP3_DISABLE; | ||
2280 | } else { | ||
2281 | val &= ~TAP2_DISABLE; | ||
2282 | val &= ~TAP3_DISABLE; | ||
2283 | } | ||
2284 | I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); | ||
2285 | |||
2286 | /* Program PORT_TX_DW2 */ | ||
2287 | val = I915_READ(ICL_PORT_TX_DW2_LN0(port)); | ||
2288 | val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK | | ||
2289 | RCOMP_SCALAR_MASK); | ||
2290 | val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select); | ||
2291 | val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select); | ||
2292 | /* Program Rcomp scalar for every table entry */ | ||
2293 | val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar); | ||
2294 | I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val); | ||
2295 | |||
2296 | /* Program PORT_TX_DW4 */ | ||
2297 | /* We cannot write to GRP. It would overwrite individual loadgen. */ | ||
2298 | for (ln = 0; ln <= 3; ln++) { | ||
2299 | val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln)); | ||
2300 | val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | | ||
2301 | CURSOR_COEFF_MASK); | ||
2302 | val |= ddi_translations[level].dw4_scaling; | ||
2303 | I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val); | ||
2304 | } | ||
2305 | } | ||
2306 | |||
2307 | static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder, | ||
2308 | u32 level, | ||
2309 | enum intel_output_type type) | ||
2310 | { | ||
2311 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
2312 | enum port port = encoder->port; | ||
2313 | int width = 0; | ||
2314 | int rate = 0; | ||
2315 | u32 val; | ||
2316 | int ln = 0; | ||
2317 | |||
2318 | if (type == INTEL_OUTPUT_HDMI) { | ||
2319 | width = 4; | ||
2320 | /* Rate is always < than 6GHz for HDMI */ | ||
2321 | } else { | ||
2322 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | ||
2323 | |||
2324 | width = intel_dp->lane_count; | ||
2325 | rate = intel_dp->link_rate; | ||
2326 | } | ||
2327 | |||
2328 | /* | ||
2329 | * 1. If port type is eDP or DP, | ||
2330 | * set PORT_PCS_DW1 cmnkeeper_enable to 1b, | ||
2331 | * else clear to 0b. | ||
2332 | */ | ||
2333 | val = I915_READ(ICL_PORT_PCS_DW1_LN0(port)); | ||
2334 | if (type == INTEL_OUTPUT_HDMI) | ||
2335 | val &= ~COMMON_KEEPER_EN; | ||
2336 | else | ||
2337 | val |= COMMON_KEEPER_EN; | ||
2338 | I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val); | ||
2339 | |||
2340 | /* 2. Program loadgen select */ | ||
2341 | /* | ||
2342 | * Program PORT_TX_DW4_LN depending on Bit rate and used lanes | ||
2343 | * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1) | ||
2344 | * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0) | ||
2345 | * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0) | ||
2346 | */ | ||
2347 | for (ln = 0; ln <= 3; ln++) { | ||
2348 | val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln)); | ||
2349 | val &= ~LOADGEN_SELECT; | ||
2350 | |||
2351 | if ((rate <= 600000 && width == 4 && ln >= 1) || | ||
2352 | (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) { | ||
2353 | val |= LOADGEN_SELECT; | ||
2354 | } | ||
2355 | I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val); | ||
2356 | } | ||
2357 | |||
2358 | /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */ | ||
2359 | val = I915_READ(ICL_PORT_CL_DW5(port)); | ||
2360 | val |= SUS_CLOCK_CONFIG; | ||
2361 | I915_WRITE(ICL_PORT_CL_DW5(port), val); | ||
2362 | |||
2363 | /* 4. Clear training enable to change swing values */ | ||
2364 | val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); | ||
2365 | val &= ~TX_TRAINING_EN; | ||
2366 | I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); | ||
2367 | |||
2368 | /* 5. Program swing and de-emphasis */ | ||
2369 | icl_ddi_combo_vswing_program(dev_priv, level, port, type); | ||
2370 | |||
2371 | /* 6. Set training enable to trigger update */ | ||
2372 | val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); | ||
2373 | val |= TX_TRAINING_EN; | ||
2374 | I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); | ||
2375 | } | ||
2376 | |||
2377 | static void icl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level, | ||
2378 | enum intel_output_type type) | ||
2379 | { | ||
2380 | enum port port = encoder->port; | ||
2381 | |||
2382 | if (port == PORT_A || port == PORT_B) | ||
2383 | icl_combo_phy_ddi_vswing_sequence(encoder, level, type); | ||
2384 | else | ||
2385 | /* Not Implemented Yet */ | ||
2386 | WARN_ON(1); | ||
2387 | } | ||
2388 | |||
2185 | static uint32_t translate_signal_level(int signal_levels) | 2389 | static uint32_t translate_signal_level(int signal_levels) |
2186 | { | 2390 | { |
2187 | int i; | 2391 | int i; |
@@ -2213,7 +2417,9 @@ u32 bxt_signal_levels(struct intel_dp *intel_dp) | |||
2213 | struct intel_encoder *encoder = &dport->base; | 2417 | struct intel_encoder *encoder = &dport->base; |
2214 | int level = intel_ddi_dp_level(intel_dp); | 2418 | int level = intel_ddi_dp_level(intel_dp); |
2215 | 2419 | ||
2216 | if (IS_CANNONLAKE(dev_priv)) | 2420 | if (IS_ICELAKE(dev_priv)) |
2421 | icl_ddi_vswing_sequence(encoder, level, encoder->type); | ||
2422 | else if (IS_CANNONLAKE(dev_priv)) | ||
2217 | cnl_ddi_vswing_sequence(encoder, level, encoder->type); | 2423 | cnl_ddi_vswing_sequence(encoder, level, encoder->type); |
2218 | else | 2424 | else |
2219 | bxt_ddi_vswing_sequence(encoder, level, encoder->type); | 2425 | bxt_ddi_vswing_sequence(encoder, level, encoder->type); |
@@ -2234,6 +2440,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) | |||
2234 | return DDI_BUF_TRANS_SELECT(level); | 2440 | return DDI_BUF_TRANS_SELECT(level); |
2235 | } | 2441 | } |
2236 | 2442 | ||
2443 | void icl_map_plls_to_ports(struct drm_crtc *crtc, | ||
2444 | struct intel_crtc_state *crtc_state, | ||
2445 | struct drm_atomic_state *old_state) | ||
2446 | { | ||
2447 | struct intel_shared_dpll *pll = crtc_state->shared_dpll; | ||
2448 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); | ||
2449 | struct drm_connector_state *conn_state; | ||
2450 | struct drm_connector *conn; | ||
2451 | int i; | ||
2452 | |||
2453 | for_each_new_connector_in_state(old_state, conn, conn_state, i) { | ||
2454 | struct intel_encoder *encoder = | ||
2455 | to_intel_encoder(conn_state->best_encoder); | ||
2456 | enum port port = encoder->port; | ||
2457 | uint32_t val; | ||
2458 | |||
2459 | if (conn_state->crtc != crtc) | ||
2460 | continue; | ||
2461 | |||
2462 | mutex_lock(&dev_priv->dpll_lock); | ||
2463 | |||
2464 | val = I915_READ(DPCLKA_CFGCR0_ICL); | ||
2465 | WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0); | ||
2466 | |||
2467 | if (port == PORT_A || port == PORT_B) { | ||
2468 | val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); | ||
2469 | val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port); | ||
2470 | I915_WRITE(DPCLKA_CFGCR0_ICL, val); | ||
2471 | POSTING_READ(DPCLKA_CFGCR0_ICL); | ||
2472 | } | ||
2473 | |||
2474 | val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port); | ||
2475 | I915_WRITE(DPCLKA_CFGCR0_ICL, val); | ||
2476 | |||
2477 | mutex_unlock(&dev_priv->dpll_lock); | ||
2478 | } | ||
2479 | } | ||
2480 | |||
2481 | void icl_unmap_plls_to_ports(struct drm_crtc *crtc, | ||
2482 | struct intel_crtc_state *crtc_state, | ||
2483 | struct drm_atomic_state *old_state) | ||
2484 | { | ||
2485 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); | ||
2486 | struct drm_connector_state *old_conn_state; | ||
2487 | struct drm_connector *conn; | ||
2488 | int i; | ||
2489 | |||
2490 | for_each_old_connector_in_state(old_state, conn, old_conn_state, i) { | ||
2491 | struct intel_encoder *encoder = | ||
2492 | to_intel_encoder(old_conn_state->best_encoder); | ||
2493 | enum port port = encoder->port; | ||
2494 | |||
2495 | if (old_conn_state->crtc != crtc) | ||
2496 | continue; | ||
2497 | |||
2498 | mutex_lock(&dev_priv->dpll_lock); | ||
2499 | I915_WRITE(DPCLKA_CFGCR0_ICL, | ||
2500 | I915_READ(DPCLKA_CFGCR0_ICL) | | ||
2501 | DPCLKA_CFGCR0_DDI_CLK_OFF(port)); | ||
2502 | mutex_unlock(&dev_priv->dpll_lock); | ||
2503 | } | ||
2504 | } | ||
2505 | |||
2237 | static void intel_ddi_clk_select(struct intel_encoder *encoder, | 2506 | static void intel_ddi_clk_select(struct intel_encoder *encoder, |
2238 | const struct intel_shared_dpll *pll) | 2507 | const struct intel_shared_dpll *pll) |
2239 | { | 2508 | { |
@@ -2246,7 +2515,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, | |||
2246 | 2515 | ||
2247 | mutex_lock(&dev_priv->dpll_lock); | 2516 | mutex_lock(&dev_priv->dpll_lock); |
2248 | 2517 | ||
2249 | if (IS_CANNONLAKE(dev_priv)) { | 2518 | if (IS_ICELAKE(dev_priv)) { |
2519 | if (port >= PORT_C) | ||
2520 | I915_WRITE(DDI_CLK_SEL(port), | ||
2521 | icl_pll_to_ddi_pll_sel(encoder, pll)); | ||
2522 | } else if (IS_CANNONLAKE(dev_priv)) { | ||
2250 | /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ | 2523 | /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ |
2251 | val = I915_READ(DPCLKA_CFGCR0); | 2524 | val = I915_READ(DPCLKA_CFGCR0); |
2252 | val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); | 2525 | val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); |
@@ -2284,14 +2557,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder) | |||
2284 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 2557 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
2285 | enum port port = encoder->port; | 2558 | enum port port = encoder->port; |
2286 | 2559 | ||
2287 | if (IS_CANNONLAKE(dev_priv)) | 2560 | if (IS_ICELAKE(dev_priv)) { |
2561 | if (port >= PORT_C) | ||
2562 | I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE); | ||
2563 | } else if (IS_CANNONLAKE(dev_priv)) { | ||
2288 | I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) | | 2564 | I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) | |
2289 | DPCLKA_CFGCR0_DDI_CLK_OFF(port)); | 2565 | DPCLKA_CFGCR0_DDI_CLK_OFF(port)); |
2290 | else if (IS_GEN9_BC(dev_priv)) | 2566 | } else if (IS_GEN9_BC(dev_priv)) { |
2291 | I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) | | 2567 | I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) | |
2292 | DPLL_CTRL2_DDI_CLK_OFF(port)); | 2568 | DPLL_CTRL2_DDI_CLK_OFF(port)); |
2293 | else if (INTEL_GEN(dev_priv) < 9) | 2569 | } else if (INTEL_GEN(dev_priv) < 9) { |
2294 | I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); | 2570 | I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); |
2571 | } | ||
2295 | } | 2572 | } |
2296 | 2573 | ||
2297 | static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, | 2574 | static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, |
@@ -2316,7 +2593,9 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, | |||
2316 | 2593 | ||
2317 | intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); | 2594 | intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); |
2318 | 2595 | ||
2319 | if (IS_CANNONLAKE(dev_priv)) | 2596 | if (IS_ICELAKE(dev_priv)) |
2597 | icl_ddi_vswing_sequence(encoder, level, encoder->type); | ||
2598 | else if (IS_CANNONLAKE(dev_priv)) | ||
2320 | cnl_ddi_vswing_sequence(encoder, level, encoder->type); | 2599 | cnl_ddi_vswing_sequence(encoder, level, encoder->type); |
2321 | else if (IS_GEN9_LP(dev_priv)) | 2600 | else if (IS_GEN9_LP(dev_priv)) |
2322 | bxt_ddi_vswing_sequence(encoder, level, encoder->type); | 2601 | bxt_ddi_vswing_sequence(encoder, level, encoder->type); |
@@ -2347,7 +2626,9 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, | |||
2347 | 2626 | ||
2348 | intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); | 2627 | intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); |
2349 | 2628 | ||
2350 | if (IS_CANNONLAKE(dev_priv)) | 2629 | if (IS_ICELAKE(dev_priv)) |
2630 | icl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); | ||
2631 | else if (IS_CANNONLAKE(dev_priv)) | ||
2351 | cnl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); | 2632 | cnl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); |
2352 | else if (IS_GEN9_LP(dev_priv)) | 2633 | else if (IS_GEN9_LP(dev_priv)) |
2353 | bxt_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); | 2634 | bxt_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); |
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index a32ba72c514e..0fd13df424cf 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c | |||
@@ -848,7 +848,7 @@ void intel_device_info_runtime_init(struct intel_device_info *info) | |||
848 | gen9_sseu_info_init(dev_priv); | 848 | gen9_sseu_info_init(dev_priv); |
849 | else if (INTEL_GEN(dev_priv) == 10) | 849 | else if (INTEL_GEN(dev_priv) == 10) |
850 | gen10_sseu_info_init(dev_priv); | 850 | gen10_sseu_info_init(dev_priv); |
851 | else if (INTEL_INFO(dev_priv)->gen >= 11) | 851 | else if (INTEL_GEN(dev_priv) >= 11) |
852 | gen11_sseu_info_init(dev_priv); | 852 | gen11_sseu_info_init(dev_priv); |
853 | 853 | ||
854 | /* Initialize command stream timestamp frequency */ | 854 | /* Initialize command stream timestamp frequency */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 020900e08d42..ad588d564198 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -88,6 +88,22 @@ static const uint32_t skl_primary_formats[] = { | |||
88 | DRM_FORMAT_VYUY, | 88 | DRM_FORMAT_VYUY, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static const uint32_t skl_pri_planar_formats[] = { | ||
92 | DRM_FORMAT_C8, | ||
93 | DRM_FORMAT_RGB565, | ||
94 | DRM_FORMAT_XRGB8888, | ||
95 | DRM_FORMAT_XBGR8888, | ||
96 | DRM_FORMAT_ARGB8888, | ||
97 | DRM_FORMAT_ABGR8888, | ||
98 | DRM_FORMAT_XRGB2101010, | ||
99 | DRM_FORMAT_XBGR2101010, | ||
100 | DRM_FORMAT_YUYV, | ||
101 | DRM_FORMAT_YVYU, | ||
102 | DRM_FORMAT_UYVY, | ||
103 | DRM_FORMAT_VYUY, | ||
104 | DRM_FORMAT_NV12, | ||
105 | }; | ||
106 | |||
91 | static const uint64_t skl_format_modifiers_noccs[] = { | 107 | static const uint64_t skl_format_modifiers_noccs[] = { |
92 | I915_FORMAT_MOD_Yf_TILED, | 108 | I915_FORMAT_MOD_Yf_TILED, |
93 | I915_FORMAT_MOD_Y_TILED, | 109 | I915_FORMAT_MOD_Y_TILED, |
@@ -489,9 +505,21 @@ static const struct intel_limit intel_limits_bxt = { | |||
489 | }; | 505 | }; |
490 | 506 | ||
491 | static void | 507 | static void |
508 | skl_wa_528(struct drm_i915_private *dev_priv, int pipe, bool enable) | ||
509 | { | ||
510 | if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) | ||
511 | return; | ||
512 | |||
513 | if (enable) | ||
514 | I915_WRITE(CHICKEN_PIPESL_1(pipe), HSW_FBCQ_DIS); | ||
515 | else | ||
516 | I915_WRITE(CHICKEN_PIPESL_1(pipe), 0); | ||
517 | } | ||
518 | |||
519 | static void | ||
492 | skl_wa_clkgate(struct drm_i915_private *dev_priv, int pipe, bool enable) | 520 | skl_wa_clkgate(struct drm_i915_private *dev_priv, int pipe, bool enable) |
493 | { | 521 | { |
494 | if (IS_SKYLAKE(dev_priv)) | 522 | if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) |
495 | return; | 523 | return; |
496 | 524 | ||
497 | if (enable) | 525 | if (enable) |
@@ -3090,6 +3118,29 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, | |||
3090 | return 0; | 3118 | return 0; |
3091 | } | 3119 | } |
3092 | 3120 | ||
3121 | static int | ||
3122 | skl_check_nv12_surface(const struct intel_crtc_state *crtc_state, | ||
3123 | struct intel_plane_state *plane_state) | ||
3124 | { | ||
3125 | /* Display WA #1106 */ | ||
3126 | if (plane_state->base.rotation != | ||
3127 | (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90) && | ||
3128 | plane_state->base.rotation != DRM_MODE_ROTATE_270) | ||
3129 | return 0; | ||
3130 | |||
3131 | /* | ||
3132 | * src coordinates are rotated here. | ||
3133 | * We check height but report it as width | ||
3134 | */ | ||
3135 | if (((drm_rect_height(&plane_state->base.src) >> 16) % 4) != 0) { | ||
3136 | DRM_DEBUG_KMS("src width must be multiple " | ||
3137 | "of 4 for rotated NV12\n"); | ||
3138 | return -EINVAL; | ||
3139 | } | ||
3140 | |||
3141 | return 0; | ||
3142 | } | ||
3143 | |||
3093 | static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) | 3144 | static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) |
3094 | { | 3145 | { |
3095 | const struct drm_framebuffer *fb = plane_state->base.fb; | 3146 | const struct drm_framebuffer *fb = plane_state->base.fb; |
@@ -3173,6 +3224,9 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, | |||
3173 | * the main surface setup depends on it. | 3224 | * the main surface setup depends on it. |
3174 | */ | 3225 | */ |
3175 | if (fb->format->format == DRM_FORMAT_NV12) { | 3226 | if (fb->format->format == DRM_FORMAT_NV12) { |
3227 | ret = skl_check_nv12_surface(crtc_state, plane_state); | ||
3228 | if (ret) | ||
3229 | return ret; | ||
3176 | ret = skl_check_nv12_aux_surface(plane_state); | 3230 | ret = skl_check_nv12_aux_surface(plane_state); |
3177 | if (ret) | 3231 | if (ret) |
3178 | return ret; | 3232 | return ret; |
@@ -3623,11 +3677,15 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, | |||
3623 | u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, | 3677 | u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, |
3624 | const struct intel_plane_state *plane_state) | 3678 | const struct intel_plane_state *plane_state) |
3625 | { | 3679 | { |
3680 | struct drm_i915_private *dev_priv = | ||
3681 | to_i915(plane_state->base.plane->dev); | ||
3626 | const struct drm_framebuffer *fb = plane_state->base.fb; | 3682 | const struct drm_framebuffer *fb = plane_state->base.fb; |
3627 | u32 plane_color_ctl = 0; | 3683 | u32 plane_color_ctl = 0; |
3628 | 3684 | ||
3629 | plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE; | 3685 | if (INTEL_GEN(dev_priv) < 11) { |
3630 | plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE; | 3686 | plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE; |
3687 | plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE; | ||
3688 | } | ||
3631 | plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; | 3689 | plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; |
3632 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); | 3690 | plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); |
3633 | 3691 | ||
@@ -4790,8 +4848,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, | |||
4790 | } | 4848 | } |
4791 | 4849 | ||
4792 | if (plane_scaler_check && pixel_format == DRM_FORMAT_NV12 && | 4850 | if (plane_scaler_check && pixel_format == DRM_FORMAT_NV12 && |
4793 | (src_h < SKL_MIN_YUV_420_SRC_H || (src_w % 4) != 0 || | 4851 | (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) { |
4794 | (src_h % 4) != 0)) { | ||
4795 | DRM_DEBUG_KMS("NV12: src dimensions not met\n"); | 4852 | DRM_DEBUG_KMS("NV12: src dimensions not met\n"); |
4796 | return -EINVAL; | 4853 | return -EINVAL; |
4797 | } | 4854 | } |
@@ -5138,6 +5195,22 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s | |||
5138 | return !old_crtc_state->ips_enabled; | 5195 | return !old_crtc_state->ips_enabled; |
5139 | } | 5196 | } |
5140 | 5197 | ||
5198 | static bool needs_nv12_wa(struct drm_i915_private *dev_priv, | ||
5199 | const struct intel_crtc_state *crtc_state) | ||
5200 | { | ||
5201 | if (!crtc_state->nv12_planes) | ||
5202 | return false; | ||
5203 | |||
5204 | if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) | ||
5205 | return false; | ||
5206 | |||
5207 | if ((INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) || | ||
5208 | IS_CANNONLAKE(dev_priv)) | ||
5209 | return true; | ||
5210 | |||
5211 | return false; | ||
5212 | } | ||
5213 | |||
5141 | static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) | 5214 | static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) |
5142 | { | 5215 | { |
5143 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); | 5216 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); |
@@ -5162,7 +5235,6 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) | |||
5162 | if (old_primary_state) { | 5235 | if (old_primary_state) { |
5163 | struct drm_plane_state *new_primary_state = | 5236 | struct drm_plane_state *new_primary_state = |
5164 | drm_atomic_get_new_plane_state(old_state, primary); | 5237 | drm_atomic_get_new_plane_state(old_state, primary); |
5165 | struct drm_framebuffer *fb = new_primary_state->fb; | ||
5166 | 5238 | ||
5167 | intel_fbc_post_update(crtc); | 5239 | intel_fbc_post_update(crtc); |
5168 | 5240 | ||
@@ -5170,14 +5242,13 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) | |||
5170 | (needs_modeset(&pipe_config->base) || | 5242 | (needs_modeset(&pipe_config->base) || |
5171 | !old_primary_state->visible)) | 5243 | !old_primary_state->visible)) |
5172 | intel_post_enable_primary(&crtc->base, pipe_config); | 5244 | intel_post_enable_primary(&crtc->base, pipe_config); |
5245 | } | ||
5173 | 5246 | ||
5174 | /* Display WA 827 */ | 5247 | /* Display WA 827 */ |
5175 | if ((INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) || | 5248 | if (needs_nv12_wa(dev_priv, old_crtc_state) && |
5176 | IS_CANNONLAKE(dev_priv)) { | 5249 | !needs_nv12_wa(dev_priv, pipe_config)) { |
5177 | if (fb && fb->format->format == DRM_FORMAT_NV12) | 5250 | skl_wa_clkgate(dev_priv, crtc->pipe, false); |
5178 | skl_wa_clkgate(dev_priv, crtc->pipe, false); | 5251 | skl_wa_528(dev_priv, crtc->pipe, false); |
5179 | } | ||
5180 | |||
5181 | } | 5252 | } |
5182 | } | 5253 | } |
5183 | 5254 | ||
@@ -5202,14 +5273,6 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, | |||
5202 | struct intel_plane_state *new_primary_state = | 5273 | struct intel_plane_state *new_primary_state = |
5203 | intel_atomic_get_new_plane_state(old_intel_state, | 5274 | intel_atomic_get_new_plane_state(old_intel_state, |
5204 | to_intel_plane(primary)); | 5275 | to_intel_plane(primary)); |
5205 | struct drm_framebuffer *fb = new_primary_state->base.fb; | ||
5206 | |||
5207 | /* Display WA 827 */ | ||
5208 | if ((INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) || | ||
5209 | IS_CANNONLAKE(dev_priv)) { | ||
5210 | if (fb && fb->format->format == DRM_FORMAT_NV12) | ||
5211 | skl_wa_clkgate(dev_priv, crtc->pipe, true); | ||
5212 | } | ||
5213 | 5276 | ||
5214 | intel_fbc_pre_update(crtc, pipe_config, new_primary_state); | 5277 | intel_fbc_pre_update(crtc, pipe_config, new_primary_state); |
5215 | /* | 5278 | /* |
@@ -5221,6 +5284,13 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, | |||
5221 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); | 5284 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); |
5222 | } | 5285 | } |
5223 | 5286 | ||
5287 | /* Display WA 827 */ | ||
5288 | if (!needs_nv12_wa(dev_priv, old_crtc_state) && | ||
5289 | needs_nv12_wa(dev_priv, pipe_config)) { | ||
5290 | skl_wa_clkgate(dev_priv, crtc->pipe, true); | ||
5291 | skl_wa_528(dev_priv, crtc->pipe, true); | ||
5292 | } | ||
5293 | |||
5224 | /* | 5294 | /* |
5225 | * Vblank time updates from the shadow to live plane control register | 5295 | * Vblank time updates from the shadow to live plane control register |
5226 | * are blocked if the memory self-refresh mode is active at that | 5296 | * are blocked if the memory self-refresh mode is active at that |
@@ -5555,6 +5625,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, | |||
5555 | if (intel_crtc->config->shared_dpll) | 5625 | if (intel_crtc->config->shared_dpll) |
5556 | intel_enable_shared_dpll(intel_crtc); | 5626 | intel_enable_shared_dpll(intel_crtc); |
5557 | 5627 | ||
5628 | if (INTEL_GEN(dev_priv) >= 11) | ||
5629 | icl_map_plls_to_ports(crtc, pipe_config, old_state); | ||
5630 | |||
5558 | if (intel_crtc_has_dp_encoder(intel_crtc->config)) | 5631 | if (intel_crtc_has_dp_encoder(intel_crtc->config)) |
5559 | intel_dp_set_m_n(intel_crtc, M1_N1); | 5632 | intel_dp_set_m_n(intel_crtc, M1_N1); |
5560 | 5633 | ||
@@ -5752,6 +5825,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, | |||
5752 | intel_ddi_disable_pipe_clock(intel_crtc->config); | 5825 | intel_ddi_disable_pipe_clock(intel_crtc->config); |
5753 | 5826 | ||
5754 | intel_encoders_post_disable(crtc, old_crtc_state, old_state); | 5827 | intel_encoders_post_disable(crtc, old_crtc_state, old_state); |
5828 | |||
5829 | if (INTEL_GEN(dev_priv) >= 11) | ||
5830 | icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state); | ||
5755 | } | 5831 | } |
5756 | 5832 | ||
5757 | static void i9xx_pfit_enable(struct intel_crtc *crtc) | 5833 | static void i9xx_pfit_enable(struct intel_crtc *crtc) |
@@ -11143,39 +11219,42 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11143 | (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) && | 11219 | (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) && |
11144 | !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED); | 11220 | !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED); |
11145 | 11221 | ||
11146 | #define PIPE_CONF_CHECK_X(name) \ | 11222 | #define PIPE_CONF_CHECK_X(name) do { \ |
11147 | if (current_config->name != pipe_config->name) { \ | 11223 | if (current_config->name != pipe_config->name) { \ |
11148 | pipe_config_err(adjust, __stringify(name), \ | 11224 | pipe_config_err(adjust, __stringify(name), \ |
11149 | "(expected 0x%08x, found 0x%08x)\n", \ | 11225 | "(expected 0x%08x, found 0x%08x)\n", \ |
11150 | current_config->name, \ | 11226 | current_config->name, \ |
11151 | pipe_config->name); \ | 11227 | pipe_config->name); \ |
11152 | ret = false; \ | 11228 | ret = false; \ |
11153 | } | 11229 | } \ |
11230 | } while (0) | ||
11154 | 11231 | ||
11155 | #define PIPE_CONF_CHECK_I(name) \ | 11232 | #define PIPE_CONF_CHECK_I(name) do { \ |
11156 | if (current_config->name != pipe_config->name) { \ | 11233 | if (current_config->name != pipe_config->name) { \ |
11157 | pipe_config_err(adjust, __stringify(name), \ | 11234 | pipe_config_err(adjust, __stringify(name), \ |
11158 | "(expected %i, found %i)\n", \ | 11235 | "(expected %i, found %i)\n", \ |
11159 | current_config->name, \ | 11236 | current_config->name, \ |
11160 | pipe_config->name); \ | 11237 | pipe_config->name); \ |
11161 | ret = false; \ | 11238 | ret = false; \ |
11162 | } | 11239 | } \ |
11240 | } while (0) | ||
11163 | 11241 | ||
11164 | #define PIPE_CONF_CHECK_BOOL(name) \ | 11242 | #define PIPE_CONF_CHECK_BOOL(name) do { \ |
11165 | if (current_config->name != pipe_config->name) { \ | 11243 | if (current_config->name != pipe_config->name) { \ |
11166 | pipe_config_err(adjust, __stringify(name), \ | 11244 | pipe_config_err(adjust, __stringify(name), \ |
11167 | "(expected %s, found %s)\n", \ | 11245 | "(expected %s, found %s)\n", \ |
11168 | yesno(current_config->name), \ | 11246 | yesno(current_config->name), \ |
11169 | yesno(pipe_config->name)); \ | 11247 | yesno(pipe_config->name)); \ |
11170 | ret = false; \ | 11248 | ret = false; \ |
11171 | } | 11249 | } \ |
11250 | } while (0) | ||
11172 | 11251 | ||
11173 | /* | 11252 | /* |
11174 | * Checks state where we only read out the enabling, but not the entire | 11253 | * Checks state where we only read out the enabling, but not the entire |
11175 | * state itself (like full infoframes or ELD for audio). These states | 11254 | * state itself (like full infoframes or ELD for audio). These states |
11176 | * require a full modeset on bootup to fix up. | 11255 | * require a full modeset on bootup to fix up. |
11177 | */ | 11256 | */ |
11178 | #define PIPE_CONF_CHECK_BOOL_INCOMPLETE(name) \ | 11257 | #define PIPE_CONF_CHECK_BOOL_INCOMPLETE(name) do { \ |
11179 | if (!fixup_inherited || (!current_config->name && !pipe_config->name)) { \ | 11258 | if (!fixup_inherited || (!current_config->name && !pipe_config->name)) { \ |
11180 | PIPE_CONF_CHECK_BOOL(name); \ | 11259 | PIPE_CONF_CHECK_BOOL(name); \ |
11181 | } else { \ | 11260 | } else { \ |
@@ -11184,18 +11263,20 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11184 | yesno(current_config->name), \ | 11263 | yesno(current_config->name), \ |
11185 | yesno(pipe_config->name)); \ | 11264 | yesno(pipe_config->name)); \ |
11186 | ret = false; \ | 11265 | ret = false; \ |
11187 | } | 11266 | } \ |
11267 | } while (0) | ||
11188 | 11268 | ||
11189 | #define PIPE_CONF_CHECK_P(name) \ | 11269 | #define PIPE_CONF_CHECK_P(name) do { \ |
11190 | if (current_config->name != pipe_config->name) { \ | 11270 | if (current_config->name != pipe_config->name) { \ |
11191 | pipe_config_err(adjust, __stringify(name), \ | 11271 | pipe_config_err(adjust, __stringify(name), \ |
11192 | "(expected %p, found %p)\n", \ | 11272 | "(expected %p, found %p)\n", \ |
11193 | current_config->name, \ | 11273 | current_config->name, \ |
11194 | pipe_config->name); \ | 11274 | pipe_config->name); \ |
11195 | ret = false; \ | 11275 | ret = false; \ |
11196 | } | 11276 | } \ |
11277 | } while (0) | ||
11197 | 11278 | ||
11198 | #define PIPE_CONF_CHECK_M_N(name) \ | 11279 | #define PIPE_CONF_CHECK_M_N(name) do { \ |
11199 | if (!intel_compare_link_m_n(¤t_config->name, \ | 11280 | if (!intel_compare_link_m_n(¤t_config->name, \ |
11200 | &pipe_config->name,\ | 11281 | &pipe_config->name,\ |
11201 | adjust)) { \ | 11282 | adjust)) { \ |
@@ -11213,14 +11294,15 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11213 | pipe_config->name.link_m, \ | 11294 | pipe_config->name.link_m, \ |
11214 | pipe_config->name.link_n); \ | 11295 | pipe_config->name.link_n); \ |
11215 | ret = false; \ | 11296 | ret = false; \ |
11216 | } | 11297 | } \ |
11298 | } while (0) | ||
11217 | 11299 | ||
11218 | /* This is required for BDW+ where there is only one set of registers for | 11300 | /* This is required for BDW+ where there is only one set of registers for |
11219 | * switching between high and low RR. | 11301 | * switching between high and low RR. |
11220 | * This macro can be used whenever a comparison has to be made between one | 11302 | * This macro can be used whenever a comparison has to be made between one |
11221 | * hw state and multiple sw state variables. | 11303 | * hw state and multiple sw state variables. |
11222 | */ | 11304 | */ |
11223 | #define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) \ | 11305 | #define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) do { \ |
11224 | if (!intel_compare_link_m_n(¤t_config->name, \ | 11306 | if (!intel_compare_link_m_n(¤t_config->name, \ |
11225 | &pipe_config->name, adjust) && \ | 11307 | &pipe_config->name, adjust) && \ |
11226 | !intel_compare_link_m_n(¤t_config->alt_name, \ | 11308 | !intel_compare_link_m_n(¤t_config->alt_name, \ |
@@ -11245,9 +11327,10 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11245 | pipe_config->name.link_m, \ | 11327 | pipe_config->name.link_m, \ |
11246 | pipe_config->name.link_n); \ | 11328 | pipe_config->name.link_n); \ |
11247 | ret = false; \ | 11329 | ret = false; \ |
11248 | } | 11330 | } \ |
11331 | } while (0) | ||
11249 | 11332 | ||
11250 | #define PIPE_CONF_CHECK_FLAGS(name, mask) \ | 11333 | #define PIPE_CONF_CHECK_FLAGS(name, mask) do { \ |
11251 | if ((current_config->name ^ pipe_config->name) & (mask)) { \ | 11334 | if ((current_config->name ^ pipe_config->name) & (mask)) { \ |
11252 | pipe_config_err(adjust, __stringify(name), \ | 11335 | pipe_config_err(adjust, __stringify(name), \ |
11253 | "(%x) (expected %i, found %i)\n", \ | 11336 | "(%x) (expected %i, found %i)\n", \ |
@@ -11255,16 +11338,18 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11255 | current_config->name & (mask), \ | 11338 | current_config->name & (mask), \ |
11256 | pipe_config->name & (mask)); \ | 11339 | pipe_config->name & (mask)); \ |
11257 | ret = false; \ | 11340 | ret = false; \ |
11258 | } | 11341 | } \ |
11342 | } while (0) | ||
11259 | 11343 | ||
11260 | #define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \ | 11344 | #define PIPE_CONF_CHECK_CLOCK_FUZZY(name) do { \ |
11261 | if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \ | 11345 | if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \ |
11262 | pipe_config_err(adjust, __stringify(name), \ | 11346 | pipe_config_err(adjust, __stringify(name), \ |
11263 | "(expected %i, found %i)\n", \ | 11347 | "(expected %i, found %i)\n", \ |
11264 | current_config->name, \ | 11348 | current_config->name, \ |
11265 | pipe_config->name); \ | 11349 | pipe_config->name); \ |
11266 | ret = false; \ | 11350 | ret = false; \ |
11267 | } | 11351 | } \ |
11352 | } while (0) | ||
11268 | 11353 | ||
11269 | #define PIPE_CONF_QUIRK(quirk) \ | 11354 | #define PIPE_CONF_QUIRK(quirk) \ |
11270 | ((current_config->quirks | pipe_config->quirks) & (quirk)) | 11355 | ((current_config->quirks | pipe_config->quirks) & (quirk)) |
@@ -11373,6 +11458,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, | |||
11373 | PIPE_CONF_CHECK_X(dpll_hw_state.pll9); | 11458 | PIPE_CONF_CHECK_X(dpll_hw_state.pll9); |
11374 | PIPE_CONF_CHECK_X(dpll_hw_state.pll10); | 11459 | PIPE_CONF_CHECK_X(dpll_hw_state.pll10); |
11375 | PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); | 11460 | PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); |
11461 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl); | ||
11462 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1); | ||
11463 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl); | ||
11464 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0); | ||
11465 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1); | ||
11466 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf); | ||
11467 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock); | ||
11468 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc); | ||
11469 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias); | ||
11470 | PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias); | ||
11376 | 11471 | ||
11377 | PIPE_CONF_CHECK_X(dsi_pll.ctrl); | 11472 | PIPE_CONF_CHECK_X(dsi_pll.ctrl); |
11378 | PIPE_CONF_CHECK_X(dsi_pll.div); | 11473 | PIPE_CONF_CHECK_X(dsi_pll.div); |
@@ -11436,6 +11531,11 @@ static void verify_wm_state(struct drm_crtc *crtc, | |||
11436 | skl_ddb_get_hw_state(dev_priv, &hw_ddb); | 11531 | skl_ddb_get_hw_state(dev_priv, &hw_ddb); |
11437 | sw_ddb = &dev_priv->wm.skl_hw.ddb; | 11532 | sw_ddb = &dev_priv->wm.skl_hw.ddb; |
11438 | 11533 | ||
11534 | if (INTEL_GEN(dev_priv) >= 11) | ||
11535 | if (hw_ddb.enabled_slices != sw_ddb->enabled_slices) | ||
11536 | DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n", | ||
11537 | sw_ddb->enabled_slices, | ||
11538 | hw_ddb.enabled_slices); | ||
11439 | /* planes */ | 11539 | /* planes */ |
11440 | for_each_universal_plane(dev_priv, pipe, plane) { | 11540 | for_each_universal_plane(dev_priv, pipe, plane) { |
11441 | hw_plane_wm = &hw_wm.planes[plane]; | 11541 | hw_plane_wm = &hw_wm.planes[plane]; |
@@ -12242,6 +12342,8 @@ static void skl_update_crtcs(struct drm_atomic_state *state) | |||
12242 | bool progress; | 12342 | bool progress; |
12243 | enum pipe pipe; | 12343 | enum pipe pipe; |
12244 | int i; | 12344 | int i; |
12345 | u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices; | ||
12346 | u8 required_slices = intel_state->wm_results.ddb.enabled_slices; | ||
12245 | 12347 | ||
12246 | const struct skl_ddb_entry *entries[I915_MAX_PIPES] = {}; | 12348 | const struct skl_ddb_entry *entries[I915_MAX_PIPES] = {}; |
12247 | 12349 | ||
@@ -12250,6 +12352,10 @@ static void skl_update_crtcs(struct drm_atomic_state *state) | |||
12250 | if (new_crtc_state->active) | 12352 | if (new_crtc_state->active) |
12251 | entries[i] = &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb; | 12353 | entries[i] = &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb; |
12252 | 12354 | ||
12355 | /* If 2nd DBuf slice required, enable it here */ | ||
12356 | if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices) | ||
12357 | icl_dbuf_slices_update(dev_priv, required_slices); | ||
12358 | |||
12253 | /* | 12359 | /* |
12254 | * Whenever the number of active pipes changes, we need to make sure we | 12360 | * Whenever the number of active pipes changes, we need to make sure we |
12255 | * update the pipes in the right order so that their ddb allocations | 12361 | * update the pipes in the right order so that their ddb allocations |
@@ -12300,6 +12406,10 @@ static void skl_update_crtcs(struct drm_atomic_state *state) | |||
12300 | progress = true; | 12406 | progress = true; |
12301 | } | 12407 | } |
12302 | } while (progress); | 12408 | } while (progress); |
12409 | |||
12410 | /* If 2nd DBuf slice is no more required disable it */ | ||
12411 | if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices) | ||
12412 | icl_dbuf_slices_update(dev_priv, required_slices); | ||
12303 | } | 12413 | } |
12304 | 12414 | ||
12305 | static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv) | 12415 | static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv) |
@@ -12763,6 +12873,15 @@ static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state) | |||
12763 | intel_unpin_fb_vma(vma, old_plane_state->flags); | 12873 | intel_unpin_fb_vma(vma, old_plane_state->flags); |
12764 | } | 12874 | } |
12765 | 12875 | ||
12876 | static void fb_obj_bump_render_priority(struct drm_i915_gem_object *obj) | ||
12877 | { | ||
12878 | struct i915_sched_attr attr = { | ||
12879 | .priority = I915_PRIORITY_DISPLAY, | ||
12880 | }; | ||
12881 | |||
12882 | i915_gem_object_wait_priority(obj, 0, &attr); | ||
12883 | } | ||
12884 | |||
12766 | /** | 12885 | /** |
12767 | * intel_prepare_plane_fb - Prepare fb for usage on plane | 12886 | * intel_prepare_plane_fb - Prepare fb for usage on plane |
12768 | * @plane: drm plane to prepare for | 12887 | * @plane: drm plane to prepare for |
@@ -12839,7 +12958,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
12839 | 12958 | ||
12840 | ret = intel_plane_pin_fb(to_intel_plane_state(new_state)); | 12959 | ret = intel_plane_pin_fb(to_intel_plane_state(new_state)); |
12841 | 12960 | ||
12842 | i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY); | 12961 | fb_obj_bump_render_priority(obj); |
12843 | 12962 | ||
12844 | mutex_unlock(&dev_priv->drm.struct_mutex); | 12963 | mutex_unlock(&dev_priv->drm.struct_mutex); |
12845 | i915_gem_object_unpin_pages(obj); | 12964 | i915_gem_object_unpin_pages(obj); |
@@ -13115,6 +13234,7 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier) | |||
13115 | case DRM_FORMAT_YVYU: | 13234 | case DRM_FORMAT_YVYU: |
13116 | case DRM_FORMAT_UYVY: | 13235 | case DRM_FORMAT_UYVY: |
13117 | case DRM_FORMAT_VYUY: | 13236 | case DRM_FORMAT_VYUY: |
13237 | case DRM_FORMAT_NV12: | ||
13118 | if (modifier == I915_FORMAT_MOD_Yf_TILED) | 13238 | if (modifier == I915_FORMAT_MOD_Yf_TILED) |
13119 | return true; | 13239 | return true; |
13120 | /* fall through */ | 13240 | /* fall through */ |
@@ -13322,6 +13442,30 @@ static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv, | |||
13322 | return pipe == PIPE_A && plane_id == PLANE_PRIMARY; | 13442 | return pipe == PIPE_A && plane_id == PLANE_PRIMARY; |
13323 | } | 13443 | } |
13324 | 13444 | ||
13445 | bool skl_plane_has_planar(struct drm_i915_private *dev_priv, | ||
13446 | enum pipe pipe, enum plane_id plane_id) | ||
13447 | { | ||
13448 | if (plane_id == PLANE_PRIMARY) { | ||
13449 | if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) | ||
13450 | return false; | ||
13451 | else if ((INTEL_GEN(dev_priv) == 9 && pipe == PIPE_C) && | ||
13452 | !IS_GEMINILAKE(dev_priv)) | ||
13453 | return false; | ||
13454 | } else if (plane_id >= PLANE_SPRITE0) { | ||
13455 | if (plane_id == PLANE_CURSOR) | ||
13456 | return false; | ||
13457 | if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) == 10) { | ||
13458 | if (plane_id != PLANE_SPRITE0) | ||
13459 | return false; | ||
13460 | } else { | ||
13461 | if (plane_id != PLANE_SPRITE0 || pipe == PIPE_C || | ||
13462 | IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) | ||
13463 | return false; | ||
13464 | } | ||
13465 | } | ||
13466 | return true; | ||
13467 | } | ||
13468 | |||
13325 | static struct intel_plane * | 13469 | static struct intel_plane * |
13326 | intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) | 13470 | intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) |
13327 | { | 13471 | { |
@@ -13382,8 +13526,13 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
13382 | primary->check_plane = intel_check_primary_plane; | 13526 | primary->check_plane = intel_check_primary_plane; |
13383 | 13527 | ||
13384 | if (INTEL_GEN(dev_priv) >= 9) { | 13528 | if (INTEL_GEN(dev_priv) >= 9) { |
13385 | intel_primary_formats = skl_primary_formats; | 13529 | if (skl_plane_has_planar(dev_priv, pipe, PLANE_PRIMARY)) { |
13386 | num_formats = ARRAY_SIZE(skl_primary_formats); | 13530 | intel_primary_formats = skl_pri_planar_formats; |
13531 | num_formats = ARRAY_SIZE(skl_pri_planar_formats); | ||
13532 | } else { | ||
13533 | intel_primary_formats = skl_primary_formats; | ||
13534 | num_formats = ARRAY_SIZE(skl_primary_formats); | ||
13535 | } | ||
13387 | 13536 | ||
13388 | if (skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY)) | 13537 | if (skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY)) |
13389 | modifiers = skl_format_modifiers_ccs; | 13538 | modifiers = skl_format_modifiers_ccs; |
@@ -14204,6 +14353,20 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, | |||
14204 | goto err; | 14353 | goto err; |
14205 | } | 14354 | } |
14206 | break; | 14355 | break; |
14356 | case DRM_FORMAT_NV12: | ||
14357 | if (mode_cmd->modifier[0] == I915_FORMAT_MOD_Y_TILED_CCS || | ||
14358 | mode_cmd->modifier[0] == I915_FORMAT_MOD_Yf_TILED_CCS) { | ||
14359 | DRM_DEBUG_KMS("RC not to be enabled with NV12\n"); | ||
14360 | goto err; | ||
14361 | } | ||
14362 | if (INTEL_GEN(dev_priv) < 9 || IS_SKYLAKE(dev_priv) || | ||
14363 | IS_BROXTON(dev_priv)) { | ||
14364 | DRM_DEBUG_KMS("unsupported pixel format: %s\n", | ||
14365 | drm_get_format_name(mode_cmd->pixel_format, | ||
14366 | &format_name)); | ||
14367 | goto err; | ||
14368 | } | ||
14369 | break; | ||
14207 | default: | 14370 | default: |
14208 | DRM_DEBUG_KMS("unsupported pixel format: %s\n", | 14371 | DRM_DEBUG_KMS("unsupported pixel format: %s\n", |
14209 | drm_get_format_name(mode_cmd->pixel_format, &format_name)); | 14372 | drm_get_format_name(mode_cmd->pixel_format, &format_name)); |
@@ -14216,6 +14379,14 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, | |||
14216 | 14379 | ||
14217 | drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd); | 14380 | drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd); |
14218 | 14381 | ||
14382 | if (fb->format->format == DRM_FORMAT_NV12 && | ||
14383 | (fb->width < SKL_MIN_YUV_420_SRC_W || | ||
14384 | fb->height < SKL_MIN_YUV_420_SRC_H || | ||
14385 | (fb->width % 4) != 0 || (fb->height % 4) != 0)) { | ||
14386 | DRM_DEBUG_KMS("src dimensions not correct for NV12\n"); | ||
14387 | return -EINVAL; | ||
14388 | } | ||
14389 | |||
14219 | for (i = 0; i < fb->format->num_planes; i++) { | 14390 | for (i = 0; i < fb->format->num_planes; i++) { |
14220 | u32 stride_alignment; | 14391 | u32 stride_alignment; |
14221 | 14392 | ||
@@ -15270,6 +15441,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) | |||
15270 | memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); | 15441 | memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); |
15271 | if (crtc_state->base.active) { | 15442 | if (crtc_state->base.active) { |
15272 | intel_mode_from_pipe_config(&crtc->base.mode, crtc_state); | 15443 | intel_mode_from_pipe_config(&crtc->base.mode, crtc_state); |
15444 | crtc->base.mode.hdisplay = crtc_state->pipe_src_w; | ||
15445 | crtc->base.mode.vdisplay = crtc_state->pipe_src_h; | ||
15273 | intel_mode_from_pipe_config(&crtc_state->base.adjusted_mode, crtc_state); | 15446 | intel_mode_from_pipe_config(&crtc_state->base.adjusted_mode, crtc_state); |
15274 | WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode)); | 15447 | WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode)); |
15275 | 15448 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h index 4e7418b345bc..2ef31617614a 100644 --- a/drivers/gpu/drm/i915/intel_display.h +++ b/drivers/gpu/drm/i915/intel_display.h | |||
@@ -218,6 +218,10 @@ struct intel_link_m_n { | |||
218 | for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) \ | 218 | for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) \ |
219 | for_each_if((__mask) & BIT(__p)) | 219 | for_each_if((__mask) & BIT(__p)) |
220 | 220 | ||
221 | #define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \ | ||
222 | for ((__t) = 0; (__t) < I915_MAX_TRANSCODERS; (__t)++) \ | ||
223 | for_each_if ((__mask) & (1 << (__t))) | ||
224 | |||
221 | #define for_each_universal_plane(__dev_priv, __pipe, __p) \ | 225 | #define for_each_universal_plane(__dev_priv, __pipe, __p) \ |
222 | for ((__p) = 0; \ | 226 | for ((__p) = 0; \ |
223 | (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \ | 227 | (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \ |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 62f82c4298ac..dde92e4af5d3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1647,9 +1647,17 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, | |||
1647 | } | 1647 | } |
1648 | } | 1648 | } |
1649 | 1649 | ||
1650 | struct link_config_limits { | ||
1651 | int min_clock, max_clock; | ||
1652 | int min_lane_count, max_lane_count; | ||
1653 | int min_bpp, max_bpp; | ||
1654 | }; | ||
1655 | |||
1650 | static int intel_dp_compute_bpp(struct intel_dp *intel_dp, | 1656 | static int intel_dp_compute_bpp(struct intel_dp *intel_dp, |
1651 | struct intel_crtc_state *pipe_config) | 1657 | struct intel_crtc_state *pipe_config) |
1652 | { | 1658 | { |
1659 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | ||
1660 | struct intel_connector *intel_connector = intel_dp->attached_connector; | ||
1653 | int bpp, bpc; | 1661 | int bpp, bpc; |
1654 | 1662 | ||
1655 | bpp = pipe_config->pipe_bpp; | 1663 | bpp = pipe_config->pipe_bpp; |
@@ -1658,13 +1666,16 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp, | |||
1658 | if (bpc > 0) | 1666 | if (bpc > 0) |
1659 | bpp = min(bpp, 3*bpc); | 1667 | bpp = min(bpp, 3*bpc); |
1660 | 1668 | ||
1661 | /* For DP Compliance we override the computed bpp for the pipe */ | 1669 | if (intel_dp_is_edp(intel_dp)) { |
1662 | if (intel_dp->compliance.test_data.bpc != 0) { | 1670 | /* Get bpp from vbt only for panels that dont have bpp in edid */ |
1663 | pipe_config->pipe_bpp = 3*intel_dp->compliance.test_data.bpc; | 1671 | if (intel_connector->base.display_info.bpc == 0 && |
1664 | pipe_config->dither_force_disable = pipe_config->pipe_bpp == 6*3; | 1672 | dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp) { |
1665 | DRM_DEBUG_KMS("Setting pipe_bpp to %d\n", | 1673 | DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", |
1666 | pipe_config->pipe_bpp); | 1674 | dev_priv->vbt.edp.bpp); |
1675 | bpp = dev_priv->vbt.edp.bpp; | ||
1676 | } | ||
1667 | } | 1677 | } |
1678 | |||
1668 | return bpp; | 1679 | return bpp; |
1669 | } | 1680 | } |
1670 | 1681 | ||
@@ -1685,6 +1696,142 @@ static bool intel_edp_compare_alt_mode(struct drm_display_mode *m1, | |||
1685 | return bres; | 1696 | return bres; |
1686 | } | 1697 | } |
1687 | 1698 | ||
1699 | /* Adjust link config limits based on compliance test requests. */ | ||
1700 | static void | ||
1701 | intel_dp_adjust_compliance_config(struct intel_dp *intel_dp, | ||
1702 | struct intel_crtc_state *pipe_config, | ||
1703 | struct link_config_limits *limits) | ||
1704 | { | ||
1705 | /* For DP Compliance we override the computed bpp for the pipe */ | ||
1706 | if (intel_dp->compliance.test_data.bpc != 0) { | ||
1707 | int bpp = 3 * intel_dp->compliance.test_data.bpc; | ||
1708 | |||
1709 | limits->min_bpp = limits->max_bpp = bpp; | ||
1710 | pipe_config->dither_force_disable = bpp == 6 * 3; | ||
1711 | |||
1712 | DRM_DEBUG_KMS("Setting pipe_bpp to %d\n", bpp); | ||
1713 | } | ||
1714 | |||
1715 | /* Use values requested by Compliance Test Request */ | ||
1716 | if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { | ||
1717 | int index; | ||
1718 | |||
1719 | /* Validate the compliance test data since max values | ||
1720 | * might have changed due to link train fallback. | ||
1721 | */ | ||
1722 | if (intel_dp_link_params_valid(intel_dp, intel_dp->compliance.test_link_rate, | ||
1723 | intel_dp->compliance.test_lane_count)) { | ||
1724 | index = intel_dp_rate_index(intel_dp->common_rates, | ||
1725 | intel_dp->num_common_rates, | ||
1726 | intel_dp->compliance.test_link_rate); | ||
1727 | if (index >= 0) | ||
1728 | limits->min_clock = limits->max_clock = index; | ||
1729 | limits->min_lane_count = limits->max_lane_count = | ||
1730 | intel_dp->compliance.test_lane_count; | ||
1731 | } | ||
1732 | } | ||
1733 | } | ||
1734 | |||
1735 | /* Optimize link config in order: max bpp, min clock, min lanes */ | ||
1736 | static bool | ||
1737 | intel_dp_compute_link_config_wide(struct intel_dp *intel_dp, | ||
1738 | struct intel_crtc_state *pipe_config, | ||
1739 | const struct link_config_limits *limits) | ||
1740 | { | ||
1741 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; | ||
1742 | int bpp, clock, lane_count; | ||
1743 | int mode_rate, link_clock, link_avail; | ||
1744 | |||
1745 | for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { | ||
1746 | mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, | ||
1747 | bpp); | ||
1748 | |||
1749 | for (clock = limits->min_clock; clock <= limits->max_clock; clock++) { | ||
1750 | for (lane_count = limits->min_lane_count; | ||
1751 | lane_count <= limits->max_lane_count; | ||
1752 | lane_count <<= 1) { | ||
1753 | link_clock = intel_dp->common_rates[clock]; | ||
1754 | link_avail = intel_dp_max_data_rate(link_clock, | ||
1755 | lane_count); | ||
1756 | |||
1757 | if (mode_rate <= link_avail) { | ||
1758 | pipe_config->lane_count = lane_count; | ||
1759 | pipe_config->pipe_bpp = bpp; | ||
1760 | pipe_config->port_clock = link_clock; | ||
1761 | |||
1762 | return true; | ||
1763 | } | ||
1764 | } | ||
1765 | } | ||
1766 | } | ||
1767 | |||
1768 | return false; | ||
1769 | } | ||
1770 | |||
1771 | static bool | ||
1772 | intel_dp_compute_link_config(struct intel_encoder *encoder, | ||
1773 | struct intel_crtc_state *pipe_config) | ||
1774 | { | ||
1775 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; | ||
1776 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | ||
1777 | struct link_config_limits limits; | ||
1778 | int common_len; | ||
1779 | |||
1780 | common_len = intel_dp_common_len_rate_limit(intel_dp, | ||
1781 | intel_dp->max_link_rate); | ||
1782 | |||
1783 | /* No common link rates between source and sink */ | ||
1784 | WARN_ON(common_len <= 0); | ||
1785 | |||
1786 | limits.min_clock = 0; | ||
1787 | limits.max_clock = common_len - 1; | ||
1788 | |||
1789 | limits.min_lane_count = 1; | ||
1790 | limits.max_lane_count = intel_dp_max_lane_count(intel_dp); | ||
1791 | |||
1792 | limits.min_bpp = 6 * 3; | ||
1793 | limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config); | ||
1794 | |||
1795 | if (intel_dp_is_edp(intel_dp)) { | ||
1796 | /* | ||
1797 | * Use the maximum clock and number of lanes the eDP panel | ||
1798 | * advertizes being capable of. The panels are generally | ||
1799 | * designed to support only a single clock and lane | ||
1800 | * configuration, and typically these values correspond to the | ||
1801 | * native resolution of the panel. | ||
1802 | */ | ||
1803 | limits.min_lane_count = limits.max_lane_count; | ||
1804 | limits.min_clock = limits.max_clock; | ||
1805 | } | ||
1806 | |||
1807 | intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits); | ||
1808 | |||
1809 | DRM_DEBUG_KMS("DP link computation with max lane count %i " | ||
1810 | "max rate %d max bpp %d pixel clock %iKHz\n", | ||
1811 | limits.max_lane_count, | ||
1812 | intel_dp->common_rates[limits.max_clock], | ||
1813 | limits.max_bpp, adjusted_mode->crtc_clock); | ||
1814 | |||
1815 | /* | ||
1816 | * Optimize for slow and wide. This is the place to add alternative | ||
1817 | * optimization policy. | ||
1818 | */ | ||
1819 | if (!intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits)) | ||
1820 | return false; | ||
1821 | |||
1822 | DRM_DEBUG_KMS("DP lane count %d clock %d bpp %d\n", | ||
1823 | pipe_config->lane_count, pipe_config->port_clock, | ||
1824 | pipe_config->pipe_bpp); | ||
1825 | |||
1826 | DRM_DEBUG_KMS("DP link rate required %i available %i\n", | ||
1827 | intel_dp_link_required(adjusted_mode->crtc_clock, | ||
1828 | pipe_config->pipe_bpp), | ||
1829 | intel_dp_max_data_rate(pipe_config->port_clock, | ||
1830 | pipe_config->lane_count)); | ||
1831 | |||
1832 | return true; | ||
1833 | } | ||
1834 | |||
1688 | bool | 1835 | bool |
1689 | intel_dp_compute_config(struct intel_encoder *encoder, | 1836 | intel_dp_compute_config(struct intel_encoder *encoder, |
1690 | struct intel_crtc_state *pipe_config, | 1837 | struct intel_crtc_state *pipe_config, |
@@ -1698,27 +1845,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
1698 | struct intel_connector *intel_connector = intel_dp->attached_connector; | 1845 | struct intel_connector *intel_connector = intel_dp->attached_connector; |
1699 | struct intel_digital_connector_state *intel_conn_state = | 1846 | struct intel_digital_connector_state *intel_conn_state = |
1700 | to_intel_digital_connector_state(conn_state); | 1847 | to_intel_digital_connector_state(conn_state); |
1701 | int lane_count, clock; | ||
1702 | int min_lane_count = 1; | ||
1703 | int max_lane_count = intel_dp_max_lane_count(intel_dp); | ||
1704 | /* Conveniently, the link BW constants become indices with a shift...*/ | ||
1705 | int min_clock = 0; | ||
1706 | int max_clock; | ||
1707 | int bpp, mode_rate; | ||
1708 | int link_avail, link_clock; | ||
1709 | int common_len; | ||
1710 | uint8_t link_bw, rate_select; | ||
1711 | bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, | 1848 | bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, |
1712 | DP_DPCD_QUIRK_LIMITED_M_N); | 1849 | DP_DPCD_QUIRK_LIMITED_M_N); |
1713 | 1850 | ||
1714 | common_len = intel_dp_common_len_rate_limit(intel_dp, | ||
1715 | intel_dp->max_link_rate); | ||
1716 | |||
1717 | /* No common link rates between source and sink */ | ||
1718 | WARN_ON(common_len <= 0); | ||
1719 | |||
1720 | max_clock = common_len - 1; | ||
1721 | |||
1722 | if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A) | 1851 | if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A) |
1723 | pipe_config->has_pch_encoder = true; | 1852 | pipe_config->has_pch_encoder = true; |
1724 | 1853 | ||
@@ -1744,6 +1873,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
1744 | 1873 | ||
1745 | if (INTEL_GEN(dev_priv) >= 9) { | 1874 | if (INTEL_GEN(dev_priv) >= 9) { |
1746 | int ret; | 1875 | int ret; |
1876 | |||
1747 | ret = skl_update_scaler_crtc(pipe_config); | 1877 | ret = skl_update_scaler_crtc(pipe_config); |
1748 | if (ret) | 1878 | if (ret) |
1749 | return ret; | 1879 | return ret; |
@@ -1764,75 +1894,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
1764 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) | 1894 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) |
1765 | return false; | 1895 | return false; |
1766 | 1896 | ||
1767 | /* Use values requested by Compliance Test Request */ | 1897 | if (!intel_dp_compute_link_config(encoder, pipe_config)) |
1768 | if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { | 1898 | return false; |
1769 | int index; | ||
1770 | |||
1771 | /* Validate the compliance test data since max values | ||
1772 | * might have changed due to link train fallback. | ||
1773 | */ | ||
1774 | if (intel_dp_link_params_valid(intel_dp, intel_dp->compliance.test_link_rate, | ||
1775 | intel_dp->compliance.test_lane_count)) { | ||
1776 | index = intel_dp_rate_index(intel_dp->common_rates, | ||
1777 | intel_dp->num_common_rates, | ||
1778 | intel_dp->compliance.test_link_rate); | ||
1779 | if (index >= 0) | ||
1780 | min_clock = max_clock = index; | ||
1781 | min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count; | ||
1782 | } | ||
1783 | } | ||
1784 | DRM_DEBUG_KMS("DP link computation with max lane count %i " | ||
1785 | "max bw %d pixel clock %iKHz\n", | ||
1786 | max_lane_count, intel_dp->common_rates[max_clock], | ||
1787 | adjusted_mode->crtc_clock); | ||
1788 | |||
1789 | /* Walk through all bpp values. Luckily they're all nicely spaced with 2 | ||
1790 | * bpc in between. */ | ||
1791 | bpp = intel_dp_compute_bpp(intel_dp, pipe_config); | ||
1792 | if (intel_dp_is_edp(intel_dp)) { | ||
1793 | |||
1794 | /* Get bpp from vbt only for panels that dont have bpp in edid */ | ||
1795 | if (intel_connector->base.display_info.bpc == 0 && | ||
1796 | (dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp)) { | ||
1797 | DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", | ||
1798 | dev_priv->vbt.edp.bpp); | ||
1799 | bpp = dev_priv->vbt.edp.bpp; | ||
1800 | } | ||
1801 | |||
1802 | /* | ||
1803 | * Use the maximum clock and number of lanes the eDP panel | ||
1804 | * advertizes being capable of. The panels are generally | ||
1805 | * designed to support only a single clock and lane | ||
1806 | * configuration, and typically these values correspond to the | ||
1807 | * native resolution of the panel. | ||
1808 | */ | ||
1809 | min_lane_count = max_lane_count; | ||
1810 | min_clock = max_clock; | ||
1811 | } | ||
1812 | |||
1813 | for (; bpp >= 6*3; bpp -= 2*3) { | ||
1814 | mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, | ||
1815 | bpp); | ||
1816 | |||
1817 | for (clock = min_clock; clock <= max_clock; clock++) { | ||
1818 | for (lane_count = min_lane_count; | ||
1819 | lane_count <= max_lane_count; | ||
1820 | lane_count <<= 1) { | ||
1821 | |||
1822 | link_clock = intel_dp->common_rates[clock]; | ||
1823 | link_avail = intel_dp_max_data_rate(link_clock, | ||
1824 | lane_count); | ||
1825 | |||
1826 | if (mode_rate <= link_avail) { | ||
1827 | goto found; | ||
1828 | } | ||
1829 | } | ||
1830 | } | ||
1831 | } | ||
1832 | |||
1833 | return false; | ||
1834 | 1899 | ||
1835 | found: | ||
1836 | if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { | 1900 | if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { |
1837 | /* | 1901 | /* |
1838 | * See: | 1902 | * See: |
@@ -1840,7 +1904,7 @@ found: | |||
1840 | * VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry | 1904 | * VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry |
1841 | */ | 1905 | */ |
1842 | pipe_config->limited_color_range = | 1906 | pipe_config->limited_color_range = |
1843 | bpp != 18 && | 1907 | pipe_config->pipe_bpp != 18 && |
1844 | drm_default_rgb_quant_range(adjusted_mode) == | 1908 | drm_default_rgb_quant_range(adjusted_mode) == |
1845 | HDMI_QUANTIZATION_RANGE_LIMITED; | 1909 | HDMI_QUANTIZATION_RANGE_LIMITED; |
1846 | } else { | 1910 | } else { |
@@ -1848,21 +1912,7 @@ found: | |||
1848 | intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED; | 1912 | intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED; |
1849 | } | 1913 | } |
1850 | 1914 | ||
1851 | pipe_config->lane_count = lane_count; | 1915 | intel_link_compute_m_n(pipe_config->pipe_bpp, pipe_config->lane_count, |
1852 | |||
1853 | pipe_config->pipe_bpp = bpp; | ||
1854 | pipe_config->port_clock = intel_dp->common_rates[clock]; | ||
1855 | |||
1856 | intel_dp_compute_rate(intel_dp, pipe_config->port_clock, | ||
1857 | &link_bw, &rate_select); | ||
1858 | |||
1859 | DRM_DEBUG_KMS("DP link bw %02x rate select %02x lane count %d clock %d bpp %d\n", | ||
1860 | link_bw, rate_select, pipe_config->lane_count, | ||
1861 | pipe_config->port_clock, bpp); | ||
1862 | DRM_DEBUG_KMS("DP link bw required %i available %i\n", | ||
1863 | mode_rate, link_avail); | ||
1864 | |||
1865 | intel_link_compute_m_n(bpp, lane_count, | ||
1866 | adjusted_mode->crtc_clock, | 1916 | adjusted_mode->crtc_clock, |
1867 | pipe_config->port_clock, | 1917 | pipe_config->port_clock, |
1868 | &pipe_config->dp_m_n, | 1918 | &pipe_config->dp_m_n, |
@@ -1871,31 +1921,12 @@ found: | |||
1871 | if (intel_connector->panel.downclock_mode != NULL && | 1921 | if (intel_connector->panel.downclock_mode != NULL && |
1872 | dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { | 1922 | dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { |
1873 | pipe_config->has_drrs = true; | 1923 | pipe_config->has_drrs = true; |
1874 | intel_link_compute_m_n(bpp, lane_count, | 1924 | intel_link_compute_m_n(pipe_config->pipe_bpp, |
1875 | intel_connector->panel.downclock_mode->clock, | 1925 | pipe_config->lane_count, |
1876 | pipe_config->port_clock, | 1926 | intel_connector->panel.downclock_mode->clock, |
1877 | &pipe_config->dp_m2_n2, | 1927 | pipe_config->port_clock, |
1878 | reduce_m_n); | 1928 | &pipe_config->dp_m2_n2, |
1879 | } | 1929 | reduce_m_n); |
1880 | |||
1881 | /* | ||
1882 | * DPLL0 VCO may need to be adjusted to get the correct | ||
1883 | * clock for eDP. This will affect cdclk as well. | ||
1884 | */ | ||
1885 | if (intel_dp_is_edp(intel_dp) && IS_GEN9_BC(dev_priv)) { | ||
1886 | int vco; | ||
1887 | |||
1888 | switch (pipe_config->port_clock / 2) { | ||
1889 | case 108000: | ||
1890 | case 216000: | ||
1891 | vco = 8640000; | ||
1892 | break; | ||
1893 | default: | ||
1894 | vco = 8100000; | ||
1895 | break; | ||
1896 | } | ||
1897 | |||
1898 | to_intel_atomic_state(pipe_config->base.state)->cdclk.logical.vco = vco; | ||
1899 | } | 1930 | } |
1900 | 1931 | ||
1901 | if (!HAS_DDI(dev_priv)) | 1932 | if (!HAS_DDI(dev_priv)) |
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index f59b59bb0a21..3fcaa98b9055 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c | |||
@@ -139,6 +139,11 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) | |||
139 | intel_dp_compute_rate(intel_dp, intel_dp->link_rate, | 139 | intel_dp_compute_rate(intel_dp, intel_dp->link_rate, |
140 | &link_bw, &rate_select); | 140 | &link_bw, &rate_select); |
141 | 141 | ||
142 | if (link_bw) | ||
143 | DRM_DEBUG_KMS("Using LINK_BW_SET value %02x\n", link_bw); | ||
144 | else | ||
145 | DRM_DEBUG_KMS("Using LINK_RATE_SET value %02x\n", rate_select); | ||
146 | |||
142 | /* Write the link configuration data */ | 147 | /* Write the link configuration data */ |
143 | link_config[0] = link_bw; | 148 | link_config[0] = link_bw; |
144 | link_config[1] = intel_dp->lane_count; | 149 | link_config[1] = intel_dp->lane_count; |
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index d5e114e9660b..383fbc15113d 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c | |||
@@ -2218,6 +2218,7 @@ cnl_ddi_calculate_wrpll(int clock, | |||
2218 | struct skl_wrpll_params *wrpll_params) | 2218 | struct skl_wrpll_params *wrpll_params) |
2219 | { | 2219 | { |
2220 | u32 afe_clock = clock * 5; | 2220 | u32 afe_clock = clock * 5; |
2221 | uint32_t ref_clock; | ||
2221 | u32 dco_min = 7998000; | 2222 | u32 dco_min = 7998000; |
2222 | u32 dco_max = 10000000; | 2223 | u32 dco_max = 10000000; |
2223 | u32 dco_mid = (dco_min + dco_max) / 2; | 2224 | u32 dco_mid = (dco_min + dco_max) / 2; |
@@ -2250,8 +2251,17 @@ cnl_ddi_calculate_wrpll(int clock, | |||
2250 | 2251 | ||
2251 | cnl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv); | 2252 | cnl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv); |
2252 | 2253 | ||
2253 | cnl_wrpll_params_populate(wrpll_params, best_dco, | 2254 | ref_clock = dev_priv->cdclk.hw.ref; |
2254 | dev_priv->cdclk.hw.ref, pdiv, qdiv, kdiv); | 2255 | |
2256 | /* | ||
2257 | * For ICL, the spec states: if reference frequency is 38.4, use 19.2 | ||
2258 | * because the DPLL automatically divides that by 2. | ||
2259 | */ | ||
2260 | if (IS_ICELAKE(dev_priv) && ref_clock == 38400) | ||
2261 | ref_clock = 19200; | ||
2262 | |||
2263 | cnl_wrpll_params_populate(wrpll_params, best_dco, ref_clock, pdiv, qdiv, | ||
2264 | kdiv); | ||
2255 | 2265 | ||
2256 | return true; | 2266 | return true; |
2257 | } | 2267 | } |
@@ -2399,6 +2409,644 @@ static const struct intel_dpll_mgr cnl_pll_mgr = { | |||
2399 | .dump_hw_state = cnl_dump_hw_state, | 2409 | .dump_hw_state = cnl_dump_hw_state, |
2400 | }; | 2410 | }; |
2401 | 2411 | ||
2412 | /* | ||
2413 | * These values alrea already adjusted: they're the bits we write to the | ||
2414 | * registers, not the logical values. | ||
2415 | */ | ||
2416 | static const struct skl_wrpll_params icl_dp_combo_pll_24MHz_values[] = { | ||
2417 | { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [0]: 5.4 */ | ||
2418 | .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2419 | { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [1]: 2.7 */ | ||
2420 | .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2421 | { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [2]: 1.62 */ | ||
2422 | .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2423 | { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [3]: 3.24 */ | ||
2424 | .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2425 | { .dco_integer = 0x168, .dco_fraction = 0x0000, /* [4]: 2.16 */ | ||
2426 | .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2}, | ||
2427 | { .dco_integer = 0x168, .dco_fraction = 0x0000, /* [5]: 4.32 */ | ||
2428 | .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2429 | { .dco_integer = 0x195, .dco_fraction = 0x0000, /* [6]: 6.48 */ | ||
2430 | .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2431 | { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [7]: 8.1 */ | ||
2432 | .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2433 | }; | ||
2434 | |||
2435 | /* Also used for 38.4 MHz values. */ | ||
2436 | static const struct skl_wrpll_params icl_dp_combo_pll_19_2MHz_values[] = { | ||
2437 | { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [0]: 5.4 */ | ||
2438 | .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2439 | { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [1]: 2.7 */ | ||
2440 | .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2441 | { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [2]: 1.62 */ | ||
2442 | .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2443 | { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [3]: 3.24 */ | ||
2444 | .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2445 | { .dco_integer = 0x1C2, .dco_fraction = 0x0000, /* [4]: 2.16 */ | ||
2446 | .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2}, | ||
2447 | { .dco_integer = 0x1C2, .dco_fraction = 0x0000, /* [5]: 4.32 */ | ||
2448 | .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2449 | { .dco_integer = 0x1FA, .dco_fraction = 0x2000, /* [6]: 6.48 */ | ||
2450 | .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2451 | { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [7]: 8.1 */ | ||
2452 | .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0}, | ||
2453 | }; | ||
2454 | |||
2455 | static bool icl_calc_dp_combo_pll(struct drm_i915_private *dev_priv, int clock, | ||
2456 | struct skl_wrpll_params *pll_params) | ||
2457 | { | ||
2458 | const struct skl_wrpll_params *params; | ||
2459 | |||
2460 | params = dev_priv->cdclk.hw.ref == 24000 ? | ||
2461 | icl_dp_combo_pll_24MHz_values : | ||
2462 | icl_dp_combo_pll_19_2MHz_values; | ||
2463 | |||
2464 | switch (clock) { | ||
2465 | case 540000: | ||
2466 | *pll_params = params[0]; | ||
2467 | break; | ||
2468 | case 270000: | ||
2469 | *pll_params = params[1]; | ||
2470 | break; | ||
2471 | case 162000: | ||
2472 | *pll_params = params[2]; | ||
2473 | break; | ||
2474 | case 324000: | ||
2475 | *pll_params = params[3]; | ||
2476 | break; | ||
2477 | case 216000: | ||
2478 | *pll_params = params[4]; | ||
2479 | break; | ||
2480 | case 432000: | ||
2481 | *pll_params = params[5]; | ||
2482 | break; | ||
2483 | case 648000: | ||
2484 | *pll_params = params[6]; | ||
2485 | break; | ||
2486 | case 810000: | ||
2487 | *pll_params = params[7]; | ||
2488 | break; | ||
2489 | default: | ||
2490 | MISSING_CASE(clock); | ||
2491 | return false; | ||
2492 | } | ||
2493 | |||
2494 | return true; | ||
2495 | } | ||
2496 | |||
2497 | static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state, | ||
2498 | struct intel_encoder *encoder, int clock, | ||
2499 | struct intel_dpll_hw_state *pll_state) | ||
2500 | { | ||
2501 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
2502 | uint32_t cfgcr0, cfgcr1; | ||
2503 | struct skl_wrpll_params pll_params = { 0 }; | ||
2504 | bool ret; | ||
2505 | |||
2506 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) | ||
2507 | ret = cnl_ddi_calculate_wrpll(clock, dev_priv, &pll_params); | ||
2508 | else | ||
2509 | ret = icl_calc_dp_combo_pll(dev_priv, clock, &pll_params); | ||
2510 | |||
2511 | if (!ret) | ||
2512 | return false; | ||
2513 | |||
2514 | cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(pll_params.dco_fraction) | | ||
2515 | pll_params.dco_integer; | ||
2516 | |||
2517 | cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params.qdiv_ratio) | | ||
2518 | DPLL_CFGCR1_QDIV_MODE(pll_params.qdiv_mode) | | ||
2519 | DPLL_CFGCR1_KDIV(pll_params.kdiv) | | ||
2520 | DPLL_CFGCR1_PDIV(pll_params.pdiv) | | ||
2521 | DPLL_CFGCR1_CENTRAL_FREQ_8400; | ||
2522 | |||
2523 | pll_state->cfgcr0 = cfgcr0; | ||
2524 | pll_state->cfgcr1 = cfgcr1; | ||
2525 | return true; | ||
2526 | } | ||
2527 | |||
2528 | static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id) | ||
2529 | { | ||
2530 | return id - DPLL_ID_ICL_MGPLL1 + PORT_C; | ||
2531 | } | ||
2532 | |||
2533 | static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port) | ||
2534 | { | ||
2535 | return port - PORT_C + DPLL_ID_ICL_MGPLL1; | ||
2536 | } | ||
2537 | |||
2538 | static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, | ||
2539 | uint32_t *target_dco_khz, | ||
2540 | struct intel_dpll_hw_state *state) | ||
2541 | { | ||
2542 | uint32_t dco_min_freq, dco_max_freq; | ||
2543 | int div1_vals[] = {7, 5, 3, 2}; | ||
2544 | unsigned int i; | ||
2545 | int div2; | ||
2546 | |||
2547 | dco_min_freq = is_dp ? 8100000 : use_ssc ? 8000000 : 7992000; | ||
2548 | dco_max_freq = is_dp ? 8100000 : 10000000; | ||
2549 | |||
2550 | for (i = 0; i < ARRAY_SIZE(div1_vals); i++) { | ||
2551 | int div1 = div1_vals[i]; | ||
2552 | |||
2553 | for (div2 = 10; div2 > 0; div2--) { | ||
2554 | int dco = div1 * div2 * clock_khz * 5; | ||
2555 | int a_divratio, tlinedrv, inputsel, hsdiv; | ||
2556 | |||
2557 | if (dco < dco_min_freq || dco > dco_max_freq) | ||
2558 | continue; | ||
2559 | |||
2560 | if (div2 >= 2) { | ||
2561 | a_divratio = is_dp ? 10 : 5; | ||
2562 | tlinedrv = 2; | ||
2563 | } else { | ||
2564 | a_divratio = 5; | ||
2565 | tlinedrv = 0; | ||
2566 | } | ||
2567 | inputsel = is_dp ? 0 : 1; | ||
2568 | |||
2569 | switch (div1) { | ||
2570 | default: | ||
2571 | MISSING_CASE(div1); | ||
2572 | case 2: | ||
2573 | hsdiv = 0; | ||
2574 | break; | ||
2575 | case 3: | ||
2576 | hsdiv = 1; | ||
2577 | break; | ||
2578 | case 5: | ||
2579 | hsdiv = 2; | ||
2580 | break; | ||
2581 | case 7: | ||
2582 | hsdiv = 3; | ||
2583 | break; | ||
2584 | } | ||
2585 | |||
2586 | *target_dco_khz = dco; | ||
2587 | |||
2588 | state->mg_refclkin_ctl = MG_REFCLKIN_CTL_OD_2_MUX(1); | ||
2589 | |||
2590 | state->mg_clktop2_coreclkctl1 = | ||
2591 | MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(a_divratio); | ||
2592 | |||
2593 | state->mg_clktop2_hsclkctl = | ||
2594 | MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(tlinedrv) | | ||
2595 | MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(inputsel) | | ||
2596 | MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO(hsdiv) | | ||
2597 | MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(div2); | ||
2598 | |||
2599 | return true; | ||
2600 | } | ||
2601 | } | ||
2602 | |||
2603 | return false; | ||
2604 | } | ||
2605 | |||
2606 | /* | ||
2607 | * The specification for this function uses real numbers, so the math had to be | ||
2608 | * adapted to integer-only calculation, that's why it looks so different. | ||
2609 | */ | ||
2610 | static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, | ||
2611 | struct intel_encoder *encoder, int clock, | ||
2612 | struct intel_dpll_hw_state *pll_state) | ||
2613 | { | ||
2614 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
2615 | int refclk_khz = dev_priv->cdclk.hw.ref; | ||
2616 | uint32_t dco_khz, m1div, m2div_int, m2div_rem, m2div_frac; | ||
2617 | uint32_t iref_ndiv, iref_trim, iref_pulse_w; | ||
2618 | uint32_t prop_coeff, int_coeff; | ||
2619 | uint32_t tdc_targetcnt, feedfwgain; | ||
2620 | uint64_t ssc_stepsize, ssc_steplen, ssc_steplog; | ||
2621 | uint64_t tmp; | ||
2622 | bool use_ssc = false; | ||
2623 | bool is_dp = !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI); | ||
2624 | |||
2625 | if (!icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz, | ||
2626 | pll_state)) { | ||
2627 | DRM_DEBUG_KMS("Failed to find divisors for clock %d\n", clock); | ||
2628 | return false; | ||
2629 | } | ||
2630 | |||
2631 | m1div = 2; | ||
2632 | m2div_int = dco_khz / (refclk_khz * m1div); | ||
2633 | if (m2div_int > 255) { | ||
2634 | m1div = 4; | ||
2635 | m2div_int = dco_khz / (refclk_khz * m1div); | ||
2636 | if (m2div_int > 255) { | ||
2637 | DRM_DEBUG_KMS("Failed to find mdiv for clock %d\n", | ||
2638 | clock); | ||
2639 | return false; | ||
2640 | } | ||
2641 | } | ||
2642 | m2div_rem = dco_khz % (refclk_khz * m1div); | ||
2643 | |||
2644 | tmp = (uint64_t)m2div_rem * (1 << 22); | ||
2645 | do_div(tmp, refclk_khz * m1div); | ||
2646 | m2div_frac = tmp; | ||
2647 | |||
2648 | switch (refclk_khz) { | ||
2649 | case 19200: | ||
2650 | iref_ndiv = 1; | ||
2651 | iref_trim = 28; | ||
2652 | iref_pulse_w = 1; | ||
2653 | break; | ||
2654 | case 24000: | ||
2655 | iref_ndiv = 1; | ||
2656 | iref_trim = 25; | ||
2657 | iref_pulse_w = 2; | ||
2658 | break; | ||
2659 | case 38400: | ||
2660 | iref_ndiv = 2; | ||
2661 | iref_trim = 28; | ||
2662 | iref_pulse_w = 1; | ||
2663 | break; | ||
2664 | default: | ||
2665 | MISSING_CASE(refclk_khz); | ||
2666 | return false; | ||
2667 | } | ||
2668 | |||
2669 | /* | ||
2670 | * tdc_res = 0.000003 | ||
2671 | * tdc_targetcnt = int(2 / (tdc_res * 8 * 50 * 1.1) / refclk_mhz + 0.5) | ||
2672 | * | ||
2673 | * The multiplication by 1000 is due to refclk MHz to KHz conversion. It | ||
2674 | * was supposed to be a division, but we rearranged the operations of | ||
2675 | * the formula to avoid early divisions so we don't multiply the | ||
2676 | * rounding errors. | ||
2677 | * | ||
2678 | * 0.000003 * 8 * 50 * 1.1 = 0.00132, also known as 132 / 100000, which | ||
2679 | * we also rearrange to work with integers. | ||
2680 | * | ||
2681 | * The 0.5 transformed to 5 results in a multiplication by 10 and the | ||
2682 | * last division by 10. | ||
2683 | */ | ||
2684 | tdc_targetcnt = (2 * 1000 * 100000 * 10 / (132 * refclk_khz) + 5) / 10; | ||
2685 | |||
2686 | /* | ||
2687 | * Here we divide dco_khz by 10 in order to allow the dividend to fit in | ||
2688 | * 32 bits. That's not a problem since we round the division down | ||
2689 | * anyway. | ||
2690 | */ | ||
2691 | feedfwgain = (use_ssc || m2div_rem > 0) ? | ||
2692 | m1div * 1000000 * 100 / (dco_khz * 3 / 10) : 0; | ||
2693 | |||
2694 | if (dco_khz >= 9000000) { | ||
2695 | prop_coeff = 5; | ||
2696 | int_coeff = 10; | ||
2697 | } else { | ||
2698 | prop_coeff = 4; | ||
2699 | int_coeff = 8; | ||
2700 | } | ||
2701 | |||
2702 | if (use_ssc) { | ||
2703 | tmp = (uint64_t)dco_khz * 47 * 32; | ||
2704 | do_div(tmp, refclk_khz * m1div * 10000); | ||
2705 | ssc_stepsize = tmp; | ||
2706 | |||
2707 | tmp = (uint64_t)dco_khz * 1000; | ||
2708 | ssc_steplen = DIV_ROUND_UP_ULL(tmp, 32 * 2 * 32); | ||
2709 | } else { | ||
2710 | ssc_stepsize = 0; | ||
2711 | ssc_steplen = 0; | ||
2712 | } | ||
2713 | ssc_steplog = 4; | ||
2714 | |||
2715 | pll_state->mg_pll_div0 = (m2div_rem > 0 ? MG_PLL_DIV0_FRACNEN_H : 0) | | ||
2716 | MG_PLL_DIV0_FBDIV_FRAC(m2div_frac) | | ||
2717 | MG_PLL_DIV0_FBDIV_INT(m2div_int); | ||
2718 | |||
2719 | pll_state->mg_pll_div1 = MG_PLL_DIV1_IREF_NDIVRATIO(iref_ndiv) | | ||
2720 | MG_PLL_DIV1_DITHER_DIV_2 | | ||
2721 | MG_PLL_DIV1_NDIVRATIO(1) | | ||
2722 | MG_PLL_DIV1_FBPREDIV(m1div); | ||
2723 | |||
2724 | pll_state->mg_pll_lf = MG_PLL_LF_TDCTARGETCNT(tdc_targetcnt) | | ||
2725 | MG_PLL_LF_AFCCNTSEL_512 | | ||
2726 | MG_PLL_LF_GAINCTRL(1) | | ||
2727 | MG_PLL_LF_INT_COEFF(int_coeff) | | ||
2728 | MG_PLL_LF_PROP_COEFF(prop_coeff); | ||
2729 | |||
2730 | pll_state->mg_pll_frac_lock = MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 | | ||
2731 | MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 | | ||
2732 | MG_PLL_FRAC_LOCK_LOCKTHRESH(10) | | ||
2733 | MG_PLL_FRAC_LOCK_DCODITHEREN | | ||
2734 | MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(feedfwgain); | ||
2735 | if (use_ssc || m2div_rem > 0) | ||
2736 | pll_state->mg_pll_frac_lock |= MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN; | ||
2737 | |||
2738 | pll_state->mg_pll_ssc = (use_ssc ? MG_PLL_SSC_EN : 0) | | ||
2739 | MG_PLL_SSC_TYPE(2) | | ||
2740 | MG_PLL_SSC_STEPLENGTH(ssc_steplen) | | ||
2741 | MG_PLL_SSC_STEPNUM(ssc_steplog) | | ||
2742 | MG_PLL_SSC_FLLEN | | ||
2743 | MG_PLL_SSC_STEPSIZE(ssc_stepsize); | ||
2744 | |||
2745 | pll_state->mg_pll_tdc_coldst_bias = MG_PLL_TDC_COLDST_COLDSTART; | ||
2746 | |||
2747 | if (refclk_khz != 38400) { | ||
2748 | pll_state->mg_pll_tdc_coldst_bias |= | ||
2749 | MG_PLL_TDC_COLDST_IREFINT_EN | | ||
2750 | MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(iref_pulse_w) | | ||
2751 | MG_PLL_TDC_COLDST_COLDSTART | | ||
2752 | MG_PLL_TDC_TDCOVCCORR_EN | | ||
2753 | MG_PLL_TDC_TDCSEL(3); | ||
2754 | |||
2755 | pll_state->mg_pll_bias = MG_PLL_BIAS_BIAS_GB_SEL(3) | | ||
2756 | MG_PLL_BIAS_INIT_DCOAMP(0x3F) | | ||
2757 | MG_PLL_BIAS_BIAS_BONUS(10) | | ||
2758 | MG_PLL_BIAS_BIASCAL_EN | | ||
2759 | MG_PLL_BIAS_CTRIM(12) | | ||
2760 | MG_PLL_BIAS_VREF_RDAC(4) | | ||
2761 | MG_PLL_BIAS_IREFTRIM(iref_trim); | ||
2762 | } | ||
2763 | |||
2764 | return true; | ||
2765 | } | ||
2766 | |||
2767 | static struct intel_shared_dpll * | ||
2768 | icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, | ||
2769 | struct intel_encoder *encoder) | ||
2770 | { | ||
2771 | struct intel_shared_dpll *pll; | ||
2772 | struct intel_dpll_hw_state pll_state = {}; | ||
2773 | enum port port = encoder->port; | ||
2774 | enum intel_dpll_id min, max; | ||
2775 | int clock = crtc_state->port_clock; | ||
2776 | bool ret; | ||
2777 | |||
2778 | switch (port) { | ||
2779 | case PORT_A: | ||
2780 | case PORT_B: | ||
2781 | min = DPLL_ID_ICL_DPLL0; | ||
2782 | max = DPLL_ID_ICL_DPLL1; | ||
2783 | ret = icl_calc_dpll_state(crtc_state, encoder, clock, | ||
2784 | &pll_state); | ||
2785 | break; | ||
2786 | case PORT_C: | ||
2787 | case PORT_D: | ||
2788 | case PORT_E: | ||
2789 | case PORT_F: | ||
2790 | min = icl_port_to_mg_pll_id(port); | ||
2791 | max = min; | ||
2792 | ret = icl_calc_mg_pll_state(crtc_state, encoder, clock, | ||
2793 | &pll_state); | ||
2794 | break; | ||
2795 | default: | ||
2796 | MISSING_CASE(port); | ||
2797 | return NULL; | ||
2798 | } | ||
2799 | |||
2800 | if (!ret) { | ||
2801 | DRM_DEBUG_KMS("Could not calculate PLL state.\n"); | ||
2802 | return NULL; | ||
2803 | } | ||
2804 | |||
2805 | crtc_state->dpll_hw_state = pll_state; | ||
2806 | |||
2807 | pll = intel_find_shared_dpll(crtc, crtc_state, min, max); | ||
2808 | if (!pll) { | ||
2809 | DRM_DEBUG_KMS("No PLL selected\n"); | ||
2810 | return NULL; | ||
2811 | } | ||
2812 | |||
2813 | intel_reference_shared_dpll(pll, crtc_state); | ||
2814 | |||
2815 | return pll; | ||
2816 | } | ||
2817 | |||
2818 | static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id) | ||
2819 | { | ||
2820 | switch (id) { | ||
2821 | default: | ||
2822 | MISSING_CASE(id); | ||
2823 | case DPLL_ID_ICL_DPLL0: | ||
2824 | case DPLL_ID_ICL_DPLL1: | ||
2825 | return CNL_DPLL_ENABLE(id); | ||
2826 | case DPLL_ID_ICL_MGPLL1: | ||
2827 | case DPLL_ID_ICL_MGPLL2: | ||
2828 | case DPLL_ID_ICL_MGPLL3: | ||
2829 | case DPLL_ID_ICL_MGPLL4: | ||
2830 | return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id)); | ||
2831 | } | ||
2832 | } | ||
2833 | |||
2834 | static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv, | ||
2835 | struct intel_shared_dpll *pll, | ||
2836 | struct intel_dpll_hw_state *hw_state) | ||
2837 | { | ||
2838 | const enum intel_dpll_id id = pll->info->id; | ||
2839 | uint32_t val; | ||
2840 | enum port port; | ||
2841 | bool ret = false; | ||
2842 | |||
2843 | if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) | ||
2844 | return false; | ||
2845 | |||
2846 | val = I915_READ(icl_pll_id_to_enable_reg(id)); | ||
2847 | if (!(val & PLL_ENABLE)) | ||
2848 | goto out; | ||
2849 | |||
2850 | switch (id) { | ||
2851 | case DPLL_ID_ICL_DPLL0: | ||
2852 | case DPLL_ID_ICL_DPLL1: | ||
2853 | hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id)); | ||
2854 | hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id)); | ||
2855 | break; | ||
2856 | case DPLL_ID_ICL_MGPLL1: | ||
2857 | case DPLL_ID_ICL_MGPLL2: | ||
2858 | case DPLL_ID_ICL_MGPLL3: | ||
2859 | case DPLL_ID_ICL_MGPLL4: | ||
2860 | port = icl_mg_pll_id_to_port(id); | ||
2861 | hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port)); | ||
2862 | hw_state->mg_clktop2_coreclkctl1 = | ||
2863 | I915_READ(MG_CLKTOP2_CORECLKCTL1(port)); | ||
2864 | hw_state->mg_clktop2_hsclkctl = | ||
2865 | I915_READ(MG_CLKTOP2_HSCLKCTL(port)); | ||
2866 | hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port)); | ||
2867 | hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port)); | ||
2868 | hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port)); | ||
2869 | hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port)); | ||
2870 | hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port)); | ||
2871 | hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port)); | ||
2872 | hw_state->mg_pll_tdc_coldst_bias = | ||
2873 | I915_READ(MG_PLL_TDC_COLDST_BIAS(port)); | ||
2874 | break; | ||
2875 | default: | ||
2876 | MISSING_CASE(id); | ||
2877 | } | ||
2878 | |||
2879 | ret = true; | ||
2880 | out: | ||
2881 | intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); | ||
2882 | return ret; | ||
2883 | } | ||
2884 | |||
2885 | static void icl_dpll_write(struct drm_i915_private *dev_priv, | ||
2886 | struct intel_shared_dpll *pll) | ||
2887 | { | ||
2888 | struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; | ||
2889 | const enum intel_dpll_id id = pll->info->id; | ||
2890 | |||
2891 | I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0); | ||
2892 | I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1); | ||
2893 | POSTING_READ(ICL_DPLL_CFGCR1(id)); | ||
2894 | } | ||
2895 | |||
2896 | static void icl_mg_pll_write(struct drm_i915_private *dev_priv, | ||
2897 | struct intel_shared_dpll *pll) | ||
2898 | { | ||
2899 | struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; | ||
2900 | enum port port = icl_mg_pll_id_to_port(pll->info->id); | ||
2901 | |||
2902 | I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl); | ||
2903 | I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port), | ||
2904 | hw_state->mg_clktop2_coreclkctl1); | ||
2905 | I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl); | ||
2906 | I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0); | ||
2907 | I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1); | ||
2908 | I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf); | ||
2909 | I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock); | ||
2910 | I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc); | ||
2911 | I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias); | ||
2912 | I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port), | ||
2913 | hw_state->mg_pll_tdc_coldst_bias); | ||
2914 | POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port)); | ||
2915 | } | ||
2916 | |||
2917 | static void icl_pll_enable(struct drm_i915_private *dev_priv, | ||
2918 | struct intel_shared_dpll *pll) | ||
2919 | { | ||
2920 | const enum intel_dpll_id id = pll->info->id; | ||
2921 | i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id); | ||
2922 | uint32_t val; | ||
2923 | |||
2924 | val = I915_READ(enable_reg); | ||
2925 | val |= PLL_POWER_ENABLE; | ||
2926 | I915_WRITE(enable_reg, val); | ||
2927 | |||
2928 | /* | ||
2929 | * The spec says we need to "wait" but it also says it should be | ||
2930 | * immediate. | ||
2931 | */ | ||
2932 | if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, | ||
2933 | PLL_POWER_STATE, 1)) | ||
2934 | DRM_ERROR("PLL %d Power not enabled\n", id); | ||
2935 | |||
2936 | switch (id) { | ||
2937 | case DPLL_ID_ICL_DPLL0: | ||
2938 | case DPLL_ID_ICL_DPLL1: | ||
2939 | icl_dpll_write(dev_priv, pll); | ||
2940 | break; | ||
2941 | case DPLL_ID_ICL_MGPLL1: | ||
2942 | case DPLL_ID_ICL_MGPLL2: | ||
2943 | case DPLL_ID_ICL_MGPLL3: | ||
2944 | case DPLL_ID_ICL_MGPLL4: | ||
2945 | icl_mg_pll_write(dev_priv, pll); | ||
2946 | break; | ||
2947 | default: | ||
2948 | MISSING_CASE(id); | ||
2949 | } | ||
2950 | |||
2951 | /* | ||
2952 | * DVFS pre sequence would be here, but in our driver the cdclk code | ||
2953 | * paths should already be setting the appropriate voltage, hence we do | ||
2954 | * nothign here. | ||
2955 | */ | ||
2956 | |||
2957 | val = I915_READ(enable_reg); | ||
2958 | val |= PLL_ENABLE; | ||
2959 | I915_WRITE(enable_reg, val); | ||
2960 | |||
2961 | if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK, | ||
2962 | 1)) /* 600us actually. */ | ||
2963 | DRM_ERROR("PLL %d not locked\n", id); | ||
2964 | |||
2965 | /* DVFS post sequence would be here. See the comment above. */ | ||
2966 | } | ||
2967 | |||
2968 | static void icl_pll_disable(struct drm_i915_private *dev_priv, | ||
2969 | struct intel_shared_dpll *pll) | ||
2970 | { | ||
2971 | const enum intel_dpll_id id = pll->info->id; | ||
2972 | i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id); | ||
2973 | uint32_t val; | ||
2974 | |||
2975 | /* The first steps are done by intel_ddi_post_disable(). */ | ||
2976 | |||
2977 | /* | ||
2978 | * DVFS pre sequence would be here, but in our driver the cdclk code | ||
2979 | * paths should already be setting the appropriate voltage, hence we do | ||
2980 | * nothign here. | ||
2981 | */ | ||
2982 | |||
2983 | val = I915_READ(enable_reg); | ||
2984 | val &= ~PLL_ENABLE; | ||
2985 | I915_WRITE(enable_reg, val); | ||
2986 | |||
2987 | /* Timeout is actually 1us. */ | ||
2988 | if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1)) | ||
2989 | DRM_ERROR("PLL %d locked\n", id); | ||
2990 | |||
2991 | /* DVFS post sequence would be here. See the comment above. */ | ||
2992 | |||
2993 | val = I915_READ(enable_reg); | ||
2994 | val &= ~PLL_POWER_ENABLE; | ||
2995 | I915_WRITE(enable_reg, val); | ||
2996 | |||
2997 | /* | ||
2998 | * The spec says we need to "wait" but it also says it should be | ||
2999 | * immediate. | ||
3000 | */ | ||
3001 | if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0, | ||
3002 | 1)) | ||
3003 | DRM_ERROR("PLL %d Power not disabled\n", id); | ||
3004 | } | ||
3005 | |||
3006 | static void icl_dump_hw_state(struct drm_i915_private *dev_priv, | ||
3007 | struct intel_dpll_hw_state *hw_state) | ||
3008 | { | ||
3009 | DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, " | ||
3010 | "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, " | ||
3011 | "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, " | ||
3012 | "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, " | ||
3013 | "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, " | ||
3014 | "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n", | ||
3015 | hw_state->cfgcr0, hw_state->cfgcr1, | ||
3016 | hw_state->mg_refclkin_ctl, | ||
3017 | hw_state->mg_clktop2_coreclkctl1, | ||
3018 | hw_state->mg_clktop2_hsclkctl, | ||
3019 | hw_state->mg_pll_div0, | ||
3020 | hw_state->mg_pll_div1, | ||
3021 | hw_state->mg_pll_lf, | ||
3022 | hw_state->mg_pll_frac_lock, | ||
3023 | hw_state->mg_pll_ssc, | ||
3024 | hw_state->mg_pll_bias, | ||
3025 | hw_state->mg_pll_tdc_coldst_bias); | ||
3026 | } | ||
3027 | |||
3028 | static const struct intel_shared_dpll_funcs icl_pll_funcs = { | ||
3029 | .enable = icl_pll_enable, | ||
3030 | .disable = icl_pll_disable, | ||
3031 | .get_hw_state = icl_pll_get_hw_state, | ||
3032 | }; | ||
3033 | |||
3034 | static const struct dpll_info icl_plls[] = { | ||
3035 | { "DPLL 0", &icl_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, | ||
3036 | { "DPLL 1", &icl_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, | ||
3037 | { "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 }, | ||
3038 | { "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 }, | ||
3039 | { "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 }, | ||
3040 | { "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 }, | ||
3041 | { }, | ||
3042 | }; | ||
3043 | |||
3044 | static const struct intel_dpll_mgr icl_pll_mgr = { | ||
3045 | .dpll_info = icl_plls, | ||
3046 | .get_dpll = icl_get_dpll, | ||
3047 | .dump_hw_state = icl_dump_hw_state, | ||
3048 | }; | ||
3049 | |||
2402 | /** | 3050 | /** |
2403 | * intel_shared_dpll_init - Initialize shared DPLLs | 3051 | * intel_shared_dpll_init - Initialize shared DPLLs |
2404 | * @dev: drm device | 3052 | * @dev: drm device |
@@ -2412,7 +3060,9 @@ void intel_shared_dpll_init(struct drm_device *dev) | |||
2412 | const struct dpll_info *dpll_info; | 3060 | const struct dpll_info *dpll_info; |
2413 | int i; | 3061 | int i; |
2414 | 3062 | ||
2415 | if (IS_CANNONLAKE(dev_priv)) | 3063 | if (IS_ICELAKE(dev_priv)) |
3064 | dpll_mgr = &icl_pll_mgr; | ||
3065 | else if (IS_CANNONLAKE(dev_priv)) | ||
2416 | dpll_mgr = &cnl_pll_mgr; | 3066 | dpll_mgr = &cnl_pll_mgr; |
2417 | else if (IS_GEN9_BC(dev_priv)) | 3067 | else if (IS_GEN9_BC(dev_priv)) |
2418 | dpll_mgr = &skl_pll_mgr; | 3068 | dpll_mgr = &skl_pll_mgr; |
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 4febfaa90bde..7a0cd564a9ee 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h | |||
@@ -103,6 +103,32 @@ enum intel_dpll_id { | |||
103 | * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3 | 103 | * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3 |
104 | */ | 104 | */ |
105 | DPLL_ID_SKL_DPLL3 = 3, | 105 | DPLL_ID_SKL_DPLL3 = 3, |
106 | |||
107 | |||
108 | /** | ||
109 | * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0 | ||
110 | */ | ||
111 | DPLL_ID_ICL_DPLL0 = 0, | ||
112 | /** | ||
113 | * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1 | ||
114 | */ | ||
115 | DPLL_ID_ICL_DPLL1 = 1, | ||
116 | /** | ||
117 | * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C) | ||
118 | */ | ||
119 | DPLL_ID_ICL_MGPLL1 = 2, | ||
120 | /** | ||
121 | * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D) | ||
122 | */ | ||
123 | DPLL_ID_ICL_MGPLL2 = 3, | ||
124 | /** | ||
125 | * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E) | ||
126 | */ | ||
127 | DPLL_ID_ICL_MGPLL3 = 4, | ||
128 | /** | ||
129 | * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F) | ||
130 | */ | ||
131 | DPLL_ID_ICL_MGPLL4 = 5, | ||
106 | }; | 132 | }; |
107 | #define I915_NUM_PLLS 6 | 133 | #define I915_NUM_PLLS 6 |
108 | 134 | ||
@@ -135,6 +161,21 @@ struct intel_dpll_hw_state { | |||
135 | /* bxt */ | 161 | /* bxt */ |
136 | uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, | 162 | uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, |
137 | pcsdw12; | 163 | pcsdw12; |
164 | |||
165 | /* | ||
166 | * ICL uses the following, already defined: | ||
167 | * uint32_t cfgcr0, cfgcr1; | ||
168 | */ | ||
169 | uint32_t mg_refclkin_ctl; | ||
170 | uint32_t mg_clktop2_coreclkctl1; | ||
171 | uint32_t mg_clktop2_hsclkctl; | ||
172 | uint32_t mg_pll_div0; | ||
173 | uint32_t mg_pll_div1; | ||
174 | uint32_t mg_pll_lf; | ||
175 | uint32_t mg_pll_frac_lock; | ||
176 | uint32_t mg_pll_ssc; | ||
177 | uint32_t mg_pll_bias; | ||
178 | uint32_t mg_pll_tdc_coldst_bias; | ||
138 | }; | 179 | }; |
139 | 180 | ||
140 | /** | 181 | /** |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6bd7bff0947a..d7dbca1aabff 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -56,6 +56,8 @@ | |||
56 | for (;;) { \ | 56 | for (;;) { \ |
57 | const bool expired__ = ktime_after(ktime_get_raw(), end__); \ | 57 | const bool expired__ = ktime_after(ktime_get_raw(), end__); \ |
58 | OP; \ | 58 | OP; \ |
59 | /* Guarantee COND check prior to timeout */ \ | ||
60 | barrier(); \ | ||
59 | if (COND) { \ | 61 | if (COND) { \ |
60 | ret__ = 0; \ | 62 | ret__ = 0; \ |
61 | break; \ | 63 | break; \ |
@@ -96,6 +98,8 @@ | |||
96 | u64 now = local_clock(); \ | 98 | u64 now = local_clock(); \ |
97 | if (!(ATOMIC)) \ | 99 | if (!(ATOMIC)) \ |
98 | preempt_enable(); \ | 100 | preempt_enable(); \ |
101 | /* Guarantee COND check prior to timeout */ \ | ||
102 | barrier(); \ | ||
99 | if (COND) { \ | 103 | if (COND) { \ |
100 | ret = 0; \ | 104 | ret = 0; \ |
101 | break; \ | 105 | break; \ |
@@ -140,6 +144,10 @@ | |||
140 | #define KHz(x) (1000 * (x)) | 144 | #define KHz(x) (1000 * (x)) |
141 | #define MHz(x) KHz(1000 * (x)) | 145 | #define MHz(x) KHz(1000 * (x)) |
142 | 146 | ||
147 | #define KBps(x) (1000 * (x)) | ||
148 | #define MBps(x) KBps(1000 * (x)) | ||
149 | #define GBps(x) ((u64)1000 * MBps((x))) | ||
150 | |||
143 | /* | 151 | /* |
144 | * Display related stuff | 152 | * Display related stuff |
145 | */ | 153 | */ |
@@ -882,6 +890,7 @@ struct intel_crtc_state { | |||
882 | 890 | ||
883 | /* bitmask of visible planes (enum plane_id) */ | 891 | /* bitmask of visible planes (enum plane_id) */ |
884 | u8 active_planes; | 892 | u8 active_planes; |
893 | u8 nv12_planes; | ||
885 | 894 | ||
886 | /* HDMI scrambling status */ | 895 | /* HDMI scrambling status */ |
887 | bool hdmi_scrambling; | 896 | bool hdmi_scrambling; |
@@ -1329,6 +1338,9 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv); | |||
1329 | void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); | 1338 | void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); |
1330 | 1339 | ||
1331 | /* i915_irq.c */ | 1340 | /* i915_irq.c */ |
1341 | bool gen11_reset_one_iir(struct drm_i915_private * const i915, | ||
1342 | const unsigned int bank, | ||
1343 | const unsigned int bit); | ||
1332 | void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); | 1344 | void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); |
1333 | void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); | 1345 | void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); |
1334 | void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); | 1346 | void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); |
@@ -1398,6 +1410,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp); | |||
1398 | u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); | 1410 | u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); |
1399 | int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, | 1411 | int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, |
1400 | bool enable); | 1412 | bool enable); |
1413 | void icl_map_plls_to_ports(struct drm_crtc *crtc, | ||
1414 | struct intel_crtc_state *crtc_state, | ||
1415 | struct drm_atomic_state *old_state); | ||
1416 | void icl_unmap_plls_to_ports(struct drm_crtc *crtc, | ||
1417 | struct intel_crtc_state *crtc_state, | ||
1418 | struct drm_atomic_state *old_state); | ||
1401 | 1419 | ||
1402 | unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, | 1420 | unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, |
1403 | int plane, unsigned int height); | 1421 | int plane, unsigned int height); |
@@ -1580,8 +1598,6 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv); | |||
1580 | void bxt_disable_dc9(struct drm_i915_private *dev_priv); | 1598 | void bxt_disable_dc9(struct drm_i915_private *dev_priv); |
1581 | void gen9_enable_dc5(struct drm_i915_private *dev_priv); | 1599 | void gen9_enable_dc5(struct drm_i915_private *dev_priv); |
1582 | unsigned int skl_cdclk_get_vco(unsigned int freq); | 1600 | unsigned int skl_cdclk_get_vco(unsigned int freq); |
1583 | void skl_enable_dc6(struct drm_i915_private *dev_priv); | ||
1584 | void skl_disable_dc6(struct drm_i915_private *dev_priv); | ||
1585 | void intel_dp_get_m_n(struct intel_crtc *crtc, | 1601 | void intel_dp_get_m_n(struct intel_crtc *crtc, |
1586 | struct intel_crtc_state *pipe_config); | 1602 | struct intel_crtc_state *pipe_config); |
1587 | void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); | 1603 | void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); |
@@ -1901,6 +1917,8 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, | |||
1901 | unsigned frontbuffer_bits); | 1917 | unsigned frontbuffer_bits); |
1902 | void intel_psr_compute_config(struct intel_dp *intel_dp, | 1918 | void intel_psr_compute_config(struct intel_dp *intel_dp, |
1903 | struct intel_crtc_state *crtc_state); | 1919 | struct intel_crtc_state *crtc_state); |
1920 | void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug); | ||
1921 | void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir); | ||
1904 | 1922 | ||
1905 | /* intel_runtime_pm.c */ | 1923 | /* intel_runtime_pm.c */ |
1906 | int intel_power_domains_init(struct drm_i915_private *); | 1924 | int intel_power_domains_init(struct drm_i915_private *); |
@@ -1924,6 +1942,8 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, | |||
1924 | enum intel_display_power_domain domain); | 1942 | enum intel_display_power_domain domain); |
1925 | void intel_display_power_put(struct drm_i915_private *dev_priv, | 1943 | void intel_display_power_put(struct drm_i915_private *dev_priv, |
1926 | enum intel_display_power_domain domain); | 1944 | enum intel_display_power_domain domain); |
1945 | void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, | ||
1946 | u8 req_slices); | ||
1927 | 1947 | ||
1928 | static inline void | 1948 | static inline void |
1929 | assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv) | 1949 | assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv) |
@@ -2062,6 +2082,8 @@ bool skl_plane_get_hw_state(struct intel_plane *plane); | |||
2062 | bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, | 2082 | bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, |
2063 | enum pipe pipe, enum plane_id plane_id); | 2083 | enum pipe pipe, enum plane_id plane_id); |
2064 | bool intel_format_is_yuv(uint32_t format); | 2084 | bool intel_format_is_yuv(uint32_t format); |
2085 | bool skl_plane_has_planar(struct drm_i915_private *dev_priv, | ||
2086 | enum pipe pipe, enum plane_id plane_id); | ||
2065 | 2087 | ||
2066 | /* intel_tv.c */ | 2088 | /* intel_tv.c */ |
2067 | void intel_tv_init(struct drm_i915_private *dev_priv); | 2089 | void intel_tv_init(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/intel_dsi_vbt.c b/drivers/gpu/drm/i915/intel_dsi_vbt.c index 91c07b0c8db9..4d6ffa7b3e7b 100644 --- a/drivers/gpu/drm/i915/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_vbt.c | |||
@@ -647,6 +647,11 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) | |||
647 | /* prepare count */ | 647 | /* prepare count */ |
648 | prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul); | 648 | prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul); |
649 | 649 | ||
650 | if (prepare_cnt > PREPARE_CNT_MAX) { | ||
651 | DRM_DEBUG_KMS("prepare count too high %u\n", prepare_cnt); | ||
652 | prepare_cnt = PREPARE_CNT_MAX; | ||
653 | } | ||
654 | |||
650 | /* exit zero count */ | 655 | /* exit zero count */ |
651 | exit_zero_cnt = DIV_ROUND_UP( | 656 | exit_zero_cnt = DIV_ROUND_UP( |
652 | (ths_prepare_hszero - ths_prepare_ns) * ui_den, | 657 | (ths_prepare_hszero - ths_prepare_ns) * ui_den, |
@@ -662,32 +667,29 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) | |||
662 | if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num) | 667 | if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num) |
663 | exit_zero_cnt += 1; | 668 | exit_zero_cnt += 1; |
664 | 669 | ||
670 | if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) { | ||
671 | DRM_DEBUG_KMS("exit zero count too high %u\n", exit_zero_cnt); | ||
672 | exit_zero_cnt = EXIT_ZERO_CNT_MAX; | ||
673 | } | ||
674 | |||
665 | /* clk zero count */ | 675 | /* clk zero count */ |
666 | clk_zero_cnt = DIV_ROUND_UP( | 676 | clk_zero_cnt = DIV_ROUND_UP( |
667 | (tclk_prepare_clkzero - ths_prepare_ns) | 677 | (tclk_prepare_clkzero - ths_prepare_ns) |
668 | * ui_den, ui_num * mul); | 678 | * ui_den, ui_num * mul); |
669 | 679 | ||
680 | if (clk_zero_cnt > CLK_ZERO_CNT_MAX) { | ||
681 | DRM_DEBUG_KMS("clock zero count too high %u\n", clk_zero_cnt); | ||
682 | clk_zero_cnt = CLK_ZERO_CNT_MAX; | ||
683 | } | ||
684 | |||
670 | /* trail count */ | 685 | /* trail count */ |
671 | tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail); | 686 | tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail); |
672 | trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul); | 687 | trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul); |
673 | 688 | ||
674 | if (prepare_cnt > PREPARE_CNT_MAX || | 689 | if (trail_cnt > TRAIL_CNT_MAX) { |
675 | exit_zero_cnt > EXIT_ZERO_CNT_MAX || | 690 | DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt); |
676 | clk_zero_cnt > CLK_ZERO_CNT_MAX || | ||
677 | trail_cnt > TRAIL_CNT_MAX) | ||
678 | DRM_DEBUG_DRIVER("Values crossing maximum limits, restricting to max values\n"); | ||
679 | |||
680 | if (prepare_cnt > PREPARE_CNT_MAX) | ||
681 | prepare_cnt = PREPARE_CNT_MAX; | ||
682 | |||
683 | if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) | ||
684 | exit_zero_cnt = EXIT_ZERO_CNT_MAX; | ||
685 | |||
686 | if (clk_zero_cnt > CLK_ZERO_CNT_MAX) | ||
687 | clk_zero_cnt = CLK_ZERO_CNT_MAX; | ||
688 | |||
689 | if (trail_cnt > TRAIL_CNT_MAX) | ||
690 | trail_cnt = TRAIL_CNT_MAX; | 691 | trail_cnt = TRAIL_CNT_MAX; |
692 | } | ||
691 | 693 | ||
692 | /* B080 */ | 694 | /* B080 */ |
693 | intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 | | 695 | intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 | |
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 1a8370779bbb..6bfd7e3ed152 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
@@ -306,7 +306,7 @@ intel_engine_setup(struct drm_i915_private *dev_priv, | |||
306 | /* Nothing to do here, execute in order of dependencies */ | 306 | /* Nothing to do here, execute in order of dependencies */ |
307 | engine->schedule = NULL; | 307 | engine->schedule = NULL; |
308 | 308 | ||
309 | spin_lock_init(&engine->stats.lock); | 309 | seqlock_init(&engine->stats.lock); |
310 | 310 | ||
311 | ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); | 311 | ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); |
312 | 312 | ||
@@ -451,11 +451,6 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) | |||
451 | GEM_BUG_ON(intel_engine_get_seqno(engine) != seqno); | 451 | GEM_BUG_ON(intel_engine_get_seqno(engine) != seqno); |
452 | } | 452 | } |
453 | 453 | ||
454 | static void intel_engine_init_timeline(struct intel_engine_cs *engine) | ||
455 | { | ||
456 | engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; | ||
457 | } | ||
458 | |||
459 | static void intel_engine_init_batch_pool(struct intel_engine_cs *engine) | 454 | static void intel_engine_init_batch_pool(struct intel_engine_cs *engine) |
460 | { | 455 | { |
461 | i915_gem_batch_pool_init(&engine->batch_pool, engine); | 456 | i915_gem_batch_pool_init(&engine->batch_pool, engine); |
@@ -463,21 +458,10 @@ static void intel_engine_init_batch_pool(struct intel_engine_cs *engine) | |||
463 | 458 | ||
464 | static bool csb_force_mmio(struct drm_i915_private *i915) | 459 | static bool csb_force_mmio(struct drm_i915_private *i915) |
465 | { | 460 | { |
466 | /* | ||
467 | * IOMMU adds unpredictable latency causing the CSB write (from the | ||
468 | * GPU into the HWSP) to only be visible some time after the interrupt | ||
469 | * (missed breadcrumb syndrome). | ||
470 | */ | ||
471 | if (intel_vtd_active()) | ||
472 | return true; | ||
473 | |||
474 | /* Older GVT emulation depends upon intercepting CSB mmio */ | 461 | /* Older GVT emulation depends upon intercepting CSB mmio */ |
475 | if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915)) | 462 | if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915)) |
476 | return true; | 463 | return true; |
477 | 464 | ||
478 | if (IS_CANNONLAKE(i915)) | ||
479 | return true; | ||
480 | |||
481 | return false; | 465 | return false; |
482 | } | 466 | } |
483 | 467 | ||
@@ -507,8 +491,9 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine) | |||
507 | */ | 491 | */ |
508 | void intel_engine_setup_common(struct intel_engine_cs *engine) | 492 | void intel_engine_setup_common(struct intel_engine_cs *engine) |
509 | { | 493 | { |
494 | i915_timeline_init(engine->i915, &engine->timeline, engine->name); | ||
495 | |||
510 | intel_engine_init_execlist(engine); | 496 | intel_engine_init_execlist(engine); |
511 | intel_engine_init_timeline(engine); | ||
512 | intel_engine_init_hangcheck(engine); | 497 | intel_engine_init_hangcheck(engine); |
513 | intel_engine_init_batch_pool(engine); | 498 | intel_engine_init_batch_pool(engine); |
514 | intel_engine_init_cmd_parser(engine); | 499 | intel_engine_init_cmd_parser(engine); |
@@ -541,8 +526,6 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size) | |||
541 | goto err_unref; | 526 | goto err_unref; |
542 | 527 | ||
543 | engine->scratch = vma; | 528 | engine->scratch = vma; |
544 | DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", | ||
545 | engine->name, i915_ggtt_offset(vma)); | ||
546 | return 0; | 529 | return 0; |
547 | 530 | ||
548 | err_unref: | 531 | err_unref: |
@@ -636,9 +619,6 @@ static int init_status_page(struct intel_engine_cs *engine) | |||
636 | engine->status_page.vma = vma; | 619 | engine->status_page.vma = vma; |
637 | engine->status_page.ggtt_offset = i915_ggtt_offset(vma); | 620 | engine->status_page.ggtt_offset = i915_ggtt_offset(vma); |
638 | engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); | 621 | engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); |
639 | |||
640 | DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", | ||
641 | engine->name, i915_ggtt_offset(vma)); | ||
642 | return 0; | 622 | return 0; |
643 | 623 | ||
644 | err_unpin: | 624 | err_unpin: |
@@ -690,7 +670,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) | |||
690 | * be available. To avoid this we always pin the default | 670 | * be available. To avoid this we always pin the default |
691 | * context. | 671 | * context. |
692 | */ | 672 | */ |
693 | ring = engine->context_pin(engine, engine->i915->kernel_context); | 673 | ring = intel_context_pin(engine->i915->kernel_context, engine); |
694 | if (IS_ERR(ring)) | 674 | if (IS_ERR(ring)) |
695 | return PTR_ERR(ring); | 675 | return PTR_ERR(ring); |
696 | 676 | ||
@@ -699,8 +679,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) | |||
699 | * we can interrupt the engine at any time. | 679 | * we can interrupt the engine at any time. |
700 | */ | 680 | */ |
701 | if (engine->i915->preempt_context) { | 681 | if (engine->i915->preempt_context) { |
702 | ring = engine->context_pin(engine, | 682 | ring = intel_context_pin(engine->i915->preempt_context, engine); |
703 | engine->i915->preempt_context); | ||
704 | if (IS_ERR(ring)) { | 683 | if (IS_ERR(ring)) { |
705 | ret = PTR_ERR(ring); | 684 | ret = PTR_ERR(ring); |
706 | goto err_unpin_kernel; | 685 | goto err_unpin_kernel; |
@@ -724,9 +703,9 @@ err_breadcrumbs: | |||
724 | intel_engine_fini_breadcrumbs(engine); | 703 | intel_engine_fini_breadcrumbs(engine); |
725 | err_unpin_preempt: | 704 | err_unpin_preempt: |
726 | if (engine->i915->preempt_context) | 705 | if (engine->i915->preempt_context) |
727 | engine->context_unpin(engine, engine->i915->preempt_context); | 706 | intel_context_unpin(engine->i915->preempt_context, engine); |
728 | err_unpin_kernel: | 707 | err_unpin_kernel: |
729 | engine->context_unpin(engine, engine->i915->kernel_context); | 708 | intel_context_unpin(engine->i915->kernel_context, engine); |
730 | return ret; | 709 | return ret; |
731 | } | 710 | } |
732 | 711 | ||
@@ -754,8 +733,10 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) | |||
754 | i915_gem_object_put(engine->default_state); | 733 | i915_gem_object_put(engine->default_state); |
755 | 734 | ||
756 | if (engine->i915->preempt_context) | 735 | if (engine->i915->preempt_context) |
757 | engine->context_unpin(engine, engine->i915->preempt_context); | 736 | intel_context_unpin(engine->i915->preempt_context, engine); |
758 | engine->context_unpin(engine, engine->i915->kernel_context); | 737 | intel_context_unpin(engine->i915->kernel_context, engine); |
738 | |||
739 | i915_timeline_fini(&engine->timeline); | ||
759 | } | 740 | } |
760 | 741 | ||
761 | u64 intel_engine_get_active_head(const struct intel_engine_cs *engine) | 742 | u64 intel_engine_get_active_head(const struct intel_engine_cs *engine) |
@@ -1008,7 +989,7 @@ bool intel_engine_has_kernel_context(const struct intel_engine_cs *engine) | |||
1008 | * the last request that remains in the timeline. When idle, it is | 989 | * the last request that remains in the timeline. When idle, it is |
1009 | * the last executed context as tracked by retirement. | 990 | * the last executed context as tracked by retirement. |
1010 | */ | 991 | */ |
1011 | rq = __i915_gem_active_peek(&engine->timeline->last_request); | 992 | rq = __i915_gem_active_peek(&engine->timeline.last_request); |
1012 | if (rq) | 993 | if (rq) |
1013 | return rq->ctx == kernel_context; | 994 | return rq->ctx == kernel_context; |
1014 | else | 995 | else |
@@ -1081,6 +1062,8 @@ void intel_engines_unpark(struct drm_i915_private *i915) | |||
1081 | for_each_engine(engine, i915, id) { | 1062 | for_each_engine(engine, i915, id) { |
1082 | if (engine->unpark) | 1063 | if (engine->unpark) |
1083 | engine->unpark(engine); | 1064 | engine->unpark(engine); |
1065 | |||
1066 | intel_engine_init_hangcheck(engine); | ||
1084 | } | 1067 | } |
1085 | } | 1068 | } |
1086 | 1069 | ||
@@ -1113,17 +1096,35 @@ unsigned int intel_engines_has_context_isolation(struct drm_i915_private *i915) | |||
1113 | return which; | 1096 | return which; |
1114 | } | 1097 | } |
1115 | 1098 | ||
1099 | static int print_sched_attr(struct drm_i915_private *i915, | ||
1100 | const struct i915_sched_attr *attr, | ||
1101 | char *buf, int x, int len) | ||
1102 | { | ||
1103 | if (attr->priority == I915_PRIORITY_INVALID) | ||
1104 | return x; | ||
1105 | |||
1106 | x += snprintf(buf + x, len - x, | ||
1107 | " prio=%d", attr->priority); | ||
1108 | |||
1109 | return x; | ||
1110 | } | ||
1111 | |||
1116 | static void print_request(struct drm_printer *m, | 1112 | static void print_request(struct drm_printer *m, |
1117 | struct i915_request *rq, | 1113 | struct i915_request *rq, |
1118 | const char *prefix) | 1114 | const char *prefix) |
1119 | { | 1115 | { |
1120 | const char *name = rq->fence.ops->get_timeline_name(&rq->fence); | 1116 | const char *name = rq->fence.ops->get_timeline_name(&rq->fence); |
1117 | char buf[80]; | ||
1118 | int x = 0; | ||
1121 | 1119 | ||
1122 | drm_printf(m, "%s%x%s [%llx:%x] prio=%d @ %dms: %s\n", prefix, | 1120 | x = print_sched_attr(rq->i915, &rq->sched.attr, buf, x, sizeof(buf)); |
1121 | |||
1122 | drm_printf(m, "%s%x%s [%llx:%x]%s @ %dms: %s\n", | ||
1123 | prefix, | ||
1123 | rq->global_seqno, | 1124 | rq->global_seqno, |
1124 | i915_request_completed(rq) ? "!" : "", | 1125 | i915_request_completed(rq) ? "!" : "", |
1125 | rq->fence.context, rq->fence.seqno, | 1126 | rq->fence.context, rq->fence.seqno, |
1126 | rq->priotree.priority, | 1127 | buf, |
1127 | jiffies_to_msecs(jiffies - rq->emitted_jiffies), | 1128 | jiffies_to_msecs(jiffies - rq->emitted_jiffies), |
1128 | name); | 1129 | name); |
1129 | } | 1130 | } |
@@ -1266,8 +1267,9 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine, | |||
1266 | char hdr[80]; | 1267 | char hdr[80]; |
1267 | 1268 | ||
1268 | snprintf(hdr, sizeof(hdr), | 1269 | snprintf(hdr, sizeof(hdr), |
1269 | "\t\tELSP[%d] count=%d, rq: ", | 1270 | "\t\tELSP[%d] count=%d, ring->start=%08x, rq: ", |
1270 | idx, count); | 1271 | idx, count, |
1272 | i915_ggtt_offset(rq->ring->vma)); | ||
1271 | print_request(m, rq, hdr); | 1273 | print_request(m, rq, hdr); |
1272 | } else { | 1274 | } else { |
1273 | drm_printf(m, "\t\tELSP[%d] idle\n", idx); | 1275 | drm_printf(m, "\t\tELSP[%d] idle\n", idx); |
@@ -1289,11 +1291,13 @@ void intel_engine_dump(struct intel_engine_cs *engine, | |||
1289 | struct drm_printer *m, | 1291 | struct drm_printer *m, |
1290 | const char *header, ...) | 1292 | const char *header, ...) |
1291 | { | 1293 | { |
1294 | const int MAX_REQUESTS_TO_SHOW = 8; | ||
1292 | struct intel_breadcrumbs * const b = &engine->breadcrumbs; | 1295 | struct intel_breadcrumbs * const b = &engine->breadcrumbs; |
1293 | const struct intel_engine_execlists * const execlists = &engine->execlists; | 1296 | const struct intel_engine_execlists * const execlists = &engine->execlists; |
1294 | struct i915_gpu_error * const error = &engine->i915->gpu_error; | 1297 | struct i915_gpu_error * const error = &engine->i915->gpu_error; |
1295 | struct i915_request *rq; | 1298 | struct i915_request *rq, *last; |
1296 | struct rb_node *rb; | 1299 | struct rb_node *rb; |
1300 | int count; | ||
1297 | 1301 | ||
1298 | if (header) { | 1302 | if (header) { |
1299 | va_list ap; | 1303 | va_list ap; |
@@ -1306,12 +1310,11 @@ void intel_engine_dump(struct intel_engine_cs *engine, | |||
1306 | if (i915_terminally_wedged(&engine->i915->gpu_error)) | 1310 | if (i915_terminally_wedged(&engine->i915->gpu_error)) |
1307 | drm_printf(m, "*** WEDGED ***\n"); | 1311 | drm_printf(m, "*** WEDGED ***\n"); |
1308 | 1312 | ||
1309 | drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", | 1313 | drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms]\n", |
1310 | intel_engine_get_seqno(engine), | 1314 | intel_engine_get_seqno(engine), |
1311 | intel_engine_last_submit(engine), | 1315 | intel_engine_last_submit(engine), |
1312 | engine->hangcheck.seqno, | 1316 | engine->hangcheck.seqno, |
1313 | jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), | 1317 | jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp)); |
1314 | engine->timeline->inflight_seqnos); | ||
1315 | drm_printf(m, "\tReset count: %d (global %d)\n", | 1318 | drm_printf(m, "\tReset count: %d (global %d)\n", |
1316 | i915_reset_engine_count(error, engine), | 1319 | i915_reset_engine_count(error, engine), |
1317 | i915_reset_count(error)); | 1320 | i915_reset_count(error)); |
@@ -1320,14 +1323,14 @@ void intel_engine_dump(struct intel_engine_cs *engine, | |||
1320 | 1323 | ||
1321 | drm_printf(m, "\tRequests:\n"); | 1324 | drm_printf(m, "\tRequests:\n"); |
1322 | 1325 | ||
1323 | rq = list_first_entry(&engine->timeline->requests, | 1326 | rq = list_first_entry(&engine->timeline.requests, |
1324 | struct i915_request, link); | 1327 | struct i915_request, link); |
1325 | if (&rq->link != &engine->timeline->requests) | 1328 | if (&rq->link != &engine->timeline.requests) |
1326 | print_request(m, rq, "\t\tfirst "); | 1329 | print_request(m, rq, "\t\tfirst "); |
1327 | 1330 | ||
1328 | rq = list_last_entry(&engine->timeline->requests, | 1331 | rq = list_last_entry(&engine->timeline.requests, |
1329 | struct i915_request, link); | 1332 | struct i915_request, link); |
1330 | if (&rq->link != &engine->timeline->requests) | 1333 | if (&rq->link != &engine->timeline.requests) |
1331 | print_request(m, rq, "\t\tlast "); | 1334 | print_request(m, rq, "\t\tlast "); |
1332 | 1335 | ||
1333 | rq = i915_gem_find_active_request(engine); | 1336 | rq = i915_gem_find_active_request(engine); |
@@ -1359,18 +1362,49 @@ void intel_engine_dump(struct intel_engine_cs *engine, | |||
1359 | drm_printf(m, "\tDevice is asleep; skipping register dump\n"); | 1362 | drm_printf(m, "\tDevice is asleep; skipping register dump\n"); |
1360 | } | 1363 | } |
1361 | 1364 | ||
1362 | spin_lock_irq(&engine->timeline->lock); | 1365 | spin_lock_irq(&engine->timeline.lock); |
1363 | list_for_each_entry(rq, &engine->timeline->requests, link) | 1366 | |
1364 | print_request(m, rq, "\t\tE "); | 1367 | last = NULL; |
1368 | count = 0; | ||
1369 | list_for_each_entry(rq, &engine->timeline.requests, link) { | ||
1370 | if (count++ < MAX_REQUESTS_TO_SHOW - 1) | ||
1371 | print_request(m, rq, "\t\tE "); | ||
1372 | else | ||
1373 | last = rq; | ||
1374 | } | ||
1375 | if (last) { | ||
1376 | if (count > MAX_REQUESTS_TO_SHOW) { | ||
1377 | drm_printf(m, | ||
1378 | "\t\t...skipping %d executing requests...\n", | ||
1379 | count - MAX_REQUESTS_TO_SHOW); | ||
1380 | } | ||
1381 | print_request(m, last, "\t\tE "); | ||
1382 | } | ||
1383 | |||
1384 | last = NULL; | ||
1385 | count = 0; | ||
1365 | drm_printf(m, "\t\tQueue priority: %d\n", execlists->queue_priority); | 1386 | drm_printf(m, "\t\tQueue priority: %d\n", execlists->queue_priority); |
1366 | for (rb = execlists->first; rb; rb = rb_next(rb)) { | 1387 | for (rb = execlists->first; rb; rb = rb_next(rb)) { |
1367 | struct i915_priolist *p = | 1388 | struct i915_priolist *p = |
1368 | rb_entry(rb, typeof(*p), node); | 1389 | rb_entry(rb, typeof(*p), node); |
1369 | 1390 | ||
1370 | list_for_each_entry(rq, &p->requests, priotree.link) | 1391 | list_for_each_entry(rq, &p->requests, sched.link) { |
1371 | print_request(m, rq, "\t\tQ "); | 1392 | if (count++ < MAX_REQUESTS_TO_SHOW - 1) |
1393 | print_request(m, rq, "\t\tQ "); | ||
1394 | else | ||
1395 | last = rq; | ||
1396 | } | ||
1372 | } | 1397 | } |
1373 | spin_unlock_irq(&engine->timeline->lock); | 1398 | if (last) { |
1399 | if (count > MAX_REQUESTS_TO_SHOW) { | ||
1400 | drm_printf(m, | ||
1401 | "\t\t...skipping %d queued requests...\n", | ||
1402 | count - MAX_REQUESTS_TO_SHOW); | ||
1403 | } | ||
1404 | print_request(m, last, "\t\tQ "); | ||
1405 | } | ||
1406 | |||
1407 | spin_unlock_irq(&engine->timeline.lock); | ||
1374 | 1408 | ||
1375 | spin_lock_irq(&b->rb_lock); | 1409 | spin_lock_irq(&b->rb_lock); |
1376 | for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { | 1410 | for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { |
@@ -1435,7 +1469,7 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) | |||
1435 | return -ENODEV; | 1469 | return -ENODEV; |
1436 | 1470 | ||
1437 | tasklet_disable(&execlists->tasklet); | 1471 | tasklet_disable(&execlists->tasklet); |
1438 | spin_lock_irqsave(&engine->stats.lock, flags); | 1472 | write_seqlock_irqsave(&engine->stats.lock, flags); |
1439 | 1473 | ||
1440 | if (unlikely(engine->stats.enabled == ~0)) { | 1474 | if (unlikely(engine->stats.enabled == ~0)) { |
1441 | err = -EBUSY; | 1475 | err = -EBUSY; |
@@ -1459,7 +1493,7 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) | |||
1459 | } | 1493 | } |
1460 | 1494 | ||
1461 | unlock: | 1495 | unlock: |
1462 | spin_unlock_irqrestore(&engine->stats.lock, flags); | 1496 | write_sequnlock_irqrestore(&engine->stats.lock, flags); |
1463 | tasklet_enable(&execlists->tasklet); | 1497 | tasklet_enable(&execlists->tasklet); |
1464 | 1498 | ||
1465 | return err; | 1499 | return err; |
@@ -1488,12 +1522,13 @@ static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine) | |||
1488 | */ | 1522 | */ |
1489 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine) | 1523 | ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine) |
1490 | { | 1524 | { |
1525 | unsigned int seq; | ||
1491 | ktime_t total; | 1526 | ktime_t total; |
1492 | unsigned long flags; | ||
1493 | 1527 | ||
1494 | spin_lock_irqsave(&engine->stats.lock, flags); | 1528 | do { |
1495 | total = __intel_engine_get_busy_time(engine); | 1529 | seq = read_seqbegin(&engine->stats.lock); |
1496 | spin_unlock_irqrestore(&engine->stats.lock, flags); | 1530 | total = __intel_engine_get_busy_time(engine); |
1531 | } while (read_seqretry(&engine->stats.lock, seq)); | ||
1497 | 1532 | ||
1498 | return total; | 1533 | return total; |
1499 | } | 1534 | } |
@@ -1511,13 +1546,13 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine) | |||
1511 | if (!intel_engine_supports_stats(engine)) | 1546 | if (!intel_engine_supports_stats(engine)) |
1512 | return; | 1547 | return; |
1513 | 1548 | ||
1514 | spin_lock_irqsave(&engine->stats.lock, flags); | 1549 | write_seqlock_irqsave(&engine->stats.lock, flags); |
1515 | WARN_ON_ONCE(engine->stats.enabled == 0); | 1550 | WARN_ON_ONCE(engine->stats.enabled == 0); |
1516 | if (--engine->stats.enabled == 0) { | 1551 | if (--engine->stats.enabled == 0) { |
1517 | engine->stats.total = __intel_engine_get_busy_time(engine); | 1552 | engine->stats.total = __intel_engine_get_busy_time(engine); |
1518 | engine->stats.active = 0; | 1553 | engine->stats.active = 0; |
1519 | } | 1554 | } |
1520 | spin_unlock_irqrestore(&engine->stats.lock, flags); | 1555 | write_sequnlock_irqrestore(&engine->stats.lock, flags); |
1521 | } | 1556 | } |
1522 | 1557 | ||
1523 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | 1558 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index a00a59a7d9ec..116f4ccf1bbd 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c | |||
@@ -203,26 +203,6 @@ void intel_guc_fini(struct intel_guc *guc) | |||
203 | guc_shared_data_destroy(guc); | 203 | guc_shared_data_destroy(guc); |
204 | } | 204 | } |
205 | 205 | ||
206 | static u32 get_gt_type(struct drm_i915_private *dev_priv) | ||
207 | { | ||
208 | /* XXX: GT type based on PCI device ID? field seems unused by fw */ | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static u32 get_core_family(struct drm_i915_private *dev_priv) | ||
213 | { | ||
214 | u32 gen = INTEL_GEN(dev_priv); | ||
215 | |||
216 | switch (gen) { | ||
217 | case 9: | ||
218 | return GUC_CORE_FAMILY_GEN9; | ||
219 | |||
220 | default: | ||
221 | MISSING_CASE(gen); | ||
222 | return GUC_CORE_FAMILY_UNKNOWN; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static u32 get_log_control_flags(void) | 206 | static u32 get_log_control_flags(void) |
227 | { | 207 | { |
228 | u32 level = i915_modparams.guc_log_level; | 208 | u32 level = i915_modparams.guc_log_level; |
@@ -255,10 +235,6 @@ void intel_guc_init_params(struct intel_guc *guc) | |||
255 | 235 | ||
256 | memset(params, 0, sizeof(params)); | 236 | memset(params, 0, sizeof(params)); |
257 | 237 | ||
258 | params[GUC_CTL_DEVICE_INFO] |= | ||
259 | (get_gt_type(dev_priv) << GUC_CTL_GT_TYPE_SHIFT) | | ||
260 | (get_core_family(dev_priv) << GUC_CTL_CORE_FAMILY_SHIFT); | ||
261 | |||
262 | /* | 238 | /* |
263 | * GuC ARAT increment is 10 ns. GuC default scheduler quantum is one | 239 | * GuC ARAT increment is 10 ns. GuC default scheduler quantum is one |
264 | * second. This ARAR is calculated by: | 240 | * second. This ARAR is calculated by: |
diff --git a/drivers/gpu/drm/i915/intel_guc_ads.c b/drivers/gpu/drm/i915/intel_guc_ads.c index 334cb5202e1c..dcaa3fb71765 100644 --- a/drivers/gpu/drm/i915/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/intel_guc_ads.c | |||
@@ -121,7 +121,8 @@ int intel_guc_ads_create(struct intel_guc *guc) | |||
121 | * to find it. Note that we have to skip our header (1 page), | 121 | * to find it. Note that we have to skip our header (1 page), |
122 | * because our GuC shared data is there. | 122 | * because our GuC shared data is there. |
123 | */ | 123 | */ |
124 | kernel_ctx_vma = dev_priv->kernel_context->engine[RCS].state; | 124 | kernel_ctx_vma = to_intel_context(dev_priv->kernel_context, |
125 | dev_priv->engine[RCS])->state; | ||
125 | blob->ads.golden_context_lrca = | 126 | blob->ads.golden_context_lrca = |
126 | intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset; | 127 | intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset; |
127 | 128 | ||
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index d73673f5d30c..0867ba76d445 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h | |||
@@ -23,9 +23,6 @@ | |||
23 | #ifndef _INTEL_GUC_FWIF_H | 23 | #ifndef _INTEL_GUC_FWIF_H |
24 | #define _INTEL_GUC_FWIF_H | 24 | #define _INTEL_GUC_FWIF_H |
25 | 25 | ||
26 | #define GUC_CORE_FAMILY_GEN9 12 | ||
27 | #define GUC_CORE_FAMILY_UNKNOWN 0x7fffffff | ||
28 | |||
29 | #define GUC_CLIENT_PRIORITY_KMD_HIGH 0 | 26 | #define GUC_CLIENT_PRIORITY_KMD_HIGH 0 |
30 | #define GUC_CLIENT_PRIORITY_HIGH 1 | 27 | #define GUC_CLIENT_PRIORITY_HIGH 1 |
31 | #define GUC_CLIENT_PRIORITY_KMD_NORMAL 2 | 28 | #define GUC_CLIENT_PRIORITY_KMD_NORMAL 2 |
@@ -82,8 +79,6 @@ | |||
82 | #define GUC_CTL_ARAT_LOW 2 | 79 | #define GUC_CTL_ARAT_LOW 2 |
83 | 80 | ||
84 | #define GUC_CTL_DEVICE_INFO 3 | 81 | #define GUC_CTL_DEVICE_INFO 3 |
85 | #define GUC_CTL_GT_TYPE_SHIFT 0 | ||
86 | #define GUC_CTL_CORE_FAMILY_SHIFT 7 | ||
87 | 82 | ||
88 | #define GUC_CTL_LOG_PARAMS 4 | 83 | #define GUC_CTL_LOG_PARAMS 4 |
89 | #define GUC_LOG_VALID (1 << 0) | 84 | #define GUC_LOG_VALID (1 << 0) |
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 97121230656c..2feb65096966 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c | |||
@@ -124,9 +124,17 @@ static int reserve_doorbell(struct intel_guc_client *client) | |||
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | static bool has_doorbell(struct intel_guc_client *client) | ||
128 | { | ||
129 | if (client->doorbell_id == GUC_DOORBELL_INVALID) | ||
130 | return false; | ||
131 | |||
132 | return test_bit(client->doorbell_id, client->guc->doorbell_bitmap); | ||
133 | } | ||
134 | |||
127 | static void unreserve_doorbell(struct intel_guc_client *client) | 135 | static void unreserve_doorbell(struct intel_guc_client *client) |
128 | { | 136 | { |
129 | GEM_BUG_ON(client->doorbell_id == GUC_DOORBELL_INVALID); | 137 | GEM_BUG_ON(!has_doorbell(client)); |
130 | 138 | ||
131 | __clear_bit(client->doorbell_id, client->guc->doorbell_bitmap); | 139 | __clear_bit(client->doorbell_id, client->guc->doorbell_bitmap); |
132 | client->doorbell_id = GUC_DOORBELL_INVALID; | 140 | client->doorbell_id = GUC_DOORBELL_INVALID; |
@@ -184,14 +192,6 @@ static struct guc_doorbell_info *__get_doorbell(struct intel_guc_client *client) | |||
184 | return client->vaddr + client->doorbell_offset; | 192 | return client->vaddr + client->doorbell_offset; |
185 | } | 193 | } |
186 | 194 | ||
187 | static bool has_doorbell(struct intel_guc_client *client) | ||
188 | { | ||
189 | if (client->doorbell_id == GUC_DOORBELL_INVALID) | ||
190 | return false; | ||
191 | |||
192 | return test_bit(client->doorbell_id, client->guc->doorbell_bitmap); | ||
193 | } | ||
194 | |||
195 | static void __create_doorbell(struct intel_guc_client *client) | 195 | static void __create_doorbell(struct intel_guc_client *client) |
196 | { | 196 | { |
197 | struct guc_doorbell_info *doorbell; | 197 | struct guc_doorbell_info *doorbell; |
@@ -207,7 +207,6 @@ static void __destroy_doorbell(struct intel_guc_client *client) | |||
207 | struct guc_doorbell_info *doorbell; | 207 | struct guc_doorbell_info *doorbell; |
208 | u16 db_id = client->doorbell_id; | 208 | u16 db_id = client->doorbell_id; |
209 | 209 | ||
210 | |||
211 | doorbell = __get_doorbell(client); | 210 | doorbell = __get_doorbell(client); |
212 | doorbell->db_status = GUC_DOORBELL_DISABLED; | 211 | doorbell->db_status = GUC_DOORBELL_DISABLED; |
213 | doorbell->cookie = 0; | 212 | doorbell->cookie = 0; |
@@ -224,6 +223,9 @@ static int create_doorbell(struct intel_guc_client *client) | |||
224 | { | 223 | { |
225 | int ret; | 224 | int ret; |
226 | 225 | ||
226 | if (WARN_ON(!has_doorbell(client))) | ||
227 | return -ENODEV; /* internal setup error, should never happen */ | ||
228 | |||
227 | __update_doorbell_desc(client, client->doorbell_id); | 229 | __update_doorbell_desc(client, client->doorbell_id); |
228 | __create_doorbell(client); | 230 | __create_doorbell(client); |
229 | 231 | ||
@@ -362,7 +364,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, | |||
362 | desc->db_id = client->doorbell_id; | 364 | desc->db_id = client->doorbell_id; |
363 | 365 | ||
364 | for_each_engine_masked(engine, dev_priv, client->engines, tmp) { | 366 | for_each_engine_masked(engine, dev_priv, client->engines, tmp) { |
365 | struct intel_context *ce = &ctx->engine[engine->id]; | 367 | struct intel_context *ce = to_intel_context(ctx, engine); |
366 | u32 guc_engine_id = engine->guc_id; | 368 | u32 guc_engine_id = engine->guc_id; |
367 | struct guc_execlist_context *lrc = &desc->lrc[guc_engine_id]; | 369 | struct guc_execlist_context *lrc = &desc->lrc[guc_engine_id]; |
368 | 370 | ||
@@ -659,7 +661,7 @@ static void port_assign(struct execlist_port *port, struct i915_request *rq) | |||
659 | 661 | ||
660 | static inline int rq_prio(const struct i915_request *rq) | 662 | static inline int rq_prio(const struct i915_request *rq) |
661 | { | 663 | { |
662 | return rq->priotree.priority; | 664 | return rq->sched.attr.priority; |
663 | } | 665 | } |
664 | 666 | ||
665 | static inline int port_prio(const struct execlist_port *port) | 667 | static inline int port_prio(const struct execlist_port *port) |
@@ -667,7 +669,7 @@ static inline int port_prio(const struct execlist_port *port) | |||
667 | return rq_prio(port_request(port)); | 669 | return rq_prio(port_request(port)); |
668 | } | 670 | } |
669 | 671 | ||
670 | static void guc_dequeue(struct intel_engine_cs *engine) | 672 | static bool __guc_dequeue(struct intel_engine_cs *engine) |
671 | { | 673 | { |
672 | struct intel_engine_execlists * const execlists = &engine->execlists; | 674 | struct intel_engine_execlists * const execlists = &engine->execlists; |
673 | struct execlist_port *port = execlists->port; | 675 | struct execlist_port *port = execlists->port; |
@@ -677,7 +679,8 @@ static void guc_dequeue(struct intel_engine_cs *engine) | |||
677 | bool submit = false; | 679 | bool submit = false; |
678 | struct rb_node *rb; | 680 | struct rb_node *rb; |
679 | 681 | ||
680 | spin_lock_irq(&engine->timeline->lock); | 682 | lockdep_assert_held(&engine->timeline.lock); |
683 | |||
681 | rb = execlists->first; | 684 | rb = execlists->first; |
682 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); | 685 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); |
683 | 686 | ||
@@ -692,13 +695,13 @@ static void guc_dequeue(struct intel_engine_cs *engine) | |||
692 | EXECLISTS_ACTIVE_PREEMPT); | 695 | EXECLISTS_ACTIVE_PREEMPT); |
693 | queue_work(engine->i915->guc.preempt_wq, | 696 | queue_work(engine->i915->guc.preempt_wq, |
694 | &preempt_work->work); | 697 | &preempt_work->work); |
695 | goto unlock; | 698 | return false; |
696 | } | 699 | } |
697 | } | 700 | } |
698 | 701 | ||
699 | port++; | 702 | port++; |
700 | if (port_isset(port)) | 703 | if (port_isset(port)) |
701 | goto unlock; | 704 | return false; |
702 | } | 705 | } |
703 | GEM_BUG_ON(port_isset(port)); | 706 | GEM_BUG_ON(port_isset(port)); |
704 | 707 | ||
@@ -706,11 +709,11 @@ static void guc_dequeue(struct intel_engine_cs *engine) | |||
706 | struct i915_priolist *p = to_priolist(rb); | 709 | struct i915_priolist *p = to_priolist(rb); |
707 | struct i915_request *rq, *rn; | 710 | struct i915_request *rq, *rn; |
708 | 711 | ||
709 | list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { | 712 | list_for_each_entry_safe(rq, rn, &p->requests, sched.link) { |
710 | if (last && rq->ctx != last->ctx) { | 713 | if (last && rq->ctx != last->ctx) { |
711 | if (port == last_port) { | 714 | if (port == last_port) { |
712 | __list_del_many(&p->requests, | 715 | __list_del_many(&p->requests, |
713 | &rq->priotree.link); | 716 | &rq->sched.link); |
714 | goto done; | 717 | goto done; |
715 | } | 718 | } |
716 | 719 | ||
@@ -719,7 +722,7 @@ static void guc_dequeue(struct intel_engine_cs *engine) | |||
719 | port++; | 722 | port++; |
720 | } | 723 | } |
721 | 724 | ||
722 | INIT_LIST_HEAD(&rq->priotree.link); | 725 | INIT_LIST_HEAD(&rq->sched.link); |
723 | 726 | ||
724 | __i915_request_submit(rq); | 727 | __i915_request_submit(rq); |
725 | trace_i915_request_in(rq, port_index(port, execlists)); | 728 | trace_i915_request_in(rq, port_index(port, execlists)); |
@@ -736,19 +739,34 @@ static void guc_dequeue(struct intel_engine_cs *engine) | |||
736 | done: | 739 | done: |
737 | execlists->queue_priority = rb ? to_priolist(rb)->priority : INT_MIN; | 740 | execlists->queue_priority = rb ? to_priolist(rb)->priority : INT_MIN; |
738 | execlists->first = rb; | 741 | execlists->first = rb; |
739 | if (submit) { | 742 | if (submit) |
740 | port_assign(port, last); | 743 | port_assign(port, last); |
744 | if (last) | ||
741 | execlists_user_begin(execlists, execlists->port); | 745 | execlists_user_begin(execlists, execlists->port); |
742 | guc_submit(engine); | ||
743 | } | ||
744 | 746 | ||
745 | /* We must always keep the beast fed if we have work piled up */ | 747 | /* We must always keep the beast fed if we have work piled up */ |
746 | GEM_BUG_ON(port_isset(execlists->port) && | 748 | GEM_BUG_ON(port_isset(execlists->port) && |
747 | !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); | 749 | !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); |
748 | GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); | 750 | GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); |
749 | 751 | ||
750 | unlock: | 752 | return submit; |
751 | spin_unlock_irq(&engine->timeline->lock); | 753 | } |
754 | |||
755 | static void guc_dequeue(struct intel_engine_cs *engine) | ||
756 | { | ||
757 | unsigned long flags; | ||
758 | bool submit; | ||
759 | |||
760 | local_irq_save(flags); | ||
761 | |||
762 | spin_lock(&engine->timeline.lock); | ||
763 | submit = __guc_dequeue(engine); | ||
764 | spin_unlock(&engine->timeline.lock); | ||
765 | |||
766 | if (submit) | ||
767 | guc_submit(engine); | ||
768 | |||
769 | local_irq_restore(flags); | ||
752 | } | 770 | } |
753 | 771 | ||
754 | static void guc_submission_tasklet(unsigned long data) | 772 | static void guc_submission_tasklet(unsigned long data) |
@@ -990,7 +1008,8 @@ static void guc_fill_preempt_context(struct intel_guc *guc) | |||
990 | enum intel_engine_id id; | 1008 | enum intel_engine_id id; |
991 | 1009 | ||
992 | for_each_engine(engine, dev_priv, id) { | 1010 | for_each_engine(engine, dev_priv, id) { |
993 | struct intel_context *ce = &client->owner->engine[id]; | 1011 | struct intel_context *ce = |
1012 | to_intel_context(client->owner, engine); | ||
994 | u32 addr = intel_hws_preempt_done_address(engine); | 1013 | u32 addr = intel_hws_preempt_done_address(engine); |
995 | u32 *cs; | 1014 | u32 *cs; |
996 | 1015 | ||
diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index fd0ffb8328d0..d47e346bd49e 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c | |||
@@ -356,7 +356,7 @@ static void hangcheck_accumulate_sample(struct intel_engine_cs *engine, | |||
356 | break; | 356 | break; |
357 | 357 | ||
358 | case ENGINE_DEAD: | 358 | case ENGINE_DEAD: |
359 | if (drm_debug & DRM_UT_DRIVER) { | 359 | if (GEM_SHOW_DEBUG()) { |
360 | struct drm_printer p = drm_debug_printer("hangcheck"); | 360 | struct drm_printer p = drm_debug_printer("hangcheck"); |
361 | intel_engine_dump(engine, &p, "%s\n", engine->name); | 361 | intel_engine_dump(engine, &p, "%s\n", engine->name); |
362 | } | 362 | } |
@@ -452,6 +452,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) | |||
452 | void intel_engine_init_hangcheck(struct intel_engine_cs *engine) | 452 | void intel_engine_init_hangcheck(struct intel_engine_cs *engine) |
453 | { | 453 | { |
454 | memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); | 454 | memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); |
455 | engine->hangcheck.action_timestamp = jiffies; | ||
455 | } | 456 | } |
456 | 457 | ||
457 | void intel_hangcheck_init(struct drm_i915_private *i915) | 458 | void intel_hangcheck_init(struct drm_i915_private *i915) |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c7c85134a84a..15434cad5430 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -177,7 +177,7 @@ static inline struct i915_priolist *to_priolist(struct rb_node *rb) | |||
177 | 177 | ||
178 | static inline int rq_prio(const struct i915_request *rq) | 178 | static inline int rq_prio(const struct i915_request *rq) |
179 | { | 179 | { |
180 | return rq->priotree.priority; | 180 | return rq->sched.attr.priority; |
181 | } | 181 | } |
182 | 182 | ||
183 | static inline bool need_preempt(const struct intel_engine_cs *engine, | 183 | static inline bool need_preempt(const struct intel_engine_cs *engine, |
@@ -185,7 +185,8 @@ static inline bool need_preempt(const struct intel_engine_cs *engine, | |||
185 | int prio) | 185 | int prio) |
186 | { | 186 | { |
187 | return (intel_engine_has_preemption(engine) && | 187 | return (intel_engine_has_preemption(engine) && |
188 | __execlists_need_preempt(prio, rq_prio(last))); | 188 | __execlists_need_preempt(prio, rq_prio(last)) && |
189 | !i915_request_completed(last)); | ||
189 | } | 190 | } |
190 | 191 | ||
191 | /** | 192 | /** |
@@ -223,7 +224,7 @@ static void | |||
223 | intel_lr_context_descriptor_update(struct i915_gem_context *ctx, | 224 | intel_lr_context_descriptor_update(struct i915_gem_context *ctx, |
224 | struct intel_engine_cs *engine) | 225 | struct intel_engine_cs *engine) |
225 | { | 226 | { |
226 | struct intel_context *ce = &ctx->engine[engine->id]; | 227 | struct intel_context *ce = to_intel_context(ctx, engine); |
227 | u64 desc; | 228 | u64 desc; |
228 | 229 | ||
229 | BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (BIT(GEN8_CTX_ID_WIDTH))); | 230 | BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (BIT(GEN8_CTX_ID_WIDTH))); |
@@ -257,9 +258,7 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx, | |||
257 | } | 258 | } |
258 | 259 | ||
259 | static struct i915_priolist * | 260 | static struct i915_priolist * |
260 | lookup_priolist(struct intel_engine_cs *engine, | 261 | lookup_priolist(struct intel_engine_cs *engine, int prio) |
261 | struct i915_priotree *pt, | ||
262 | int prio) | ||
263 | { | 262 | { |
264 | struct intel_engine_execlists * const execlists = &engine->execlists; | 263 | struct intel_engine_execlists * const execlists = &engine->execlists; |
265 | struct i915_priolist *p; | 264 | struct i915_priolist *p; |
@@ -330,10 +329,10 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine) | |||
330 | struct i915_priolist *uninitialized_var(p); | 329 | struct i915_priolist *uninitialized_var(p); |
331 | int last_prio = I915_PRIORITY_INVALID; | 330 | int last_prio = I915_PRIORITY_INVALID; |
332 | 331 | ||
333 | lockdep_assert_held(&engine->timeline->lock); | 332 | lockdep_assert_held(&engine->timeline.lock); |
334 | 333 | ||
335 | list_for_each_entry_safe_reverse(rq, rn, | 334 | list_for_each_entry_safe_reverse(rq, rn, |
336 | &engine->timeline->requests, | 335 | &engine->timeline.requests, |
337 | link) { | 336 | link) { |
338 | if (i915_request_completed(rq)) | 337 | if (i915_request_completed(rq)) |
339 | return; | 338 | return; |
@@ -344,10 +343,11 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine) | |||
344 | GEM_BUG_ON(rq_prio(rq) == I915_PRIORITY_INVALID); | 343 | GEM_BUG_ON(rq_prio(rq) == I915_PRIORITY_INVALID); |
345 | if (rq_prio(rq) != last_prio) { | 344 | if (rq_prio(rq) != last_prio) { |
346 | last_prio = rq_prio(rq); | 345 | last_prio = rq_prio(rq); |
347 | p = lookup_priolist(engine, &rq->priotree, last_prio); | 346 | p = lookup_priolist(engine, last_prio); |
348 | } | 347 | } |
349 | 348 | ||
350 | list_add(&rq->priotree.link, &p->requests); | 349 | GEM_BUG_ON(p->priority != rq_prio(rq)); |
350 | list_add(&rq->sched.link, &p->requests); | ||
351 | } | 351 | } |
352 | } | 352 | } |
353 | 353 | ||
@@ -356,10 +356,13 @@ execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists) | |||
356 | { | 356 | { |
357 | struct intel_engine_cs *engine = | 357 | struct intel_engine_cs *engine = |
358 | container_of(execlists, typeof(*engine), execlists); | 358 | container_of(execlists, typeof(*engine), execlists); |
359 | unsigned long flags; | ||
360 | |||
361 | spin_lock_irqsave(&engine->timeline.lock, flags); | ||
359 | 362 | ||
360 | spin_lock_irq(&engine->timeline->lock); | ||
361 | __unwind_incomplete_requests(engine); | 363 | __unwind_incomplete_requests(engine); |
362 | spin_unlock_irq(&engine->timeline->lock); | 364 | |
365 | spin_unlock_irqrestore(&engine->timeline.lock, flags); | ||
363 | } | 366 | } |
364 | 367 | ||
365 | static inline void | 368 | static inline void |
@@ -397,10 +400,11 @@ execlists_context_schedule_in(struct i915_request *rq) | |||
397 | } | 400 | } |
398 | 401 | ||
399 | static inline void | 402 | static inline void |
400 | execlists_context_schedule_out(struct i915_request *rq) | 403 | execlists_context_schedule_out(struct i915_request *rq, unsigned long status) |
401 | { | 404 | { |
402 | intel_engine_context_out(rq->engine); | 405 | intel_engine_context_out(rq->engine); |
403 | execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); | 406 | execlists_context_status_change(rq, status); |
407 | trace_i915_request_out(rq); | ||
404 | } | 408 | } |
405 | 409 | ||
406 | static void | 410 | static void |
@@ -414,7 +418,7 @@ execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state) | |||
414 | 418 | ||
415 | static u64 execlists_update_context(struct i915_request *rq) | 419 | static u64 execlists_update_context(struct i915_request *rq) |
416 | { | 420 | { |
417 | struct intel_context *ce = &rq->ctx->engine[rq->engine->id]; | 421 | struct intel_context *ce = to_intel_context(rq->ctx, rq->engine); |
418 | struct i915_hw_ppgtt *ppgtt = | 422 | struct i915_hw_ppgtt *ppgtt = |
419 | rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; | 423 | rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; |
420 | u32 *reg_state = ce->lrc_reg_state; | 424 | u32 *reg_state = ce->lrc_reg_state; |
@@ -523,7 +527,7 @@ static void inject_preempt_context(struct intel_engine_cs *engine) | |||
523 | { | 527 | { |
524 | struct intel_engine_execlists *execlists = &engine->execlists; | 528 | struct intel_engine_execlists *execlists = &engine->execlists; |
525 | struct intel_context *ce = | 529 | struct intel_context *ce = |
526 | &engine->i915->preempt_context->engine[engine->id]; | 530 | to_intel_context(engine->i915->preempt_context, engine); |
527 | unsigned int n; | 531 | unsigned int n; |
528 | 532 | ||
529 | GEM_BUG_ON(execlists->preempt_complete_status != | 533 | GEM_BUG_ON(execlists->preempt_complete_status != |
@@ -552,7 +556,7 @@ static void inject_preempt_context(struct intel_engine_cs *engine) | |||
552 | execlists_set_active(&engine->execlists, EXECLISTS_ACTIVE_PREEMPT); | 556 | execlists_set_active(&engine->execlists, EXECLISTS_ACTIVE_PREEMPT); |
553 | } | 557 | } |
554 | 558 | ||
555 | static void execlists_dequeue(struct intel_engine_cs *engine) | 559 | static bool __execlists_dequeue(struct intel_engine_cs *engine) |
556 | { | 560 | { |
557 | struct intel_engine_execlists * const execlists = &engine->execlists; | 561 | struct intel_engine_execlists * const execlists = &engine->execlists; |
558 | struct execlist_port *port = execlists->port; | 562 | struct execlist_port *port = execlists->port; |
@@ -562,6 +566,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
562 | struct rb_node *rb; | 566 | struct rb_node *rb; |
563 | bool submit = false; | 567 | bool submit = false; |
564 | 568 | ||
569 | lockdep_assert_held(&engine->timeline.lock); | ||
570 | |||
565 | /* Hardware submission is through 2 ports. Conceptually each port | 571 | /* Hardware submission is through 2 ports. Conceptually each port |
566 | * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is | 572 | * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is |
567 | * static for a context, and unique to each, so we only execute | 573 | * static for a context, and unique to each, so we only execute |
@@ -583,7 +589,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
583 | * and context switches) submission. | 589 | * and context switches) submission. |
584 | */ | 590 | */ |
585 | 591 | ||
586 | spin_lock_irq(&engine->timeline->lock); | ||
587 | rb = execlists->first; | 592 | rb = execlists->first; |
588 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); | 593 | GEM_BUG_ON(rb_first(&execlists->queue) != rb); |
589 | 594 | ||
@@ -598,7 +603,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
598 | EXECLISTS_ACTIVE_USER)); | 603 | EXECLISTS_ACTIVE_USER)); |
599 | GEM_BUG_ON(!port_count(&port[0])); | 604 | GEM_BUG_ON(!port_count(&port[0])); |
600 | if (port_count(&port[0]) > 1) | 605 | if (port_count(&port[0]) > 1) |
601 | goto unlock; | 606 | return false; |
602 | 607 | ||
603 | /* | 608 | /* |
604 | * If we write to ELSP a second time before the HW has had | 609 | * If we write to ELSP a second time before the HW has had |
@@ -608,11 +613,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
608 | * the HW to indicate that it has had a chance to respond. | 613 | * the HW to indicate that it has had a chance to respond. |
609 | */ | 614 | */ |
610 | if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK)) | 615 | if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK)) |
611 | goto unlock; | 616 | return false; |
612 | 617 | ||
613 | if (need_preempt(engine, last, execlists->queue_priority)) { | 618 | if (need_preempt(engine, last, execlists->queue_priority)) { |
614 | inject_preempt_context(engine); | 619 | inject_preempt_context(engine); |
615 | goto unlock; | 620 | return false; |
616 | } | 621 | } |
617 | 622 | ||
618 | /* | 623 | /* |
@@ -637,7 +642,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
637 | * priorities of the ports haven't been switch. | 642 | * priorities of the ports haven't been switch. |
638 | */ | 643 | */ |
639 | if (port_count(&port[1])) | 644 | if (port_count(&port[1])) |
640 | goto unlock; | 645 | return false; |
641 | 646 | ||
642 | /* | 647 | /* |
643 | * WaIdleLiteRestore:bdw,skl | 648 | * WaIdleLiteRestore:bdw,skl |
@@ -654,7 +659,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
654 | struct i915_priolist *p = to_priolist(rb); | 659 | struct i915_priolist *p = to_priolist(rb); |
655 | struct i915_request *rq, *rn; | 660 | struct i915_request *rq, *rn; |
656 | 661 | ||
657 | list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { | 662 | list_for_each_entry_safe(rq, rn, &p->requests, sched.link) { |
658 | /* | 663 | /* |
659 | * Can we combine this request with the current port? | 664 | * Can we combine this request with the current port? |
660 | * It has to be the same context/ringbuffer and not | 665 | * It has to be the same context/ringbuffer and not |
@@ -674,7 +679,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
674 | */ | 679 | */ |
675 | if (port == last_port) { | 680 | if (port == last_port) { |
676 | __list_del_many(&p->requests, | 681 | __list_del_many(&p->requests, |
677 | &rq->priotree.link); | 682 | &rq->sched.link); |
678 | goto done; | 683 | goto done; |
679 | } | 684 | } |
680 | 685 | ||
@@ -688,7 +693,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
688 | if (ctx_single_port_submission(last->ctx) || | 693 | if (ctx_single_port_submission(last->ctx) || |
689 | ctx_single_port_submission(rq->ctx)) { | 694 | ctx_single_port_submission(rq->ctx)) { |
690 | __list_del_many(&p->requests, | 695 | __list_del_many(&p->requests, |
691 | &rq->priotree.link); | 696 | &rq->sched.link); |
692 | goto done; | 697 | goto done; |
693 | } | 698 | } |
694 | 699 | ||
@@ -701,7 +706,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
701 | GEM_BUG_ON(port_isset(port)); | 706 | GEM_BUG_ON(port_isset(port)); |
702 | } | 707 | } |
703 | 708 | ||
704 | INIT_LIST_HEAD(&rq->priotree.link); | 709 | INIT_LIST_HEAD(&rq->sched.link); |
705 | __i915_request_submit(rq); | 710 | __i915_request_submit(rq); |
706 | trace_i915_request_in(rq, port_index(port, execlists)); | 711 | trace_i915_request_in(rq, port_index(port, execlists)); |
707 | last = rq; | 712 | last = rq; |
@@ -742,13 +747,25 @@ done: | |||
742 | /* We must always keep the beast fed if we have work piled up */ | 747 | /* We must always keep the beast fed if we have work piled up */ |
743 | GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); | 748 | GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); |
744 | 749 | ||
745 | unlock: | 750 | /* Re-evaluate the executing context setup after each preemptive kick */ |
746 | spin_unlock_irq(&engine->timeline->lock); | 751 | if (last) |
747 | |||
748 | if (submit) { | ||
749 | execlists_user_begin(execlists, execlists->port); | 752 | execlists_user_begin(execlists, execlists->port); |
753 | |||
754 | return submit; | ||
755 | } | ||
756 | |||
757 | static void execlists_dequeue(struct intel_engine_cs *engine) | ||
758 | { | ||
759 | struct intel_engine_execlists * const execlists = &engine->execlists; | ||
760 | unsigned long flags; | ||
761 | bool submit; | ||
762 | |||
763 | spin_lock_irqsave(&engine->timeline.lock, flags); | ||
764 | submit = __execlists_dequeue(engine); | ||
765 | spin_unlock_irqrestore(&engine->timeline.lock, flags); | ||
766 | |||
767 | if (submit) | ||
750 | execlists_submit_ports(engine); | 768 | execlists_submit_ports(engine); |
751 | } | ||
752 | 769 | ||
753 | GEM_BUG_ON(port_isset(execlists->port) && | 770 | GEM_BUG_ON(port_isset(execlists->port) && |
754 | !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); | 771 | !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); |
@@ -771,12 +788,10 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) | |||
771 | intel_engine_get_seqno(rq->engine)); | 788 | intel_engine_get_seqno(rq->engine)); |
772 | 789 | ||
773 | GEM_BUG_ON(!execlists->active); | 790 | GEM_BUG_ON(!execlists->active); |
774 | intel_engine_context_out(rq->engine); | 791 | execlists_context_schedule_out(rq, |
775 | 792 | i915_request_completed(rq) ? | |
776 | execlists_context_status_change(rq, | 793 | INTEL_CONTEXT_SCHEDULE_OUT : |
777 | i915_request_completed(rq) ? | 794 | INTEL_CONTEXT_SCHEDULE_PREEMPTED); |
778 | INTEL_CONTEXT_SCHEDULE_OUT : | ||
779 | INTEL_CONTEXT_SCHEDULE_PREEMPTED); | ||
780 | 795 | ||
781 | i915_request_put(rq); | 796 | i915_request_put(rq); |
782 | 797 | ||
@@ -789,22 +804,9 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) | |||
789 | 804 | ||
790 | static void clear_gtiir(struct intel_engine_cs *engine) | 805 | static void clear_gtiir(struct intel_engine_cs *engine) |
791 | { | 806 | { |
792 | static const u8 gtiir[] = { | ||
793 | [RCS] = 0, | ||
794 | [BCS] = 0, | ||
795 | [VCS] = 1, | ||
796 | [VCS2] = 1, | ||
797 | [VECS] = 3, | ||
798 | }; | ||
799 | struct drm_i915_private *dev_priv = engine->i915; | 807 | struct drm_i915_private *dev_priv = engine->i915; |
800 | int i; | 808 | int i; |
801 | 809 | ||
802 | /* TODO: correctly reset irqs for gen11 */ | ||
803 | if (WARN_ON_ONCE(INTEL_GEN(engine->i915) >= 11)) | ||
804 | return; | ||
805 | |||
806 | GEM_BUG_ON(engine->id >= ARRAY_SIZE(gtiir)); | ||
807 | |||
808 | /* | 810 | /* |
809 | * Clear any pending interrupt state. | 811 | * Clear any pending interrupt state. |
810 | * | 812 | * |
@@ -812,13 +814,50 @@ static void clear_gtiir(struct intel_engine_cs *engine) | |||
812 | * double buffered, and so if we only reset it once there may | 814 | * double buffered, and so if we only reset it once there may |
813 | * still be an interrupt pending. | 815 | * still be an interrupt pending. |
814 | */ | 816 | */ |
815 | for (i = 0; i < 2; i++) { | 817 | if (INTEL_GEN(dev_priv) >= 11) { |
816 | I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), | 818 | static const struct { |
819 | u8 bank; | ||
820 | u8 bit; | ||
821 | } gen11_gtiir[] = { | ||
822 | [RCS] = {0, GEN11_RCS0}, | ||
823 | [BCS] = {0, GEN11_BCS}, | ||
824 | [_VCS(0)] = {1, GEN11_VCS(0)}, | ||
825 | [_VCS(1)] = {1, GEN11_VCS(1)}, | ||
826 | [_VCS(2)] = {1, GEN11_VCS(2)}, | ||
827 | [_VCS(3)] = {1, GEN11_VCS(3)}, | ||
828 | [_VECS(0)] = {1, GEN11_VECS(0)}, | ||
829 | [_VECS(1)] = {1, GEN11_VECS(1)}, | ||
830 | }; | ||
831 | unsigned long irqflags; | ||
832 | |||
833 | GEM_BUG_ON(engine->id >= ARRAY_SIZE(gen11_gtiir)); | ||
834 | |||
835 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
836 | for (i = 0; i < 2; i++) { | ||
837 | gen11_reset_one_iir(dev_priv, | ||
838 | gen11_gtiir[engine->id].bank, | ||
839 | gen11_gtiir[engine->id].bit); | ||
840 | } | ||
841 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
842 | } else { | ||
843 | static const u8 gtiir[] = { | ||
844 | [RCS] = 0, | ||
845 | [BCS] = 0, | ||
846 | [VCS] = 1, | ||
847 | [VCS2] = 1, | ||
848 | [VECS] = 3, | ||
849 | }; | ||
850 | |||
851 | GEM_BUG_ON(engine->id >= ARRAY_SIZE(gtiir)); | ||
852 | |||
853 | for (i = 0; i < 2; i++) { | ||
854 | I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), | ||
855 | engine->irq_keep_mask); | ||
856 | POSTING_READ(GEN8_GT_IIR(gtiir[engine->id])); | ||
857 | } | ||
858 | GEM_BUG_ON(I915_READ(GEN8_GT_IIR(gtiir[engine->id])) & | ||
817 | engine->irq_keep_mask); | 859 | engine->irq_keep_mask); |
818 | POSTING_READ(GEN8_GT_IIR(gtiir[engine->id])); | ||
819 | } | 860 | } |
820 | GEM_BUG_ON(I915_READ(GEN8_GT_IIR(gtiir[engine->id])) & | ||
821 | engine->irq_keep_mask); | ||
822 | } | 861 | } |
823 | 862 | ||
824 | static void reset_irq(struct intel_engine_cs *engine) | 863 | static void reset_irq(struct intel_engine_cs *engine) |
@@ -868,10 +907,10 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
868 | execlists_cancel_port_requests(execlists); | 907 | execlists_cancel_port_requests(execlists); |
869 | reset_irq(engine); | 908 | reset_irq(engine); |
870 | 909 | ||
871 | spin_lock(&engine->timeline->lock); | 910 | spin_lock(&engine->timeline.lock); |
872 | 911 | ||
873 | /* Mark all executing requests as skipped. */ | 912 | /* Mark all executing requests as skipped. */ |
874 | list_for_each_entry(rq, &engine->timeline->requests, link) { | 913 | list_for_each_entry(rq, &engine->timeline.requests, link) { |
875 | GEM_BUG_ON(!rq->global_seqno); | 914 | GEM_BUG_ON(!rq->global_seqno); |
876 | if (!i915_request_completed(rq)) | 915 | if (!i915_request_completed(rq)) |
877 | dma_fence_set_error(&rq->fence, -EIO); | 916 | dma_fence_set_error(&rq->fence, -EIO); |
@@ -882,8 +921,8 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
882 | while (rb) { | 921 | while (rb) { |
883 | struct i915_priolist *p = to_priolist(rb); | 922 | struct i915_priolist *p = to_priolist(rb); |
884 | 923 | ||
885 | list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { | 924 | list_for_each_entry_safe(rq, rn, &p->requests, sched.link) { |
886 | INIT_LIST_HEAD(&rq->priotree.link); | 925 | INIT_LIST_HEAD(&rq->sched.link); |
887 | 926 | ||
888 | dma_fence_set_error(&rq->fence, -EIO); | 927 | dma_fence_set_error(&rq->fence, -EIO); |
889 | __i915_request_submit(rq); | 928 | __i915_request_submit(rq); |
@@ -903,7 +942,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
903 | execlists->first = NULL; | 942 | execlists->first = NULL; |
904 | GEM_BUG_ON(port_isset(execlists->port)); | 943 | GEM_BUG_ON(port_isset(execlists->port)); |
905 | 944 | ||
906 | spin_unlock(&engine->timeline->lock); | 945 | spin_unlock(&engine->timeline.lock); |
907 | 946 | ||
908 | local_irq_restore(flags); | 947 | local_irq_restore(flags); |
909 | } | 948 | } |
@@ -969,6 +1008,7 @@ static void execlists_submission_tasklet(unsigned long data) | |||
969 | 1008 | ||
970 | head = execlists->csb_head; | 1009 | head = execlists->csb_head; |
971 | tail = READ_ONCE(buf[write_idx]); | 1010 | tail = READ_ONCE(buf[write_idx]); |
1011 | rmb(); /* Hopefully paired with a wmb() in HW */ | ||
972 | } | 1012 | } |
973 | GEM_TRACE("%s cs-irq head=%d [%d%s], tail=%d [%d%s]\n", | 1013 | GEM_TRACE("%s cs-irq head=%d [%d%s], tail=%d [%d%s]\n", |
974 | engine->name, | 1014 | engine->name, |
@@ -1079,8 +1119,8 @@ static void execlists_submission_tasklet(unsigned long data) | |||
1079 | */ | 1119 | */ |
1080 | GEM_BUG_ON(!i915_request_completed(rq)); | 1120 | GEM_BUG_ON(!i915_request_completed(rq)); |
1081 | 1121 | ||
1082 | execlists_context_schedule_out(rq); | 1122 | execlists_context_schedule_out(rq, |
1083 | trace_i915_request_out(rq); | 1123 | INTEL_CONTEXT_SCHEDULE_OUT); |
1084 | i915_request_put(rq); | 1124 | i915_request_put(rq); |
1085 | 1125 | ||
1086 | GEM_TRACE("%s completed ctx=%d\n", | 1126 | GEM_TRACE("%s completed ctx=%d\n", |
@@ -1116,10 +1156,11 @@ static void execlists_submission_tasklet(unsigned long data) | |||
1116 | } | 1156 | } |
1117 | 1157 | ||
1118 | static void queue_request(struct intel_engine_cs *engine, | 1158 | static void queue_request(struct intel_engine_cs *engine, |
1119 | struct i915_priotree *pt, | 1159 | struct i915_sched_node *node, |
1120 | int prio) | 1160 | int prio) |
1121 | { | 1161 | { |
1122 | list_add_tail(&pt->link, &lookup_priolist(engine, pt, prio)->requests); | 1162 | list_add_tail(&node->link, |
1163 | &lookup_priolist(engine, prio)->requests); | ||
1123 | } | 1164 | } |
1124 | 1165 | ||
1125 | static void __submit_queue(struct intel_engine_cs *engine, int prio) | 1166 | static void __submit_queue(struct intel_engine_cs *engine, int prio) |
@@ -1140,42 +1181,45 @@ static void execlists_submit_request(struct i915_request *request) | |||
1140 | unsigned long flags; | 1181 | unsigned long flags; |
1141 | 1182 | ||
1142 | /* Will be called from irq-context when using foreign fences. */ | 1183 | /* Will be called from irq-context when using foreign fences. */ |
1143 | spin_lock_irqsave(&engine->timeline->lock, flags); | 1184 | spin_lock_irqsave(&engine->timeline.lock, flags); |
1144 | 1185 | ||
1145 | queue_request(engine, &request->priotree, rq_prio(request)); | 1186 | queue_request(engine, &request->sched, rq_prio(request)); |
1146 | submit_queue(engine, rq_prio(request)); | 1187 | submit_queue(engine, rq_prio(request)); |
1147 | 1188 | ||
1148 | GEM_BUG_ON(!engine->execlists.first); | 1189 | GEM_BUG_ON(!engine->execlists.first); |
1149 | GEM_BUG_ON(list_empty(&request->priotree.link)); | 1190 | GEM_BUG_ON(list_empty(&request->sched.link)); |
1150 | 1191 | ||
1151 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 1192 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
1152 | } | 1193 | } |
1153 | 1194 | ||
1154 | static struct i915_request *pt_to_request(struct i915_priotree *pt) | 1195 | static struct i915_request *sched_to_request(struct i915_sched_node *node) |
1155 | { | 1196 | { |
1156 | return container_of(pt, struct i915_request, priotree); | 1197 | return container_of(node, struct i915_request, sched); |
1157 | } | 1198 | } |
1158 | 1199 | ||
1159 | static struct intel_engine_cs * | 1200 | static struct intel_engine_cs * |
1160 | pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked) | 1201 | sched_lock_engine(struct i915_sched_node *node, struct intel_engine_cs *locked) |
1161 | { | 1202 | { |
1162 | struct intel_engine_cs *engine = pt_to_request(pt)->engine; | 1203 | struct intel_engine_cs *engine = sched_to_request(node)->engine; |
1163 | 1204 | ||
1164 | GEM_BUG_ON(!locked); | 1205 | GEM_BUG_ON(!locked); |
1165 | 1206 | ||
1166 | if (engine != locked) { | 1207 | if (engine != locked) { |
1167 | spin_unlock(&locked->timeline->lock); | 1208 | spin_unlock(&locked->timeline.lock); |
1168 | spin_lock(&engine->timeline->lock); | 1209 | spin_lock(&engine->timeline.lock); |
1169 | } | 1210 | } |
1170 | 1211 | ||
1171 | return engine; | 1212 | return engine; |
1172 | } | 1213 | } |
1173 | 1214 | ||
1174 | static void execlists_schedule(struct i915_request *request, int prio) | 1215 | static void execlists_schedule(struct i915_request *request, |
1216 | const struct i915_sched_attr *attr) | ||
1175 | { | 1217 | { |
1176 | struct intel_engine_cs *engine; | 1218 | struct i915_priolist *uninitialized_var(pl); |
1219 | struct intel_engine_cs *engine, *last; | ||
1177 | struct i915_dependency *dep, *p; | 1220 | struct i915_dependency *dep, *p; |
1178 | struct i915_dependency stack; | 1221 | struct i915_dependency stack; |
1222 | const int prio = attr->priority; | ||
1179 | LIST_HEAD(dfs); | 1223 | LIST_HEAD(dfs); |
1180 | 1224 | ||
1181 | GEM_BUG_ON(prio == I915_PRIORITY_INVALID); | 1225 | GEM_BUG_ON(prio == I915_PRIORITY_INVALID); |
@@ -1183,23 +1227,23 @@ static void execlists_schedule(struct i915_request *request, int prio) | |||
1183 | if (i915_request_completed(request)) | 1227 | if (i915_request_completed(request)) |
1184 | return; | 1228 | return; |
1185 | 1229 | ||
1186 | if (prio <= READ_ONCE(request->priotree.priority)) | 1230 | if (prio <= READ_ONCE(request->sched.attr.priority)) |
1187 | return; | 1231 | return; |
1188 | 1232 | ||
1189 | /* Need BKL in order to use the temporary link inside i915_dependency */ | 1233 | /* Need BKL in order to use the temporary link inside i915_dependency */ |
1190 | lockdep_assert_held(&request->i915->drm.struct_mutex); | 1234 | lockdep_assert_held(&request->i915->drm.struct_mutex); |
1191 | 1235 | ||
1192 | stack.signaler = &request->priotree; | 1236 | stack.signaler = &request->sched; |
1193 | list_add(&stack.dfs_link, &dfs); | 1237 | list_add(&stack.dfs_link, &dfs); |
1194 | 1238 | ||
1195 | /* | 1239 | /* |
1196 | * Recursively bump all dependent priorities to match the new request. | 1240 | * Recursively bump all dependent priorities to match the new request. |
1197 | * | 1241 | * |
1198 | * A naive approach would be to use recursion: | 1242 | * A naive approach would be to use recursion: |
1199 | * static void update_priorities(struct i915_priotree *pt, prio) { | 1243 | * static void update_priorities(struct i915_sched_node *node, prio) { |
1200 | * list_for_each_entry(dep, &pt->signalers_list, signal_link) | 1244 | * list_for_each_entry(dep, &node->signalers_list, signal_link) |
1201 | * update_priorities(dep->signal, prio) | 1245 | * update_priorities(dep->signal, prio) |
1202 | * queue_request(pt); | 1246 | * queue_request(node); |
1203 | * } | 1247 | * } |
1204 | * but that may have unlimited recursion depth and so runs a very | 1248 | * but that may have unlimited recursion depth and so runs a very |
1205 | * real risk of overunning the kernel stack. Instead, we build | 1249 | * real risk of overunning the kernel stack. Instead, we build |
@@ -1211,7 +1255,7 @@ static void execlists_schedule(struct i915_request *request, int prio) | |||
1211 | * last element in the list is the request we must execute first. | 1255 | * last element in the list is the request we must execute first. |
1212 | */ | 1256 | */ |
1213 | list_for_each_entry(dep, &dfs, dfs_link) { | 1257 | list_for_each_entry(dep, &dfs, dfs_link) { |
1214 | struct i915_priotree *pt = dep->signaler; | 1258 | struct i915_sched_node *node = dep->signaler; |
1215 | 1259 | ||
1216 | /* | 1260 | /* |
1217 | * Within an engine, there can be no cycle, but we may | 1261 | * Within an engine, there can be no cycle, but we may |
@@ -1219,14 +1263,14 @@ static void execlists_schedule(struct i915_request *request, int prio) | |||
1219 | * (redundant dependencies are not eliminated) and across | 1263 | * (redundant dependencies are not eliminated) and across |
1220 | * engines. | 1264 | * engines. |
1221 | */ | 1265 | */ |
1222 | list_for_each_entry(p, &pt->signalers_list, signal_link) { | 1266 | list_for_each_entry(p, &node->signalers_list, signal_link) { |
1223 | GEM_BUG_ON(p == dep); /* no cycles! */ | 1267 | GEM_BUG_ON(p == dep); /* no cycles! */ |
1224 | 1268 | ||
1225 | if (i915_priotree_signaled(p->signaler)) | 1269 | if (i915_sched_node_signaled(p->signaler)) |
1226 | continue; | 1270 | continue; |
1227 | 1271 | ||
1228 | GEM_BUG_ON(p->signaler->priority < pt->priority); | 1272 | GEM_BUG_ON(p->signaler->attr.priority < node->attr.priority); |
1229 | if (prio > READ_ONCE(p->signaler->priority)) | 1273 | if (prio > READ_ONCE(p->signaler->attr.priority)) |
1230 | list_move_tail(&p->dfs_link, &dfs); | 1274 | list_move_tail(&p->dfs_link, &dfs); |
1231 | } | 1275 | } |
1232 | } | 1276 | } |
@@ -1237,40 +1281,45 @@ static void execlists_schedule(struct i915_request *request, int prio) | |||
1237 | * execlists_submit_request()), we can set our own priority and skip | 1281 | * execlists_submit_request()), we can set our own priority and skip |
1238 | * acquiring the engine locks. | 1282 | * acquiring the engine locks. |
1239 | */ | 1283 | */ |
1240 | if (request->priotree.priority == I915_PRIORITY_INVALID) { | 1284 | if (request->sched.attr.priority == I915_PRIORITY_INVALID) { |
1241 | GEM_BUG_ON(!list_empty(&request->priotree.link)); | 1285 | GEM_BUG_ON(!list_empty(&request->sched.link)); |
1242 | request->priotree.priority = prio; | 1286 | request->sched.attr = *attr; |
1243 | if (stack.dfs_link.next == stack.dfs_link.prev) | 1287 | if (stack.dfs_link.next == stack.dfs_link.prev) |
1244 | return; | 1288 | return; |
1245 | __list_del_entry(&stack.dfs_link); | 1289 | __list_del_entry(&stack.dfs_link); |
1246 | } | 1290 | } |
1247 | 1291 | ||
1292 | last = NULL; | ||
1248 | engine = request->engine; | 1293 | engine = request->engine; |
1249 | spin_lock_irq(&engine->timeline->lock); | 1294 | spin_lock_irq(&engine->timeline.lock); |
1250 | 1295 | ||
1251 | /* Fifo and depth-first replacement ensure our deps execute before us */ | 1296 | /* Fifo and depth-first replacement ensure our deps execute before us */ |
1252 | list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) { | 1297 | list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) { |
1253 | struct i915_priotree *pt = dep->signaler; | 1298 | struct i915_sched_node *node = dep->signaler; |
1254 | 1299 | ||
1255 | INIT_LIST_HEAD(&dep->dfs_link); | 1300 | INIT_LIST_HEAD(&dep->dfs_link); |
1256 | 1301 | ||
1257 | engine = pt_lock_engine(pt, engine); | 1302 | engine = sched_lock_engine(node, engine); |
1258 | 1303 | ||
1259 | if (prio <= pt->priority) | 1304 | if (prio <= node->attr.priority) |
1260 | continue; | 1305 | continue; |
1261 | 1306 | ||
1262 | pt->priority = prio; | 1307 | node->attr.priority = prio; |
1263 | if (!list_empty(&pt->link)) { | 1308 | if (!list_empty(&node->link)) { |
1264 | __list_del_entry(&pt->link); | 1309 | if (last != engine) { |
1265 | queue_request(engine, pt, prio); | 1310 | pl = lookup_priolist(engine, prio); |
1311 | last = engine; | ||
1312 | } | ||
1313 | GEM_BUG_ON(pl->priority != prio); | ||
1314 | list_move_tail(&node->link, &pl->requests); | ||
1266 | } | 1315 | } |
1267 | 1316 | ||
1268 | if (prio > engine->execlists.queue_priority && | 1317 | if (prio > engine->execlists.queue_priority && |
1269 | i915_sw_fence_done(&pt_to_request(pt)->submit)) | 1318 | i915_sw_fence_done(&sched_to_request(node)->submit)) |
1270 | __submit_queue(engine, prio); | 1319 | __submit_queue(engine, prio); |
1271 | } | 1320 | } |
1272 | 1321 | ||
1273 | spin_unlock_irq(&engine->timeline->lock); | 1322 | spin_unlock_irq(&engine->timeline.lock); |
1274 | } | 1323 | } |
1275 | 1324 | ||
1276 | static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma) | 1325 | static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma) |
@@ -1300,7 +1349,7 @@ static struct intel_ring * | |||
1300 | execlists_context_pin(struct intel_engine_cs *engine, | 1349 | execlists_context_pin(struct intel_engine_cs *engine, |
1301 | struct i915_gem_context *ctx) | 1350 | struct i915_gem_context *ctx) |
1302 | { | 1351 | { |
1303 | struct intel_context *ce = &ctx->engine[engine->id]; | 1352 | struct intel_context *ce = to_intel_context(ctx, engine); |
1304 | void *vaddr; | 1353 | void *vaddr; |
1305 | int ret; | 1354 | int ret; |
1306 | 1355 | ||
@@ -1353,7 +1402,7 @@ err: | |||
1353 | static void execlists_context_unpin(struct intel_engine_cs *engine, | 1402 | static void execlists_context_unpin(struct intel_engine_cs *engine, |
1354 | struct i915_gem_context *ctx) | 1403 | struct i915_gem_context *ctx) |
1355 | { | 1404 | { |
1356 | struct intel_context *ce = &ctx->engine[engine->id]; | 1405 | struct intel_context *ce = to_intel_context(ctx, engine); |
1357 | 1406 | ||
1358 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); | 1407 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); |
1359 | GEM_BUG_ON(ce->pin_count == 0); | 1408 | GEM_BUG_ON(ce->pin_count == 0); |
@@ -1372,8 +1421,8 @@ static void execlists_context_unpin(struct intel_engine_cs *engine, | |||
1372 | 1421 | ||
1373 | static int execlists_request_alloc(struct i915_request *request) | 1422 | static int execlists_request_alloc(struct i915_request *request) |
1374 | { | 1423 | { |
1375 | struct intel_engine_cs *engine = request->engine; | 1424 | struct intel_context *ce = |
1376 | struct intel_context *ce = &request->ctx->engine[engine->id]; | 1425 | to_intel_context(request->ctx, request->engine); |
1377 | int ret; | 1426 | int ret; |
1378 | 1427 | ||
1379 | GEM_BUG_ON(!ce->pin_count); | 1428 | GEM_BUG_ON(!ce->pin_count); |
@@ -1633,6 +1682,8 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) | |||
1633 | return -EINVAL; | 1682 | return -EINVAL; |
1634 | 1683 | ||
1635 | switch (INTEL_GEN(engine->i915)) { | 1684 | switch (INTEL_GEN(engine->i915)) { |
1685 | case 11: | ||
1686 | return 0; | ||
1636 | case 10: | 1687 | case 10: |
1637 | wa_bb_fn[0] = gen10_init_indirectctx_bb; | 1688 | wa_bb_fn[0] = gen10_init_indirectctx_bb; |
1638 | wa_bb_fn[1] = NULL; | 1689 | wa_bb_fn[1] = NULL; |
@@ -1744,9 +1795,7 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine) | |||
1744 | if (ret) | 1795 | if (ret) |
1745 | return ret; | 1796 | return ret; |
1746 | 1797 | ||
1747 | ret = intel_whitelist_workarounds_apply(engine); | 1798 | intel_whitelist_workarounds_apply(engine); |
1748 | if (ret) | ||
1749 | return ret; | ||
1750 | 1799 | ||
1751 | /* We need to disable the AsyncFlip performance optimisations in order | 1800 | /* We need to disable the AsyncFlip performance optimisations in order |
1752 | * to use MI_WAIT_FOR_EVENT within the CS. It should already be | 1801 | * to use MI_WAIT_FOR_EVENT within the CS. It should already be |
@@ -1769,9 +1818,7 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) | |||
1769 | if (ret) | 1818 | if (ret) |
1770 | return ret; | 1819 | return ret; |
1771 | 1820 | ||
1772 | ret = intel_whitelist_workarounds_apply(engine); | 1821 | intel_whitelist_workarounds_apply(engine); |
1773 | if (ret) | ||
1774 | return ret; | ||
1775 | 1822 | ||
1776 | return 0; | 1823 | return 0; |
1777 | } | 1824 | } |
@@ -1780,8 +1827,8 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1780 | struct i915_request *request) | 1827 | struct i915_request *request) |
1781 | { | 1828 | { |
1782 | struct intel_engine_execlists * const execlists = &engine->execlists; | 1829 | struct intel_engine_execlists * const execlists = &engine->execlists; |
1783 | struct intel_context *ce; | ||
1784 | unsigned long flags; | 1830 | unsigned long flags; |
1831 | u32 *regs; | ||
1785 | 1832 | ||
1786 | GEM_TRACE("%s request global=%x, current=%d\n", | 1833 | GEM_TRACE("%s request global=%x, current=%d\n", |
1787 | engine->name, request ? request->global_seqno : 0, | 1834 | engine->name, request ? request->global_seqno : 0, |
@@ -1803,9 +1850,9 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1803 | reset_irq(engine); | 1850 | reset_irq(engine); |
1804 | 1851 | ||
1805 | /* Push back any incomplete requests for replay after the reset. */ | 1852 | /* Push back any incomplete requests for replay after the reset. */ |
1806 | spin_lock(&engine->timeline->lock); | 1853 | spin_lock(&engine->timeline.lock); |
1807 | __unwind_incomplete_requests(engine); | 1854 | __unwind_incomplete_requests(engine); |
1808 | spin_unlock(&engine->timeline->lock); | 1855 | spin_unlock(&engine->timeline.lock); |
1809 | 1856 | ||
1810 | local_irq_restore(flags); | 1857 | local_irq_restore(flags); |
1811 | 1858 | ||
@@ -1831,14 +1878,24 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1831 | * future request will be after userspace has had the opportunity | 1878 | * future request will be after userspace has had the opportunity |
1832 | * to recreate its own state. | 1879 | * to recreate its own state. |
1833 | */ | 1880 | */ |
1834 | ce = &request->ctx->engine[engine->id]; | 1881 | regs = to_intel_context(request->ctx, engine)->lrc_reg_state; |
1835 | execlists_init_reg_state(ce->lrc_reg_state, | 1882 | if (engine->default_state) { |
1836 | request->ctx, engine, ce->ring); | 1883 | void *defaults; |
1884 | |||
1885 | defaults = i915_gem_object_pin_map(engine->default_state, | ||
1886 | I915_MAP_WB); | ||
1887 | if (!IS_ERR(defaults)) { | ||
1888 | memcpy(regs, /* skip restoring the vanilla PPHWSP */ | ||
1889 | defaults + LRC_STATE_PN * PAGE_SIZE, | ||
1890 | engine->context_size - PAGE_SIZE); | ||
1891 | i915_gem_object_unpin_map(engine->default_state); | ||
1892 | } | ||
1893 | } | ||
1894 | execlists_init_reg_state(regs, request->ctx, engine, request->ring); | ||
1837 | 1895 | ||
1838 | /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */ | 1896 | /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */ |
1839 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = | 1897 | regs[CTX_RING_BUFFER_START + 1] = i915_ggtt_offset(request->ring->vma); |
1840 | i915_ggtt_offset(ce->ring->vma); | 1898 | regs[CTX_RING_HEAD + 1] = request->postfix; |
1841 | ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; | ||
1842 | 1899 | ||
1843 | request->ring->head = request->postfix; | 1900 | request->ring->head = request->postfix; |
1844 | intel_ring_update_space(request->ring); | 1901 | intel_ring_update_space(request->ring); |
@@ -1899,7 +1956,7 @@ static int gen8_emit_bb_start(struct i915_request *rq, | |||
1899 | rq->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(rq->engine); | 1956 | rq->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(rq->engine); |
1900 | } | 1957 | } |
1901 | 1958 | ||
1902 | cs = intel_ring_begin(rq, 4); | 1959 | cs = intel_ring_begin(rq, 6); |
1903 | if (IS_ERR(cs)) | 1960 | if (IS_ERR(cs)) |
1904 | return PTR_ERR(cs); | 1961 | return PTR_ERR(cs); |
1905 | 1962 | ||
@@ -1928,6 +1985,9 @@ static int gen8_emit_bb_start(struct i915_request *rq, | |||
1928 | (flags & I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0); | 1985 | (flags & I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0); |
1929 | *cs++ = lower_32_bits(offset); | 1986 | *cs++ = lower_32_bits(offset); |
1930 | *cs++ = upper_32_bits(offset); | 1987 | *cs++ = upper_32_bits(offset); |
1988 | |||
1989 | *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; | ||
1990 | *cs++ = MI_NOOP; | ||
1931 | intel_ring_advance(rq, cs); | 1991 | intel_ring_advance(rq, cs); |
1932 | 1992 | ||
1933 | return 0; | 1993 | return 0; |
@@ -2070,7 +2130,7 @@ static void gen8_emit_breadcrumb(struct i915_request *request, u32 *cs) | |||
2070 | cs = gen8_emit_ggtt_write(cs, request->global_seqno, | 2130 | cs = gen8_emit_ggtt_write(cs, request->global_seqno, |
2071 | intel_hws_seqno_address(request->engine)); | 2131 | intel_hws_seqno_address(request->engine)); |
2072 | *cs++ = MI_USER_INTERRUPT; | 2132 | *cs++ = MI_USER_INTERRUPT; |
2073 | *cs++ = MI_NOOP; | 2133 | *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; |
2074 | request->tail = intel_ring_offset(request, cs); | 2134 | request->tail = intel_ring_offset(request, cs); |
2075 | assert_ring_tail_valid(request->ring, request->tail); | 2135 | assert_ring_tail_valid(request->ring, request->tail); |
2076 | 2136 | ||
@@ -2086,7 +2146,7 @@ static void gen8_emit_breadcrumb_rcs(struct i915_request *request, u32 *cs) | |||
2086 | cs = gen8_emit_ggtt_write_rcs(cs, request->global_seqno, | 2146 | cs = gen8_emit_ggtt_write_rcs(cs, request->global_seqno, |
2087 | intel_hws_seqno_address(request->engine)); | 2147 | intel_hws_seqno_address(request->engine)); |
2088 | *cs++ = MI_USER_INTERRUPT; | 2148 | *cs++ = MI_USER_INTERRUPT; |
2089 | *cs++ = MI_NOOP; | 2149 | *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; |
2090 | request->tail = intel_ring_offset(request, cs); | 2150 | request->tail = intel_ring_offset(request, cs); |
2091 | assert_ring_tail_valid(request->ring, request->tail); | 2151 | assert_ring_tail_valid(request->ring, request->tail); |
2092 | 2152 | ||
@@ -2272,9 +2332,13 @@ static int logical_ring_init(struct intel_engine_cs *engine) | |||
2272 | } | 2332 | } |
2273 | 2333 | ||
2274 | engine->execlists.preempt_complete_status = ~0u; | 2334 | engine->execlists.preempt_complete_status = ~0u; |
2275 | if (engine->i915->preempt_context) | 2335 | if (engine->i915->preempt_context) { |
2336 | struct intel_context *ce = | ||
2337 | to_intel_context(engine->i915->preempt_context, engine); | ||
2338 | |||
2276 | engine->execlists.preempt_complete_status = | 2339 | engine->execlists.preempt_complete_status = |
2277 | upper_32_bits(engine->i915->preempt_context->engine[engine->id].lrc_desc); | 2340 | upper_32_bits(ce->lrc_desc); |
2341 | } | ||
2278 | 2342 | ||
2279 | return 0; | 2343 | return 0; |
2280 | 2344 | ||
@@ -2528,8 +2592,10 @@ populate_lr_context(struct i915_gem_context *ctx, | |||
2528 | 2592 | ||
2529 | defaults = i915_gem_object_pin_map(engine->default_state, | 2593 | defaults = i915_gem_object_pin_map(engine->default_state, |
2530 | I915_MAP_WB); | 2594 | I915_MAP_WB); |
2531 | if (IS_ERR(defaults)) | 2595 | if (IS_ERR(defaults)) { |
2532 | return PTR_ERR(defaults); | 2596 | ret = PTR_ERR(defaults); |
2597 | goto err_unpin_ctx; | ||
2598 | } | ||
2533 | 2599 | ||
2534 | memcpy(vaddr + start, defaults + start, engine->context_size); | 2600 | memcpy(vaddr + start, defaults + start, engine->context_size); |
2535 | i915_gem_object_unpin_map(engine->default_state); | 2601 | i915_gem_object_unpin_map(engine->default_state); |
@@ -2547,19 +2613,20 @@ populate_lr_context(struct i915_gem_context *ctx, | |||
2547 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | | 2613 | _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | |
2548 | CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT); | 2614 | CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT); |
2549 | 2615 | ||
2616 | err_unpin_ctx: | ||
2550 | i915_gem_object_unpin_map(ctx_obj); | 2617 | i915_gem_object_unpin_map(ctx_obj); |
2551 | 2618 | return ret; | |
2552 | return 0; | ||
2553 | } | 2619 | } |
2554 | 2620 | ||
2555 | static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, | 2621 | static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, |
2556 | struct intel_engine_cs *engine) | 2622 | struct intel_engine_cs *engine) |
2557 | { | 2623 | { |
2558 | struct drm_i915_gem_object *ctx_obj; | 2624 | struct drm_i915_gem_object *ctx_obj; |
2559 | struct intel_context *ce = &ctx->engine[engine->id]; | 2625 | struct intel_context *ce = to_intel_context(ctx, engine); |
2560 | struct i915_vma *vma; | 2626 | struct i915_vma *vma; |
2561 | uint32_t context_size; | 2627 | uint32_t context_size; |
2562 | struct intel_ring *ring; | 2628 | struct intel_ring *ring; |
2629 | struct i915_timeline *timeline; | ||
2563 | int ret; | 2630 | int ret; |
2564 | 2631 | ||
2565 | if (ce->state) | 2632 | if (ce->state) |
@@ -2575,8 +2642,8 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, | |||
2575 | 2642 | ||
2576 | ctx_obj = i915_gem_object_create(ctx->i915, context_size); | 2643 | ctx_obj = i915_gem_object_create(ctx->i915, context_size); |
2577 | if (IS_ERR(ctx_obj)) { | 2644 | if (IS_ERR(ctx_obj)) { |
2578 | DRM_DEBUG_DRIVER("Alloc LRC backing obj failed.\n"); | 2645 | ret = PTR_ERR(ctx_obj); |
2579 | return PTR_ERR(ctx_obj); | 2646 | goto error_deref_obj; |
2580 | } | 2647 | } |
2581 | 2648 | ||
2582 | vma = i915_vma_instance(ctx_obj, &ctx->i915->ggtt.base, NULL); | 2649 | vma = i915_vma_instance(ctx_obj, &ctx->i915->ggtt.base, NULL); |
@@ -2585,7 +2652,14 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, | |||
2585 | goto error_deref_obj; | 2652 | goto error_deref_obj; |
2586 | } | 2653 | } |
2587 | 2654 | ||
2588 | ring = intel_engine_create_ring(engine, ctx->ring_size); | 2655 | timeline = i915_timeline_create(ctx->i915, ctx->name); |
2656 | if (IS_ERR(timeline)) { | ||
2657 | ret = PTR_ERR(timeline); | ||
2658 | goto error_deref_obj; | ||
2659 | } | ||
2660 | |||
2661 | ring = intel_engine_create_ring(engine, timeline, ctx->ring_size); | ||
2662 | i915_timeline_put(timeline); | ||
2589 | if (IS_ERR(ring)) { | 2663 | if (IS_ERR(ring)) { |
2590 | ret = PTR_ERR(ring); | 2664 | ret = PTR_ERR(ring); |
2591 | goto error_deref_obj; | 2665 | goto error_deref_obj; |
@@ -2627,7 +2701,8 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) | |||
2627 | */ | 2701 | */ |
2628 | list_for_each_entry(ctx, &dev_priv->contexts.list, link) { | 2702 | list_for_each_entry(ctx, &dev_priv->contexts.list, link) { |
2629 | for_each_engine(engine, dev_priv, id) { | 2703 | for_each_engine(engine, dev_priv, id) { |
2630 | struct intel_context *ce = &ctx->engine[engine->id]; | 2704 | struct intel_context *ce = |
2705 | to_intel_context(ctx, engine); | ||
2631 | u32 *reg; | 2706 | u32 *reg; |
2632 | 2707 | ||
2633 | if (!ce->state) | 2708 | if (!ce->state) |
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 59d7b86012e9..4ec7d8dd13c8 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h | |||
@@ -108,7 +108,7 @@ static inline uint64_t | |||
108 | intel_lr_context_descriptor(struct i915_gem_context *ctx, | 108 | intel_lr_context_descriptor(struct i915_gem_context *ctx, |
109 | struct intel_engine_cs *engine) | 109 | struct intel_engine_cs *engine) |
110 | { | 110 | { |
111 | return ctx->engine[engine->id].lrc_desc; | 111 | return to_intel_context(ctx, engine)->lrc_desc; |
112 | } | 112 | } |
113 | 113 | ||
114 | #endif /* _INTEL_LRC_H_ */ | 114 | #endif /* _INTEL_LRC_H_ */ |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index d35d2d50f595..8691c86f579c 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -326,7 +326,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder, | |||
326 | 326 | ||
327 | I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON); | 327 | I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON); |
328 | POSTING_READ(lvds_encoder->reg); | 328 | POSTING_READ(lvds_encoder->reg); |
329 | if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000)) | 329 | |
330 | if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 5000)) | ||
330 | DRM_ERROR("timed out waiting for panel to power on\n"); | 331 | DRM_ERROR("timed out waiting for panel to power on\n"); |
331 | 332 | ||
332 | intel_panel_enable_backlight(pipe_config, conn_state); | 333 | intel_panel_enable_backlight(pipe_config, conn_state); |
diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index c0b34b7943b9..9f0bd6a4cb79 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c | |||
@@ -178,7 +178,8 @@ static bool get_mocs_settings(struct drm_i915_private *dev_priv, | |||
178 | { | 178 | { |
179 | bool result = false; | 179 | bool result = false; |
180 | 180 | ||
181 | if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { | 181 | if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv) || |
182 | IS_ICELAKE(dev_priv)) { | ||
182 | table->size = ARRAY_SIZE(skylake_mocs_table); | 183 | table->size = ARRAY_SIZE(skylake_mocs_table); |
183 | table->table = skylake_mocs_table; | 184 | table->table = skylake_mocs_table; |
184 | result = true; | 185 | result = true; |
@@ -217,6 +218,8 @@ static i915_reg_t mocs_register(enum intel_engine_id engine_id, int index) | |||
217 | return GEN9_VEBOX_MOCS(index); | 218 | return GEN9_VEBOX_MOCS(index); |
218 | case VCS2: | 219 | case VCS2: |
219 | return GEN9_MFX1_MOCS(index); | 220 | return GEN9_MFX1_MOCS(index); |
221 | case VCS3: | ||
222 | return GEN11_MFX2_MOCS(index); | ||
220 | default: | 223 | default: |
221 | MISSING_CASE(engine_id); | 224 | MISSING_CASE(engine_id); |
222 | return INVALID_MMIO_REG; | 225 | return INVALID_MMIO_REG; |
diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index 4f367c16e9e5..39a4e4edda07 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c | |||
@@ -766,13 +766,12 @@ display_crc_ctl_parse_object(const char *buf, enum intel_pipe_crc_object *o) | |||
766 | { | 766 | { |
767 | int i; | 767 | int i; |
768 | 768 | ||
769 | for (i = 0; i < ARRAY_SIZE(pipe_crc_objects); i++) | 769 | i = match_string(pipe_crc_objects, ARRAY_SIZE(pipe_crc_objects), buf); |
770 | if (!strcmp(buf, pipe_crc_objects[i])) { | 770 | if (i < 0) |
771 | *o = i; | 771 | return i; |
772 | return 0; | ||
773 | } | ||
774 | 772 | ||
775 | return -EINVAL; | 773 | *o = i; |
774 | return 0; | ||
776 | } | 775 | } |
777 | 776 | ||
778 | static int display_crc_ctl_parse_pipe(struct drm_i915_private *dev_priv, | 777 | static int display_crc_ctl_parse_pipe(struct drm_i915_private *dev_priv, |
@@ -798,13 +797,12 @@ display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s) | |||
798 | return 0; | 797 | return 0; |
799 | } | 798 | } |
800 | 799 | ||
801 | for (i = 0; i < ARRAY_SIZE(pipe_crc_sources); i++) | 800 | i = match_string(pipe_crc_sources, ARRAY_SIZE(pipe_crc_sources), buf); |
802 | if (!strcmp(buf, pipe_crc_sources[i])) { | 801 | if (i < 0) |
803 | *s = i; | 802 | return i; |
804 | return 0; | ||
805 | } | ||
806 | 803 | ||
807 | return -EINVAL; | 804 | *s = i; |
805 | return 0; | ||
808 | } | 806 | } |
809 | 807 | ||
810 | static int display_crc_ctl_parse(struct drm_i915_private *dev_priv, | 808 | static int display_crc_ctl_parse(struct drm_i915_private *dev_priv, |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4baab858e442..b85229e153c4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -3567,6 +3567,23 @@ bool ilk_disable_lp_wm(struct drm_device *dev) | |||
3567 | return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL); | 3567 | return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL); |
3568 | } | 3568 | } |
3569 | 3569 | ||
3570 | static u8 intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv) | ||
3571 | { | ||
3572 | u8 enabled_slices; | ||
3573 | |||
3574 | /* Slice 1 will always be enabled */ | ||
3575 | enabled_slices = 1; | ||
3576 | |||
3577 | /* Gen prior to GEN11 have only one DBuf slice */ | ||
3578 | if (INTEL_GEN(dev_priv) < 11) | ||
3579 | return enabled_slices; | ||
3580 | |||
3581 | if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE) | ||
3582 | enabled_slices++; | ||
3583 | |||
3584 | return enabled_slices; | ||
3585 | } | ||
3586 | |||
3570 | /* | 3587 | /* |
3571 | * FIXME: We still don't have the proper code detect if we need to apply the WA, | 3588 | * FIXME: We still don't have the proper code detect if we need to apply the WA, |
3572 | * so assume we'll always need it in order to avoid underruns. | 3589 | * so assume we'll always need it in order to avoid underruns. |
@@ -3754,9 +3771,42 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) | |||
3754 | return true; | 3771 | return true; |
3755 | } | 3772 | } |
3756 | 3773 | ||
3774 | static unsigned int intel_get_ddb_size(struct drm_i915_private *dev_priv, | ||
3775 | const struct intel_crtc_state *cstate, | ||
3776 | const unsigned int total_data_rate, | ||
3777 | const int num_active, | ||
3778 | struct skl_ddb_allocation *ddb) | ||
3779 | { | ||
3780 | const struct drm_display_mode *adjusted_mode; | ||
3781 | u64 total_data_bw; | ||
3782 | u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size; | ||
3783 | |||
3784 | WARN_ON(ddb_size == 0); | ||
3785 | |||
3786 | if (INTEL_GEN(dev_priv) < 11) | ||
3787 | return ddb_size - 4; /* 4 blocks for bypass path allocation */ | ||
3788 | |||
3789 | adjusted_mode = &cstate->base.adjusted_mode; | ||
3790 | total_data_bw = (u64)total_data_rate * drm_mode_vrefresh(adjusted_mode); | ||
3791 | |||
3792 | /* | ||
3793 | * 12GB/s is maximum BW supported by single DBuf slice. | ||
3794 | */ | ||
3795 | if (total_data_bw >= GBps(12) || num_active > 1) { | ||
3796 | ddb->enabled_slices = 2; | ||
3797 | } else { | ||
3798 | ddb->enabled_slices = 1; | ||
3799 | ddb_size /= 2; | ||
3800 | } | ||
3801 | |||
3802 | return ddb_size; | ||
3803 | } | ||
3804 | |||
3757 | static void | 3805 | static void |
3758 | skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, | 3806 | skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, |
3759 | const struct intel_crtc_state *cstate, | 3807 | const struct intel_crtc_state *cstate, |
3808 | const unsigned int total_data_rate, | ||
3809 | struct skl_ddb_allocation *ddb, | ||
3760 | struct skl_ddb_entry *alloc, /* out */ | 3810 | struct skl_ddb_entry *alloc, /* out */ |
3761 | int *num_active /* out */) | 3811 | int *num_active /* out */) |
3762 | { | 3812 | { |
@@ -3779,11 +3829,8 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, | |||
3779 | else | 3829 | else |
3780 | *num_active = hweight32(dev_priv->active_crtcs); | 3830 | *num_active = hweight32(dev_priv->active_crtcs); |
3781 | 3831 | ||
3782 | ddb_size = INTEL_INFO(dev_priv)->ddb_size; | 3832 | ddb_size = intel_get_ddb_size(dev_priv, cstate, total_data_rate, |
3783 | WARN_ON(ddb_size == 0); | 3833 | *num_active, ddb); |
3784 | |||
3785 | if (INTEL_GEN(dev_priv) < 11) | ||
3786 | ddb_size -= 4; /* 4 blocks for bypass path allocation */ | ||
3787 | 3834 | ||
3788 | /* | 3835 | /* |
3789 | * If the state doesn't change the active CRTC's, then there's | 3836 | * If the state doesn't change the active CRTC's, then there's |
@@ -3817,10 +3864,18 @@ static unsigned int skl_cursor_allocation(int num_active) | |||
3817 | return 8; | 3864 | return 8; |
3818 | } | 3865 | } |
3819 | 3866 | ||
3820 | static void skl_ddb_entry_init_from_hw(struct skl_ddb_entry *entry, u32 reg) | 3867 | static void skl_ddb_entry_init_from_hw(struct drm_i915_private *dev_priv, |
3868 | struct skl_ddb_entry *entry, u32 reg) | ||
3821 | { | 3869 | { |
3822 | entry->start = reg & 0x3ff; | 3870 | u16 mask; |
3823 | entry->end = (reg >> 16) & 0x3ff; | 3871 | |
3872 | if (INTEL_GEN(dev_priv) >= 11) | ||
3873 | mask = ICL_DDB_ENTRY_MASK; | ||
3874 | else | ||
3875 | mask = SKL_DDB_ENTRY_MASK; | ||
3876 | entry->start = reg & mask; | ||
3877 | entry->end = (reg >> DDB_ENTRY_END_SHIFT) & mask; | ||
3878 | |||
3824 | if (entry->end) | 3879 | if (entry->end) |
3825 | entry->end += 1; | 3880 | entry->end += 1; |
3826 | } | 3881 | } |
@@ -3837,7 +3892,8 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, | |||
3837 | /* Cursor doesn't support NV12/planar, so no extra calculation needed */ | 3892 | /* Cursor doesn't support NV12/planar, so no extra calculation needed */ |
3838 | if (plane_id == PLANE_CURSOR) { | 3893 | if (plane_id == PLANE_CURSOR) { |
3839 | val = I915_READ(CUR_BUF_CFG(pipe)); | 3894 | val = I915_READ(CUR_BUF_CFG(pipe)); |
3840 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val); | 3895 | skl_ddb_entry_init_from_hw(dev_priv, |
3896 | &ddb->plane[pipe][plane_id], val); | ||
3841 | return; | 3897 | return; |
3842 | } | 3898 | } |
3843 | 3899 | ||
@@ -3856,10 +3912,13 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, | |||
3856 | val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id)); | 3912 | val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id)); |
3857 | 3913 | ||
3858 | if (fourcc == DRM_FORMAT_NV12) { | 3914 | if (fourcc == DRM_FORMAT_NV12) { |
3859 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val2); | 3915 | skl_ddb_entry_init_from_hw(dev_priv, |
3860 | skl_ddb_entry_init_from_hw(&ddb->uv_plane[pipe][plane_id], val); | 3916 | &ddb->plane[pipe][plane_id], val2); |
3917 | skl_ddb_entry_init_from_hw(dev_priv, | ||
3918 | &ddb->uv_plane[pipe][plane_id], val); | ||
3861 | } else { | 3919 | } else { |
3862 | skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane_id], val); | 3920 | skl_ddb_entry_init_from_hw(dev_priv, |
3921 | &ddb->plane[pipe][plane_id], val); | ||
3863 | } | 3922 | } |
3864 | } | 3923 | } |
3865 | 3924 | ||
@@ -3870,6 +3929,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, | |||
3870 | 3929 | ||
3871 | memset(ddb, 0, sizeof(*ddb)); | 3930 | memset(ddb, 0, sizeof(*ddb)); |
3872 | 3931 | ||
3932 | ddb->enabled_slices = intel_enabled_dbuf_slices_num(dev_priv); | ||
3933 | |||
3873 | for_each_intel_crtc(&dev_priv->drm, crtc) { | 3934 | for_each_intel_crtc(&dev_priv->drm, crtc) { |
3874 | enum intel_display_power_domain power_domain; | 3935 | enum intel_display_power_domain power_domain; |
3875 | enum plane_id plane_id; | 3936 | enum plane_id plane_id; |
@@ -4242,7 +4303,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4242 | return 0; | 4303 | return 0; |
4243 | } | 4304 | } |
4244 | 4305 | ||
4245 | skl_ddb_get_pipe_allocation_limits(dev, cstate, alloc, &num_active); | 4306 | total_data_rate = skl_get_total_relative_data_rate(cstate, |
4307 | plane_data_rate, | ||
4308 | uv_plane_data_rate); | ||
4309 | skl_ddb_get_pipe_allocation_limits(dev, cstate, total_data_rate, ddb, | ||
4310 | alloc, &num_active); | ||
4246 | alloc_size = skl_ddb_entry_size(alloc); | 4311 | alloc_size = skl_ddb_entry_size(alloc); |
4247 | if (alloc_size == 0) | 4312 | if (alloc_size == 0) |
4248 | return 0; | 4313 | return 0; |
@@ -4277,9 +4342,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
4277 | * | 4342 | * |
4278 | * FIXME: we may not allocate every single block here. | 4343 | * FIXME: we may not allocate every single block here. |
4279 | */ | 4344 | */ |
4280 | total_data_rate = skl_get_total_relative_data_rate(cstate, | ||
4281 | plane_data_rate, | ||
4282 | uv_plane_data_rate); | ||
4283 | if (total_data_rate == 0) | 4345 | if (total_data_rate == 0) |
4284 | return 0; | 4346 | return 0; |
4285 | 4347 | ||
@@ -5088,6 +5150,7 @@ skl_copy_ddb_for_pipe(struct skl_ddb_values *dst, | |||
5088 | sizeof(dst->ddb.uv_plane[pipe])); | 5150 | sizeof(dst->ddb.uv_plane[pipe])); |
5089 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], | 5151 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], |
5090 | sizeof(dst->ddb.plane[pipe])); | 5152 | sizeof(dst->ddb.plane[pipe])); |
5153 | dst->ddb.enabled_slices = src->ddb.enabled_slices; | ||
5091 | } | 5154 | } |
5092 | 5155 | ||
5093 | static void | 5156 | static void |
@@ -5472,8 +5535,12 @@ void skl_wm_get_hw_state(struct drm_device *dev) | |||
5472 | /* Fully recompute DDB on first atomic commit */ | 5535 | /* Fully recompute DDB on first atomic commit */ |
5473 | dev_priv->wm.distrust_bios_wm = true; | 5536 | dev_priv->wm.distrust_bios_wm = true; |
5474 | } else { | 5537 | } else { |
5475 | /* Easy/common case; just sanitize DDB now if everything off */ | 5538 | /* |
5476 | memset(ddb, 0, sizeof(*ddb)); | 5539 | * Easy/common case; just sanitize DDB now if everything off |
5540 | * Keep dbuf slice info intact | ||
5541 | */ | ||
5542 | memset(ddb->plane, 0, sizeof(ddb->plane)); | ||
5543 | memset(ddb->uv_plane, 0, sizeof(ddb->uv_plane)); | ||
5477 | } | 5544 | } |
5478 | } | 5545 | } |
5479 | 5546 | ||
@@ -8597,6 +8664,13 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv, | |||
8597 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | 8664 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); |
8598 | } | 8665 | } |
8599 | 8666 | ||
8667 | static void icl_init_clock_gating(struct drm_i915_private *dev_priv) | ||
8668 | { | ||
8669 | /* This is not an Wa. Enable to reduce Sampler power */ | ||
8670 | I915_WRITE(GEN10_DFR_RATIO_EN_AND_CHICKEN, | ||
8671 | I915_READ(GEN10_DFR_RATIO_EN_AND_CHICKEN) & ~DFR_DISABLE); | ||
8672 | } | ||
8673 | |||
8600 | static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) | 8674 | static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) |
8601 | { | 8675 | { |
8602 | if (!HAS_PCH_CNP(dev_priv)) | 8676 | if (!HAS_PCH_CNP(dev_priv)) |
@@ -9123,7 +9197,9 @@ static void nop_init_clock_gating(struct drm_i915_private *dev_priv) | |||
9123 | */ | 9197 | */ |
9124 | void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) | 9198 | void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) |
9125 | { | 9199 | { |
9126 | if (IS_CANNONLAKE(dev_priv)) | 9200 | if (IS_ICELAKE(dev_priv)) |
9201 | dev_priv->display.init_clock_gating = icl_init_clock_gating; | ||
9202 | else if (IS_CANNONLAKE(dev_priv)) | ||
9127 | dev_priv->display.init_clock_gating = cnl_init_clock_gating; | 9203 | dev_priv->display.init_clock_gating = cnl_init_clock_gating; |
9128 | else if (IS_COFFEELAKE(dev_priv)) | 9204 | else if (IS_COFFEELAKE(dev_priv)) |
9129 | dev_priv->display.init_clock_gating = cfl_init_clock_gating; | 9205 | dev_priv->display.init_clock_gating = cfl_init_clock_gating; |
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 69a5b276f4d8..db27f2faa1de 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c | |||
@@ -93,6 +93,114 @@ static void psr_aux_io_power_put(struct intel_dp *intel_dp) | |||
93 | intel_display_power_put(dev_priv, psr_aux_domain(intel_dp)); | 93 | intel_display_power_put(dev_priv, psr_aux_domain(intel_dp)); |
94 | } | 94 | } |
95 | 95 | ||
96 | void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug) | ||
97 | { | ||
98 | u32 debug_mask, mask; | ||
99 | |||
100 | /* No PSR interrupts on VLV/CHV */ | ||
101 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) | ||
102 | return; | ||
103 | |||
104 | mask = EDP_PSR_ERROR(TRANSCODER_EDP); | ||
105 | debug_mask = EDP_PSR_POST_EXIT(TRANSCODER_EDP) | | ||
106 | EDP_PSR_PRE_ENTRY(TRANSCODER_EDP); | ||
107 | |||
108 | if (INTEL_GEN(dev_priv) >= 8) { | ||
109 | mask |= EDP_PSR_ERROR(TRANSCODER_A) | | ||
110 | EDP_PSR_ERROR(TRANSCODER_B) | | ||
111 | EDP_PSR_ERROR(TRANSCODER_C); | ||
112 | |||
113 | debug_mask |= EDP_PSR_POST_EXIT(TRANSCODER_A) | | ||
114 | EDP_PSR_PRE_ENTRY(TRANSCODER_A) | | ||
115 | EDP_PSR_POST_EXIT(TRANSCODER_B) | | ||
116 | EDP_PSR_PRE_ENTRY(TRANSCODER_B) | | ||
117 | EDP_PSR_POST_EXIT(TRANSCODER_C) | | ||
118 | EDP_PSR_PRE_ENTRY(TRANSCODER_C); | ||
119 | } | ||
120 | |||
121 | if (debug) | ||
122 | mask |= debug_mask; | ||
123 | |||
124 | WRITE_ONCE(dev_priv->psr.debug, debug); | ||
125 | I915_WRITE(EDP_PSR_IMR, ~mask); | ||
126 | } | ||
127 | |||
128 | static void psr_event_print(u32 val, bool psr2_enabled) | ||
129 | { | ||
130 | DRM_DEBUG_KMS("PSR exit events: 0x%x\n", val); | ||
131 | if (val & PSR_EVENT_PSR2_WD_TIMER_EXPIRE) | ||
132 | DRM_DEBUG_KMS("\tPSR2 watchdog timer expired\n"); | ||
133 | if ((val & PSR_EVENT_PSR2_DISABLED) && psr2_enabled) | ||
134 | DRM_DEBUG_KMS("\tPSR2 disabled\n"); | ||
135 | if (val & PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN) | ||
136 | DRM_DEBUG_KMS("\tSU dirty FIFO underrun\n"); | ||
137 | if (val & PSR_EVENT_SU_CRC_FIFO_UNDERRUN) | ||
138 | DRM_DEBUG_KMS("\tSU CRC FIFO underrun\n"); | ||
139 | if (val & PSR_EVENT_GRAPHICS_RESET) | ||
140 | DRM_DEBUG_KMS("\tGraphics reset\n"); | ||
141 | if (val & PSR_EVENT_PCH_INTERRUPT) | ||
142 | DRM_DEBUG_KMS("\tPCH interrupt\n"); | ||
143 | if (val & PSR_EVENT_MEMORY_UP) | ||
144 | DRM_DEBUG_KMS("\tMemory up\n"); | ||
145 | if (val & PSR_EVENT_FRONT_BUFFER_MODIFY) | ||
146 | DRM_DEBUG_KMS("\tFront buffer modification\n"); | ||
147 | if (val & PSR_EVENT_WD_TIMER_EXPIRE) | ||
148 | DRM_DEBUG_KMS("\tPSR watchdog timer expired\n"); | ||
149 | if (val & PSR_EVENT_PIPE_REGISTERS_UPDATE) | ||
150 | DRM_DEBUG_KMS("\tPIPE registers updated\n"); | ||
151 | if (val & PSR_EVENT_REGISTER_UPDATE) | ||
152 | DRM_DEBUG_KMS("\tRegister updated\n"); | ||
153 | if (val & PSR_EVENT_HDCP_ENABLE) | ||
154 | DRM_DEBUG_KMS("\tHDCP enabled\n"); | ||
155 | if (val & PSR_EVENT_KVMR_SESSION_ENABLE) | ||
156 | DRM_DEBUG_KMS("\tKVMR session enabled\n"); | ||
157 | if (val & PSR_EVENT_VBI_ENABLE) | ||
158 | DRM_DEBUG_KMS("\tVBI enabled\n"); | ||
159 | if (val & PSR_EVENT_LPSP_MODE_EXIT) | ||
160 | DRM_DEBUG_KMS("\tLPSP mode exited\n"); | ||
161 | if ((val & PSR_EVENT_PSR_DISABLE) && !psr2_enabled) | ||
162 | DRM_DEBUG_KMS("\tPSR disabled\n"); | ||
163 | } | ||
164 | |||
165 | void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir) | ||
166 | { | ||
167 | u32 transcoders = BIT(TRANSCODER_EDP); | ||
168 | enum transcoder cpu_transcoder; | ||
169 | ktime_t time_ns = ktime_get(); | ||
170 | |||
171 | if (INTEL_GEN(dev_priv) >= 8) | ||
172 | transcoders |= BIT(TRANSCODER_A) | | ||
173 | BIT(TRANSCODER_B) | | ||
174 | BIT(TRANSCODER_C); | ||
175 | |||
176 | for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) { | ||
177 | /* FIXME: Exit PSR and link train manually when this happens. */ | ||
178 | if (psr_iir & EDP_PSR_ERROR(cpu_transcoder)) | ||
179 | DRM_DEBUG_KMS("[transcoder %s] PSR aux error\n", | ||
180 | transcoder_name(cpu_transcoder)); | ||
181 | |||
182 | if (psr_iir & EDP_PSR_PRE_ENTRY(cpu_transcoder)) { | ||
183 | dev_priv->psr.last_entry_attempt = time_ns; | ||
184 | DRM_DEBUG_KMS("[transcoder %s] PSR entry attempt in 2 vblanks\n", | ||
185 | transcoder_name(cpu_transcoder)); | ||
186 | } | ||
187 | |||
188 | if (psr_iir & EDP_PSR_POST_EXIT(cpu_transcoder)) { | ||
189 | dev_priv->psr.last_exit = time_ns; | ||
190 | DRM_DEBUG_KMS("[transcoder %s] PSR exit completed\n", | ||
191 | transcoder_name(cpu_transcoder)); | ||
192 | |||
193 | if (INTEL_GEN(dev_priv) >= 9) { | ||
194 | u32 val = I915_READ(PSR_EVENT(cpu_transcoder)); | ||
195 | bool psr2_enabled = dev_priv->psr.psr2_enabled; | ||
196 | |||
197 | I915_WRITE(PSR_EVENT(cpu_transcoder), val); | ||
198 | psr_event_print(val, psr2_enabled); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | |||
96 | static bool intel_dp_get_y_coord_required(struct intel_dp *intel_dp) | 204 | static bool intel_dp_get_y_coord_required(struct intel_dp *intel_dp) |
97 | { | 205 | { |
98 | uint8_t psr_caps = 0; | 206 | uint8_t psr_caps = 0; |
@@ -400,9 +508,8 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) | |||
400 | * mesh at all with our frontbuffer tracking. And the hw alone isn't | 508 | * mesh at all with our frontbuffer tracking. And the hw alone isn't |
401 | * good enough. */ | 509 | * good enough. */ |
402 | val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; | 510 | val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; |
403 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { | 511 | if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) |
404 | val |= EDP_Y_COORDINATE_VALID | EDP_Y_COORDINATE_ENABLE; | 512 | val |= EDP_Y_COORDINATE_ENABLE; |
405 | } | ||
406 | 513 | ||
407 | val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); | 514 | val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); |
408 | 515 | ||
@@ -604,7 +711,8 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp, | |||
604 | I915_WRITE(EDP_PSR_DEBUG, | 711 | I915_WRITE(EDP_PSR_DEBUG, |
605 | EDP_PSR_DEBUG_MASK_MEMUP | | 712 | EDP_PSR_DEBUG_MASK_MEMUP | |
606 | EDP_PSR_DEBUG_MASK_HPD | | 713 | EDP_PSR_DEBUG_MASK_HPD | |
607 | EDP_PSR_DEBUG_MASK_LPSP); | 714 | EDP_PSR_DEBUG_MASK_LPSP | |
715 | EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); | ||
608 | } | 716 | } |
609 | } | 717 | } |
610 | 718 | ||
@@ -1065,9 +1173,12 @@ void intel_psr_init(struct drm_i915_private *dev_priv) | |||
1065 | if (!dev_priv->psr.sink_support) | 1173 | if (!dev_priv->psr.sink_support) |
1066 | return; | 1174 | return; |
1067 | 1175 | ||
1068 | /* Per platform default: all disabled. */ | 1176 | if (i915_modparams.enable_psr == -1) { |
1069 | if (i915_modparams.enable_psr == -1) | 1177 | i915_modparams.enable_psr = dev_priv->vbt.psr.enable; |
1178 | |||
1179 | /* Per platform default: all disabled. */ | ||
1070 | i915_modparams.enable_psr = 0; | 1180 | i915_modparams.enable_psr = 0; |
1181 | } | ||
1071 | 1182 | ||
1072 | /* Set link_standby x link_off defaults */ | 1183 | /* Set link_standby x link_off defaults */ |
1073 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | 1184 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 757bb0990c07..8f19349a6055 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -558,7 +558,8 @@ static void reset_ring_common(struct intel_engine_cs *engine, | |||
558 | */ | 558 | */ |
559 | if (request) { | 559 | if (request) { |
560 | struct drm_i915_private *dev_priv = request->i915; | 560 | struct drm_i915_private *dev_priv = request->i915; |
561 | struct intel_context *ce = &request->ctx->engine[engine->id]; | 561 | struct intel_context *ce = to_intel_context(request->ctx, |
562 | engine); | ||
562 | struct i915_hw_ppgtt *ppgtt; | 563 | struct i915_hw_ppgtt *ppgtt; |
563 | 564 | ||
564 | if (ce->state) { | 565 | if (ce->state) { |
@@ -618,9 +619,7 @@ static int init_render_ring(struct intel_engine_cs *engine) | |||
618 | if (ret) | 619 | if (ret) |
619 | return ret; | 620 | return ret; |
620 | 621 | ||
621 | ret = intel_whitelist_workarounds_apply(engine); | 622 | intel_whitelist_workarounds_apply(engine); |
622 | if (ret) | ||
623 | return ret; | ||
624 | 623 | ||
625 | /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ | 624 | /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ |
626 | if (IS_GEN(dev_priv, 4, 6)) | 625 | if (IS_GEN(dev_priv, 4, 6)) |
@@ -698,17 +697,17 @@ static void cancel_requests(struct intel_engine_cs *engine) | |||
698 | struct i915_request *request; | 697 | struct i915_request *request; |
699 | unsigned long flags; | 698 | unsigned long flags; |
700 | 699 | ||
701 | spin_lock_irqsave(&engine->timeline->lock, flags); | 700 | spin_lock_irqsave(&engine->timeline.lock, flags); |
702 | 701 | ||
703 | /* Mark all submitted requests as skipped. */ | 702 | /* Mark all submitted requests as skipped. */ |
704 | list_for_each_entry(request, &engine->timeline->requests, link) { | 703 | list_for_each_entry(request, &engine->timeline.requests, link) { |
705 | GEM_BUG_ON(!request->global_seqno); | 704 | GEM_BUG_ON(!request->global_seqno); |
706 | if (!i915_request_completed(request)) | 705 | if (!i915_request_completed(request)) |
707 | dma_fence_set_error(&request->fence, -EIO); | 706 | dma_fence_set_error(&request->fence, -EIO); |
708 | } | 707 | } |
709 | /* Remaining _unready_ requests will be nop'ed when submitted */ | 708 | /* Remaining _unready_ requests will be nop'ed when submitted */ |
710 | 709 | ||
711 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 710 | spin_unlock_irqrestore(&engine->timeline.lock, flags); |
712 | } | 711 | } |
713 | 712 | ||
714 | static void i9xx_submit_request(struct i915_request *request) | 713 | static void i9xx_submit_request(struct i915_request *request) |
@@ -1067,7 +1066,6 @@ err: | |||
1067 | 1066 | ||
1068 | void intel_ring_reset(struct intel_ring *ring, u32 tail) | 1067 | void intel_ring_reset(struct intel_ring *ring, u32 tail) |
1069 | { | 1068 | { |
1070 | GEM_BUG_ON(!list_empty(&ring->request_list)); | ||
1071 | ring->tail = tail; | 1069 | ring->tail = tail; |
1072 | ring->head = tail; | 1070 | ring->head = tail; |
1073 | ring->emit = tail; | 1071 | ring->emit = tail; |
@@ -1119,19 +1117,24 @@ err: | |||
1119 | } | 1117 | } |
1120 | 1118 | ||
1121 | struct intel_ring * | 1119 | struct intel_ring * |
1122 | intel_engine_create_ring(struct intel_engine_cs *engine, int size) | 1120 | intel_engine_create_ring(struct intel_engine_cs *engine, |
1121 | struct i915_timeline *timeline, | ||
1122 | int size) | ||
1123 | { | 1123 | { |
1124 | struct intel_ring *ring; | 1124 | struct intel_ring *ring; |
1125 | struct i915_vma *vma; | 1125 | struct i915_vma *vma; |
1126 | 1126 | ||
1127 | GEM_BUG_ON(!is_power_of_2(size)); | 1127 | GEM_BUG_ON(!is_power_of_2(size)); |
1128 | GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); | 1128 | GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); |
1129 | GEM_BUG_ON(timeline == &engine->timeline); | ||
1130 | lockdep_assert_held(&engine->i915->drm.struct_mutex); | ||
1129 | 1131 | ||
1130 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 1132 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
1131 | if (!ring) | 1133 | if (!ring) |
1132 | return ERR_PTR(-ENOMEM); | 1134 | return ERR_PTR(-ENOMEM); |
1133 | 1135 | ||
1134 | INIT_LIST_HEAD(&ring->request_list); | 1136 | INIT_LIST_HEAD(&ring->request_list); |
1137 | ring->timeline = i915_timeline_get(timeline); | ||
1135 | 1138 | ||
1136 | ring->size = size; | 1139 | ring->size = size; |
1137 | /* Workaround an erratum on the i830 which causes a hang if | 1140 | /* Workaround an erratum on the i830 which causes a hang if |
@@ -1162,12 +1165,13 @@ intel_ring_free(struct intel_ring *ring) | |||
1162 | i915_vma_close(ring->vma); | 1165 | i915_vma_close(ring->vma); |
1163 | __i915_gem_object_release_unless_active(obj); | 1166 | __i915_gem_object_release_unless_active(obj); |
1164 | 1167 | ||
1168 | i915_timeline_put(ring->timeline); | ||
1165 | kfree(ring); | 1169 | kfree(ring); |
1166 | } | 1170 | } |
1167 | 1171 | ||
1168 | static int context_pin(struct i915_gem_context *ctx) | 1172 | static int context_pin(struct intel_context *ce) |
1169 | { | 1173 | { |
1170 | struct i915_vma *vma = ctx->engine[RCS].state; | 1174 | struct i915_vma *vma = ce->state; |
1171 | int ret; | 1175 | int ret; |
1172 | 1176 | ||
1173 | /* | 1177 | /* |
@@ -1258,7 +1262,7 @@ static struct intel_ring * | |||
1258 | intel_ring_context_pin(struct intel_engine_cs *engine, | 1262 | intel_ring_context_pin(struct intel_engine_cs *engine, |
1259 | struct i915_gem_context *ctx) | 1263 | struct i915_gem_context *ctx) |
1260 | { | 1264 | { |
1261 | struct intel_context *ce = &ctx->engine[engine->id]; | 1265 | struct intel_context *ce = to_intel_context(ctx, engine); |
1262 | int ret; | 1266 | int ret; |
1263 | 1267 | ||
1264 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); | 1268 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); |
@@ -1280,7 +1284,7 @@ intel_ring_context_pin(struct intel_engine_cs *engine, | |||
1280 | } | 1284 | } |
1281 | 1285 | ||
1282 | if (ce->state) { | 1286 | if (ce->state) { |
1283 | ret = context_pin(ctx); | 1287 | ret = context_pin(ce); |
1284 | if (ret) | 1288 | if (ret) |
1285 | goto err; | 1289 | goto err; |
1286 | 1290 | ||
@@ -1301,7 +1305,7 @@ err: | |||
1301 | static void intel_ring_context_unpin(struct intel_engine_cs *engine, | 1305 | static void intel_ring_context_unpin(struct intel_engine_cs *engine, |
1302 | struct i915_gem_context *ctx) | 1306 | struct i915_gem_context *ctx) |
1303 | { | 1307 | { |
1304 | struct intel_context *ce = &ctx->engine[engine->id]; | 1308 | struct intel_context *ce = to_intel_context(ctx, engine); |
1305 | 1309 | ||
1306 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); | 1310 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); |
1307 | GEM_BUG_ON(ce->pin_count == 0); | 1311 | GEM_BUG_ON(ce->pin_count == 0); |
@@ -1320,6 +1324,7 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine, | |||
1320 | static int intel_init_ring_buffer(struct intel_engine_cs *engine) | 1324 | static int intel_init_ring_buffer(struct intel_engine_cs *engine) |
1321 | { | 1325 | { |
1322 | struct intel_ring *ring; | 1326 | struct intel_ring *ring; |
1327 | struct i915_timeline *timeline; | ||
1323 | int err; | 1328 | int err; |
1324 | 1329 | ||
1325 | intel_engine_setup_common(engine); | 1330 | intel_engine_setup_common(engine); |
@@ -1328,7 +1333,14 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) | |||
1328 | if (err) | 1333 | if (err) |
1329 | goto err; | 1334 | goto err; |
1330 | 1335 | ||
1331 | ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); | 1336 | timeline = i915_timeline_create(engine->i915, engine->name); |
1337 | if (IS_ERR(timeline)) { | ||
1338 | err = PTR_ERR(timeline); | ||
1339 | goto err; | ||
1340 | } | ||
1341 | |||
1342 | ring = intel_engine_create_ring(engine, timeline, 32 * PAGE_SIZE); | ||
1343 | i915_timeline_put(timeline); | ||
1332 | if (IS_ERR(ring)) { | 1344 | if (IS_ERR(ring)) { |
1333 | err = PTR_ERR(ring); | 1345 | err = PTR_ERR(ring); |
1334 | goto err; | 1346 | goto err; |
@@ -1429,7 +1441,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags) | |||
1429 | 1441 | ||
1430 | *cs++ = MI_NOOP; | 1442 | *cs++ = MI_NOOP; |
1431 | *cs++ = MI_SET_CONTEXT; | 1443 | *cs++ = MI_SET_CONTEXT; |
1432 | *cs++ = i915_ggtt_offset(rq->ctx->engine[RCS].state) | flags; | 1444 | *cs++ = i915_ggtt_offset(to_intel_context(rq->ctx, engine)->state) | flags; |
1433 | /* | 1445 | /* |
1434 | * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP | 1446 | * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP |
1435 | * WaMiSetContext_Hang:snb,ivb,vlv | 1447 | * WaMiSetContext_Hang:snb,ivb,vlv |
@@ -1520,7 +1532,7 @@ static int switch_context(struct i915_request *rq) | |||
1520 | hw_flags = MI_FORCE_RESTORE; | 1532 | hw_flags = MI_FORCE_RESTORE; |
1521 | } | 1533 | } |
1522 | 1534 | ||
1523 | if (to_ctx->engine[engine->id].state && | 1535 | if (to_intel_context(to_ctx, engine)->state && |
1524 | (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) { | 1536 | (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) { |
1525 | GEM_BUG_ON(engine->id != RCS); | 1537 | GEM_BUG_ON(engine->id != RCS); |
1526 | 1538 | ||
@@ -1568,7 +1580,7 @@ static int ring_request_alloc(struct i915_request *request) | |||
1568 | { | 1580 | { |
1569 | int ret; | 1581 | int ret; |
1570 | 1582 | ||
1571 | GEM_BUG_ON(!request->ctx->engine[request->engine->id].pin_count); | 1583 | GEM_BUG_ON(!to_intel_context(request->ctx, request->engine)->pin_count); |
1572 | 1584 | ||
1573 | /* Flush enough space to reduce the likelihood of waiting after | 1585 | /* Flush enough space to reduce the likelihood of waiting after |
1574 | * we start building the request - in which case we will just | 1586 | * we start building the request - in which case we will just |
@@ -1719,22 +1731,24 @@ u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords) | |||
1719 | /* Align the ring tail to a cacheline boundary */ | 1731 | /* Align the ring tail to a cacheline boundary */ |
1720 | int intel_ring_cacheline_align(struct i915_request *rq) | 1732 | int intel_ring_cacheline_align(struct i915_request *rq) |
1721 | { | 1733 | { |
1722 | int num_dwords = (rq->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(u32); | 1734 | int num_dwords; |
1723 | u32 *cs; | 1735 | void *cs; |
1724 | 1736 | ||
1737 | num_dwords = (rq->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(u32); | ||
1725 | if (num_dwords == 0) | 1738 | if (num_dwords == 0) |
1726 | return 0; | 1739 | return 0; |
1727 | 1740 | ||
1728 | num_dwords = CACHELINE_BYTES / sizeof(u32) - num_dwords; | 1741 | num_dwords = CACHELINE_DWORDS - num_dwords; |
1742 | GEM_BUG_ON(num_dwords & 1); | ||
1743 | |||
1729 | cs = intel_ring_begin(rq, num_dwords); | 1744 | cs = intel_ring_begin(rq, num_dwords); |
1730 | if (IS_ERR(cs)) | 1745 | if (IS_ERR(cs)) |
1731 | return PTR_ERR(cs); | 1746 | return PTR_ERR(cs); |
1732 | 1747 | ||
1733 | while (num_dwords--) | 1748 | memset64(cs, (u64)MI_NOOP << 32 | MI_NOOP, num_dwords / 2); |
1734 | *cs++ = MI_NOOP; | ||
1735 | |||
1736 | intel_ring_advance(rq, cs); | 1749 | intel_ring_advance(rq, cs); |
1737 | 1750 | ||
1751 | GEM_BUG_ON(rq->ring->emit & (CACHELINE_BYTES - 1)); | ||
1738 | return 0; | 1752 | return 0; |
1739 | } | 1753 | } |
1740 | 1754 | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 717041640135..010750e8ee44 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -3,17 +3,19 @@ | |||
3 | #define _INTEL_RINGBUFFER_H_ | 3 | #define _INTEL_RINGBUFFER_H_ |
4 | 4 | ||
5 | #include <linux/hashtable.h> | 5 | #include <linux/hashtable.h> |
6 | #include <linux/seqlock.h> | ||
6 | 7 | ||
7 | #include "i915_gem_batch_pool.h" | 8 | #include "i915_gem_batch_pool.h" |
8 | #include "i915_gem_timeline.h" | ||
9 | 9 | ||
10 | #include "i915_reg.h" | 10 | #include "i915_reg.h" |
11 | #include "i915_pmu.h" | 11 | #include "i915_pmu.h" |
12 | #include "i915_request.h" | 12 | #include "i915_request.h" |
13 | #include "i915_selftest.h" | 13 | #include "i915_selftest.h" |
14 | #include "i915_timeline.h" | ||
14 | #include "intel_gpu_commands.h" | 15 | #include "intel_gpu_commands.h" |
15 | 16 | ||
16 | struct drm_printer; | 17 | struct drm_printer; |
18 | struct i915_sched_attr; | ||
17 | 19 | ||
18 | #define I915_CMD_HASH_ORDER 9 | 20 | #define I915_CMD_HASH_ORDER 9 |
19 | 21 | ||
@@ -127,7 +129,9 @@ struct intel_ring { | |||
127 | struct i915_vma *vma; | 129 | struct i915_vma *vma; |
128 | void *vaddr; | 130 | void *vaddr; |
129 | 131 | ||
132 | struct i915_timeline *timeline; | ||
130 | struct list_head request_list; | 133 | struct list_head request_list; |
134 | struct list_head active_link; | ||
131 | 135 | ||
132 | u32 head; | 136 | u32 head; |
133 | u32 tail; | 137 | u32 tail; |
@@ -334,7 +338,8 @@ struct intel_engine_cs { | |||
334 | u32 mmio_base; | 338 | u32 mmio_base; |
335 | 339 | ||
336 | struct intel_ring *buffer; | 340 | struct intel_ring *buffer; |
337 | struct intel_timeline *timeline; | 341 | |
342 | struct i915_timeline timeline; | ||
338 | 343 | ||
339 | struct drm_i915_gem_object *default_state; | 344 | struct drm_i915_gem_object *default_state; |
340 | 345 | ||
@@ -460,7 +465,8 @@ struct intel_engine_cs { | |||
460 | * | 465 | * |
461 | * Called under the struct_mutex. | 466 | * Called under the struct_mutex. |
462 | */ | 467 | */ |
463 | void (*schedule)(struct i915_request *request, int priority); | 468 | void (*schedule)(struct i915_request *request, |
469 | const struct i915_sched_attr *attr); | ||
464 | 470 | ||
465 | /* | 471 | /* |
466 | * Cancel all requests on the hardware, or queued for execution. | 472 | * Cancel all requests on the hardware, or queued for execution. |
@@ -593,7 +599,7 @@ struct intel_engine_cs { | |||
593 | /** | 599 | /** |
594 | * @lock: Lock protecting the below fields. | 600 | * @lock: Lock protecting the below fields. |
595 | */ | 601 | */ |
596 | spinlock_t lock; | 602 | seqlock_t lock; |
597 | /** | 603 | /** |
598 | * @enabled: Reference count indicating number of listeners. | 604 | * @enabled: Reference count indicating number of listeners. |
599 | */ | 605 | */ |
@@ -764,7 +770,9 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) | |||
764 | #define CNL_HWS_CSB_WRITE_INDEX 0x2f | 770 | #define CNL_HWS_CSB_WRITE_INDEX 0x2f |
765 | 771 | ||
766 | struct intel_ring * | 772 | struct intel_ring * |
767 | intel_engine_create_ring(struct intel_engine_cs *engine, int size); | 773 | intel_engine_create_ring(struct intel_engine_cs *engine, |
774 | struct i915_timeline *timeline, | ||
775 | int size); | ||
768 | int intel_ring_pin(struct intel_ring *ring, | 776 | int intel_ring_pin(struct intel_ring *ring, |
769 | struct drm_i915_private *i915, | 777 | struct drm_i915_private *i915, |
770 | unsigned int offset_bias); | 778 | unsigned int offset_bias); |
@@ -882,7 +890,7 @@ static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine) | |||
882 | * wtih serialising this hint with anything, so document it as | 890 | * wtih serialising this hint with anything, so document it as |
883 | * a hint and nothing more. | 891 | * a hint and nothing more. |
884 | */ | 892 | */ |
885 | return READ_ONCE(engine->timeline->seqno); | 893 | return READ_ONCE(engine->timeline.seqno); |
886 | } | 894 | } |
887 | 895 | ||
888 | void intel_engine_get_instdone(struct intel_engine_cs *engine, | 896 | void intel_engine_get_instdone(struct intel_engine_cs *engine, |
@@ -1062,7 +1070,7 @@ static inline void intel_engine_context_in(struct intel_engine_cs *engine) | |||
1062 | if (READ_ONCE(engine->stats.enabled) == 0) | 1070 | if (READ_ONCE(engine->stats.enabled) == 0) |
1063 | return; | 1071 | return; |
1064 | 1072 | ||
1065 | spin_lock_irqsave(&engine->stats.lock, flags); | 1073 | write_seqlock_irqsave(&engine->stats.lock, flags); |
1066 | 1074 | ||
1067 | if (engine->stats.enabled > 0) { | 1075 | if (engine->stats.enabled > 0) { |
1068 | if (engine->stats.active++ == 0) | 1076 | if (engine->stats.active++ == 0) |
@@ -1070,7 +1078,7 @@ static inline void intel_engine_context_in(struct intel_engine_cs *engine) | |||
1070 | GEM_BUG_ON(engine->stats.active == 0); | 1078 | GEM_BUG_ON(engine->stats.active == 0); |
1071 | } | 1079 | } |
1072 | 1080 | ||
1073 | spin_unlock_irqrestore(&engine->stats.lock, flags); | 1081 | write_sequnlock_irqrestore(&engine->stats.lock, flags); |
1074 | } | 1082 | } |
1075 | 1083 | ||
1076 | static inline void intel_engine_context_out(struct intel_engine_cs *engine) | 1084 | static inline void intel_engine_context_out(struct intel_engine_cs *engine) |
@@ -1080,7 +1088,7 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine) | |||
1080 | if (READ_ONCE(engine->stats.enabled) == 0) | 1088 | if (READ_ONCE(engine->stats.enabled) == 0) |
1081 | return; | 1089 | return; |
1082 | 1090 | ||
1083 | spin_lock_irqsave(&engine->stats.lock, flags); | 1091 | write_seqlock_irqsave(&engine->stats.lock, flags); |
1084 | 1092 | ||
1085 | if (engine->stats.enabled > 0) { | 1093 | if (engine->stats.enabled > 0) { |
1086 | ktime_t last; | 1094 | ktime_t last; |
@@ -1107,7 +1115,7 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine) | |||
1107 | } | 1115 | } |
1108 | } | 1116 | } |
1109 | 1117 | ||
1110 | spin_unlock_irqrestore(&engine->stats.lock, flags); | 1118 | write_sequnlock_irqrestore(&engine->stats.lock, flags); |
1111 | } | 1119 | } |
1112 | 1120 | ||
1113 | int intel_enable_engine_stats(struct intel_engine_cs *engine); | 1121 | int intel_enable_engine_stats(struct intel_engine_cs *engine); |
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 66de4b2dc8b7..53a6eaa9671a 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c | |||
@@ -542,6 +542,29 @@ void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv) | |||
542 | dev_priv->csr.dc_state = val; | 542 | dev_priv->csr.dc_state = val; |
543 | } | 543 | } |
544 | 544 | ||
545 | /** | ||
546 | * gen9_set_dc_state - set target display C power state | ||
547 | * @dev_priv: i915 device instance | ||
548 | * @state: target DC power state | ||
549 | * - DC_STATE_DISABLE | ||
550 | * - DC_STATE_EN_UPTO_DC5 | ||
551 | * - DC_STATE_EN_UPTO_DC6 | ||
552 | * - DC_STATE_EN_DC9 | ||
553 | * | ||
554 | * Signal to DMC firmware/HW the target DC power state passed in @state. | ||
555 | * DMC/HW can turn off individual display clocks and power rails when entering | ||
556 | * a deeper DC power state (higher in number) and turns these back when exiting | ||
557 | * that state to a shallower power state (lower in number). The HW will decide | ||
558 | * when to actually enter a given state on an on-demand basis, for instance | ||
559 | * depending on the active state of display pipes. The state of display | ||
560 | * registers backed by affected power rails are saved/restored as needed. | ||
561 | * | ||
562 | * Based on the above enabling a deeper DC power state is asynchronous wrt. | ||
563 | * enabling it. Disabling a deeper power state is synchronous: for instance | ||
564 | * setting %DC_STATE_DISABLE won't complete until all HW resources are turned | ||
565 | * back on and register state is restored. This is guaranteed by the MMIO write | ||
566 | * to DC_STATE_EN blocking until the state is restored. | ||
567 | */ | ||
545 | static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state) | 568 | static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state) |
546 | { | 569 | { |
547 | uint32_t val; | 570 | uint32_t val; |
@@ -635,7 +658,7 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) | |||
635 | assert_csr_loaded(dev_priv); | 658 | assert_csr_loaded(dev_priv); |
636 | } | 659 | } |
637 | 660 | ||
638 | void skl_enable_dc6(struct drm_i915_private *dev_priv) | 661 | static void skl_enable_dc6(struct drm_i915_private *dev_priv) |
639 | { | 662 | { |
640 | assert_can_enable_dc6(dev_priv); | 663 | assert_can_enable_dc6(dev_priv); |
641 | 664 | ||
@@ -649,13 +672,6 @@ void skl_enable_dc6(struct drm_i915_private *dev_priv) | |||
649 | gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); | 672 | gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); |
650 | } | 673 | } |
651 | 674 | ||
652 | void skl_disable_dc6(struct drm_i915_private *dev_priv) | ||
653 | { | ||
654 | DRM_DEBUG_KMS("Disabling DC6\n"); | ||
655 | |||
656 | gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); | ||
657 | } | ||
658 | |||
659 | static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, | 675 | static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, |
660 | struct i915_power_well *power_well) | 676 | struct i915_power_well *power_well) |
661 | { | 677 | { |
@@ -2626,32 +2642,69 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv) | |||
2626 | mutex_unlock(&power_domains->lock); | 2642 | mutex_unlock(&power_domains->lock); |
2627 | } | 2643 | } |
2628 | 2644 | ||
2629 | static void gen9_dbuf_enable(struct drm_i915_private *dev_priv) | 2645 | static inline |
2646 | bool intel_dbuf_slice_set(struct drm_i915_private *dev_priv, | ||
2647 | i915_reg_t reg, bool enable) | ||
2630 | { | 2648 | { |
2631 | I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST); | 2649 | u32 val, status; |
2632 | POSTING_READ(DBUF_CTL); | ||
2633 | 2650 | ||
2651 | val = I915_READ(reg); | ||
2652 | val = enable ? (val | DBUF_POWER_REQUEST) : (val & ~DBUF_POWER_REQUEST); | ||
2653 | I915_WRITE(reg, val); | ||
2654 | POSTING_READ(reg); | ||
2634 | udelay(10); | 2655 | udelay(10); |
2635 | 2656 | ||
2636 | if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE)) | 2657 | status = I915_READ(reg) & DBUF_POWER_STATE; |
2637 | DRM_ERROR("DBuf power enable timeout\n"); | 2658 | if ((enable && !status) || (!enable && status)) { |
2659 | DRM_ERROR("DBus power %s timeout!\n", | ||
2660 | enable ? "enable" : "disable"); | ||
2661 | return false; | ||
2662 | } | ||
2663 | return true; | ||
2664 | } | ||
2665 | |||
2666 | static void gen9_dbuf_enable(struct drm_i915_private *dev_priv) | ||
2667 | { | ||
2668 | intel_dbuf_slice_set(dev_priv, DBUF_CTL, true); | ||
2638 | } | 2669 | } |
2639 | 2670 | ||
2640 | static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) | 2671 | static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) |
2641 | { | 2672 | { |
2642 | I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST); | 2673 | intel_dbuf_slice_set(dev_priv, DBUF_CTL, false); |
2643 | POSTING_READ(DBUF_CTL); | 2674 | } |
2644 | 2675 | ||
2645 | udelay(10); | 2676 | static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv) |
2677 | { | ||
2678 | if (INTEL_GEN(dev_priv) < 11) | ||
2679 | return 1; | ||
2680 | return 2; | ||
2681 | } | ||
2646 | 2682 | ||
2647 | if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE) | 2683 | void icl_dbuf_slices_update(struct drm_i915_private *dev_priv, |
2648 | DRM_ERROR("DBuf power disable timeout!\n"); | 2684 | u8 req_slices) |
2685 | { | ||
2686 | u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices; | ||
2687 | u32 val; | ||
2688 | bool ret; | ||
2689 | |||
2690 | if (req_slices > intel_dbuf_max_slices(dev_priv)) { | ||
2691 | DRM_ERROR("Invalid number of dbuf slices requested\n"); | ||
2692 | return; | ||
2693 | } | ||
2694 | |||
2695 | if (req_slices == hw_enabled_slices || req_slices == 0) | ||
2696 | return; | ||
2697 | |||
2698 | val = I915_READ(DBUF_CTL_S2); | ||
2699 | if (req_slices > hw_enabled_slices) | ||
2700 | ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true); | ||
2701 | else | ||
2702 | ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false); | ||
2703 | |||
2704 | if (ret) | ||
2705 | dev_priv->wm.skl_hw.ddb.enabled_slices = req_slices; | ||
2649 | } | 2706 | } |
2650 | 2707 | ||
2651 | /* | ||
2652 | * TODO: we shouldn't always enable DBUF_CTL_S2, we should only enable it when | ||
2653 | * needed and keep it disabled as much as possible. | ||
2654 | */ | ||
2655 | static void icl_dbuf_enable(struct drm_i915_private *dev_priv) | 2708 | static void icl_dbuf_enable(struct drm_i915_private *dev_priv) |
2656 | { | 2709 | { |
2657 | I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST); | 2710 | I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST); |
@@ -2663,6 +2716,8 @@ static void icl_dbuf_enable(struct drm_i915_private *dev_priv) | |||
2663 | if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || | 2716 | if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || |
2664 | !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) | 2717 | !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) |
2665 | DRM_ERROR("DBuf power enable timeout\n"); | 2718 | DRM_ERROR("DBuf power enable timeout\n"); |
2719 | else | ||
2720 | dev_priv->wm.skl_hw.ddb.enabled_slices = 2; | ||
2666 | } | 2721 | } |
2667 | 2722 | ||
2668 | static void icl_dbuf_disable(struct drm_i915_private *dev_priv) | 2723 | static void icl_dbuf_disable(struct drm_i915_private *dev_priv) |
@@ -2676,6 +2731,8 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv) | |||
2676 | if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || | 2731 | if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || |
2677 | (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) | 2732 | (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) |
2678 | DRM_ERROR("DBuf power disable timeout!\n"); | 2733 | DRM_ERROR("DBuf power disable timeout!\n"); |
2734 | else | ||
2735 | dev_priv->wm.skl_hw.ddb.enabled_slices = 0; | ||
2679 | } | 2736 | } |
2680 | 2737 | ||
2681 | static void icl_mbus_init(struct drm_i915_private *dev_priv) | 2738 | static void icl_mbus_init(struct drm_i915_private *dev_priv) |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 970015dcc6f1..ee23613f9fd4 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -131,7 +131,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) | |||
131 | if (scanline < min || scanline > max) | 131 | if (scanline < min || scanline > max) |
132 | break; | 132 | break; |
133 | 133 | ||
134 | if (timeout <= 0) { | 134 | if (!timeout) { |
135 | DRM_ERROR("Potential atomic update failure on pipe %c\n", | 135 | DRM_ERROR("Potential atomic update failure on pipe %c\n", |
136 | pipe_name(crtc->pipe)); | 136 | pipe_name(crtc->pipe)); |
137 | break; | 137 | break; |
@@ -1011,6 +1011,7 @@ intel_check_sprite_plane(struct intel_plane *plane, | |||
1011 | src->y2 = (src_y + src_h) << 16; | 1011 | src->y2 = (src_y + src_h) << 16; |
1012 | 1012 | ||
1013 | if (intel_format_is_yuv(fb->format->format) && | 1013 | if (intel_format_is_yuv(fb->format->format) && |
1014 | fb->format->format != DRM_FORMAT_NV12 && | ||
1014 | (src_x % 2 || src_w % 2)) { | 1015 | (src_x % 2 || src_w % 2)) { |
1015 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", | 1016 | DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", |
1016 | src_x, src_w); | 1017 | src_x, src_w); |
@@ -1179,6 +1180,19 @@ static uint32_t skl_plane_formats[] = { | |||
1179 | DRM_FORMAT_VYUY, | 1180 | DRM_FORMAT_VYUY, |
1180 | }; | 1181 | }; |
1181 | 1182 | ||
1183 | static uint32_t skl_planar_formats[] = { | ||
1184 | DRM_FORMAT_RGB565, | ||
1185 | DRM_FORMAT_ABGR8888, | ||
1186 | DRM_FORMAT_ARGB8888, | ||
1187 | DRM_FORMAT_XBGR8888, | ||
1188 | DRM_FORMAT_XRGB8888, | ||
1189 | DRM_FORMAT_YUYV, | ||
1190 | DRM_FORMAT_YVYU, | ||
1191 | DRM_FORMAT_UYVY, | ||
1192 | DRM_FORMAT_VYUY, | ||
1193 | DRM_FORMAT_NV12, | ||
1194 | }; | ||
1195 | |||
1182 | static const uint64_t skl_plane_format_modifiers_noccs[] = { | 1196 | static const uint64_t skl_plane_format_modifiers_noccs[] = { |
1183 | I915_FORMAT_MOD_Yf_TILED, | 1197 | I915_FORMAT_MOD_Yf_TILED, |
1184 | I915_FORMAT_MOD_Y_TILED, | 1198 | I915_FORMAT_MOD_Y_TILED, |
@@ -1273,6 +1287,7 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier) | |||
1273 | case DRM_FORMAT_YVYU: | 1287 | case DRM_FORMAT_YVYU: |
1274 | case DRM_FORMAT_UYVY: | 1288 | case DRM_FORMAT_UYVY: |
1275 | case DRM_FORMAT_VYUY: | 1289 | case DRM_FORMAT_VYUY: |
1290 | case DRM_FORMAT_NV12: | ||
1276 | if (modifier == I915_FORMAT_MOD_Yf_TILED) | 1291 | if (modifier == I915_FORMAT_MOD_Yf_TILED) |
1277 | return true; | 1292 | return true; |
1278 | /* fall through */ | 1293 | /* fall through */ |
@@ -1372,8 +1387,14 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, | |||
1372 | intel_plane->disable_plane = skl_disable_plane; | 1387 | intel_plane->disable_plane = skl_disable_plane; |
1373 | intel_plane->get_hw_state = skl_plane_get_hw_state; | 1388 | intel_plane->get_hw_state = skl_plane_get_hw_state; |
1374 | 1389 | ||
1375 | plane_formats = skl_plane_formats; | 1390 | if (skl_plane_has_planar(dev_priv, pipe, |
1376 | num_plane_formats = ARRAY_SIZE(skl_plane_formats); | 1391 | PLANE_SPRITE0 + plane)) { |
1392 | plane_formats = skl_planar_formats; | ||
1393 | num_plane_formats = ARRAY_SIZE(skl_planar_formats); | ||
1394 | } else { | ||
1395 | plane_formats = skl_plane_formats; | ||
1396 | num_plane_formats = ARRAY_SIZE(skl_plane_formats); | ||
1397 | } | ||
1377 | 1398 | ||
1378 | if (skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane)) | 1399 | if (skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane)) |
1379 | modifiers = skl_plane_format_modifiers_ccs; | 1400 | modifiers = skl_plane_format_modifiers_ccs; |
diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h b/drivers/gpu/drm/i915/intel_uc_fw.h index dc33b12394de..87910aa83267 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/intel_uc_fw.h | |||
@@ -30,7 +30,7 @@ struct drm_i915_private; | |||
30 | struct i915_vma; | 30 | struct i915_vma; |
31 | 31 | ||
32 | /* Home of GuC, HuC and DMC firmwares */ | 32 | /* Home of GuC, HuC and DMC firmwares */ |
33 | #define INTEL_UC_FIRMWARE_URL "https://01.org/linuxgraphics/downloads/firmware" | 33 | #define INTEL_UC_FIRMWARE_URL "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915" |
34 | 34 | ||
35 | enum intel_uc_fw_status { | 35 | enum intel_uc_fw_status { |
36 | INTEL_UC_FIRMWARE_FAIL = -1, | 36 | INTEL_UC_FIRMWARE_FAIL = -1, |
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d6e20f0f4c28..448293eb638d 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c | |||
@@ -139,7 +139,9 @@ fw_domain_wait_ack_with_fallback(const struct drm_i915_private *i915, | |||
139 | * in the hope that the original ack will be delivered along with | 139 | * in the hope that the original ack will be delivered along with |
140 | * the fallback ack. | 140 | * the fallback ack. |
141 | * | 141 | * |
142 | * This workaround is described in HSDES #1604254524 | 142 | * This workaround is described in HSDES #1604254524 and it's known as: |
143 | * WaRsForcewakeAddDelayForAck:skl,bxt,kbl,glk,cfl,cnl,icl | ||
144 | * although the name is a bit misleading. | ||
143 | */ | 145 | */ |
144 | 146 | ||
145 | pass = 1; | 147 | pass = 1; |
@@ -1394,7 +1396,8 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) | |||
1394 | if (INTEL_GEN(dev_priv) >= 11) { | 1396 | if (INTEL_GEN(dev_priv) >= 11) { |
1395 | int i; | 1397 | int i; |
1396 | 1398 | ||
1397 | dev_priv->uncore.funcs.force_wake_get = fw_domains_get; | 1399 | dev_priv->uncore.funcs.force_wake_get = |
1400 | fw_domains_get_with_fallback; | ||
1398 | dev_priv->uncore.funcs.force_wake_put = fw_domains_put; | 1401 | dev_priv->uncore.funcs.force_wake_put = fw_domains_put; |
1399 | fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, | 1402 | fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, |
1400 | FORCEWAKE_RENDER_GEN9, | 1403 | FORCEWAKE_RENDER_GEN9, |
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c index bbbf4ed4aa97..2df3538ceba5 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.c +++ b/drivers/gpu/drm/i915/intel_workarounds.c | |||
@@ -270,6 +270,10 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv) | |||
270 | GEN9_PREEMPT_GPGPU_LEVEL_MASK, | 270 | GEN9_PREEMPT_GPGPU_LEVEL_MASK, |
271 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); | 271 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); |
272 | 272 | ||
273 | /* WaClearHIZ_WM_CHICKEN3:bxt,glk */ | ||
274 | if (IS_GEN9_LP(dev_priv)) | ||
275 | WA_SET_BIT_MASKED(GEN9_WM_CHICKEN3, GEN9_FACTOR_IN_CLR_VAL_HIZ); | ||
276 | |||
273 | return 0; | 277 | return 0; |
274 | } | 278 | } |
275 | 279 | ||
@@ -441,6 +445,27 @@ static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv) | |||
441 | return 0; | 445 | return 0; |
442 | } | 446 | } |
443 | 447 | ||
448 | static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv) | ||
449 | { | ||
450 | /* Wa_1604370585:icl (pre-prod) | ||
451 | * Formerly known as WaPushConstantDereferenceHoldDisable | ||
452 | */ | ||
453 | if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0)) | ||
454 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, | ||
455 | PUSH_CONSTANT_DEREF_DISABLE); | ||
456 | |||
457 | /* WaForceEnableNonCoherent:icl | ||
458 | * This is not the same workaround as in early Gen9 platforms, where | ||
459 | * lacking this could cause system hangs, but coherency performance | ||
460 | * overhead is high and only a few compute workloads really need it | ||
461 | * (the register is whitelisted in hardware now, so UMDs can opt in | ||
462 | * for coherency if they have a good reason). | ||
463 | */ | ||
464 | WA_SET_BIT_MASKED(ICL_HDC_MODE, HDC_FORCE_NON_COHERENT); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
444 | int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv) | 469 | int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv) |
445 | { | 470 | { |
446 | int err = 0; | 471 | int err = 0; |
@@ -465,6 +490,8 @@ int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv) | |||
465 | err = cfl_ctx_workarounds_init(dev_priv); | 490 | err = cfl_ctx_workarounds_init(dev_priv); |
466 | else if (IS_CANNONLAKE(dev_priv)) | 491 | else if (IS_CANNONLAKE(dev_priv)) |
467 | err = cnl_ctx_workarounds_init(dev_priv); | 492 | err = cnl_ctx_workarounds_init(dev_priv); |
493 | else if (IS_ICELAKE(dev_priv)) | ||
494 | err = icl_ctx_workarounds_init(dev_priv); | ||
468 | else | 495 | else |
469 | MISSING_CASE(INTEL_GEN(dev_priv)); | 496 | MISSING_CASE(INTEL_GEN(dev_priv)); |
470 | if (err) | 497 | if (err) |
@@ -663,6 +690,90 @@ static void cnl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | |||
663 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | 690 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); |
664 | } | 691 | } |
665 | 692 | ||
693 | static void icl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | ||
694 | { | ||
695 | /* This is not an Wa. Enable for better image quality */ | ||
696 | I915_WRITE(_3D_CHICKEN3, | ||
697 | _MASKED_BIT_ENABLE(_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE)); | ||
698 | |||
699 | /* WaInPlaceDecompressionHang:icl */ | ||
700 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | ||
701 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | ||
702 | |||
703 | /* WaPipelineFlushCoherentLines:icl */ | ||
704 | I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | | ||
705 | GEN8_LQSC_FLUSH_COHERENT_LINES); | ||
706 | |||
707 | /* Wa_1405543622:icl | ||
708 | * Formerly known as WaGAPZPriorityScheme | ||
709 | */ | ||
710 | I915_WRITE(GEN8_GARBCNTL, I915_READ(GEN8_GARBCNTL) | | ||
711 | GEN11_ARBITRATION_PRIO_ORDER_MASK); | ||
712 | |||
713 | /* Wa_1604223664:icl | ||
714 | * Formerly known as WaL3BankAddressHashing | ||
715 | */ | ||
716 | I915_WRITE(GEN8_GARBCNTL, | ||
717 | (I915_READ(GEN8_GARBCNTL) & ~GEN11_HASH_CTRL_EXCL_MASK) | | ||
718 | GEN11_HASH_CTRL_EXCL_BIT0); | ||
719 | I915_WRITE(GEN11_GLBLINVL, | ||
720 | (I915_READ(GEN11_GLBLINVL) & ~GEN11_BANK_HASH_ADDR_EXCL_MASK) | | ||
721 | GEN11_BANK_HASH_ADDR_EXCL_BIT0); | ||
722 | |||
723 | /* WaModifyGamTlbPartitioning:icl */ | ||
724 | I915_WRITE(GEN11_GACB_PERF_CTRL, | ||
725 | (I915_READ(GEN11_GACB_PERF_CTRL) & ~GEN11_HASH_CTRL_MASK) | | ||
726 | GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4); | ||
727 | |||
728 | /* Wa_1405733216:icl | ||
729 | * Formerly known as WaDisableCleanEvicts | ||
730 | */ | ||
731 | I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | | ||
732 | GEN11_LQSC_CLEAN_EVICT_DISABLE); | ||
733 | |||
734 | /* Wa_1405766107:icl | ||
735 | * Formerly known as WaCL2SFHalfMaxAlloc | ||
736 | */ | ||
737 | I915_WRITE(GEN11_LSN_UNSLCVC, I915_READ(GEN11_LSN_UNSLCVC) | | ||
738 | GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC | | ||
739 | GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC); | ||
740 | |||
741 | /* Wa_220166154:icl | ||
742 | * Formerly known as WaDisCtxReload | ||
743 | */ | ||
744 | I915_WRITE(GAMW_ECO_DEV_RW_IA_REG, I915_READ(GAMW_ECO_DEV_RW_IA_REG) | | ||
745 | GAMW_ECO_DEV_CTX_RELOAD_DISABLE); | ||
746 | |||
747 | /* Wa_1405779004:icl (pre-prod) */ | ||
748 | if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0)) | ||
749 | I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE, | ||
750 | I915_READ(SLICE_UNIT_LEVEL_CLKGATE) | | ||
751 | MSCUNIT_CLKGATE_DIS); | ||
752 | |||
753 | /* Wa_1406680159:icl */ | ||
754 | I915_WRITE(SUBSLICE_UNIT_LEVEL_CLKGATE, | ||
755 | I915_READ(SUBSLICE_UNIT_LEVEL_CLKGATE) | | ||
756 | GWUNIT_CLKGATE_DIS); | ||
757 | |||
758 | /* Wa_1604302699:icl */ | ||
759 | I915_WRITE(GEN10_L3_CHICKEN_MODE_REGISTER, | ||
760 | I915_READ(GEN10_L3_CHICKEN_MODE_REGISTER) | | ||
761 | GEN11_I2M_WRITE_DISABLE); | ||
762 | |||
763 | /* Wa_1406838659:icl (pre-prod) */ | ||
764 | if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0)) | ||
765 | I915_WRITE(INF_UNIT_LEVEL_CLKGATE, | ||
766 | I915_READ(INF_UNIT_LEVEL_CLKGATE) | | ||
767 | CGPSF_CLKGATE_DIS); | ||
768 | |||
769 | /* WaForwardProgressSoftReset:icl */ | ||
770 | I915_WRITE(GEN10_SCRATCH_LNCF2, | ||
771 | I915_READ(GEN10_SCRATCH_LNCF2) | | ||
772 | PMFLUSHDONE_LNICRSDROP | | ||
773 | PMFLUSH_GAPL3UNBLOCK | | ||
774 | PMFLUSHDONE_LNEBLK); | ||
775 | } | ||
776 | |||
666 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 777 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) |
667 | { | 778 | { |
668 | if (INTEL_GEN(dev_priv) < 8) | 779 | if (INTEL_GEN(dev_priv) < 8) |
@@ -683,174 +794,156 @@ void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) | |||
683 | cfl_gt_workarounds_apply(dev_priv); | 794 | cfl_gt_workarounds_apply(dev_priv); |
684 | else if (IS_CANNONLAKE(dev_priv)) | 795 | else if (IS_CANNONLAKE(dev_priv)) |
685 | cnl_gt_workarounds_apply(dev_priv); | 796 | cnl_gt_workarounds_apply(dev_priv); |
797 | else if (IS_ICELAKE(dev_priv)) | ||
798 | icl_gt_workarounds_apply(dev_priv); | ||
686 | else | 799 | else |
687 | MISSING_CASE(INTEL_GEN(dev_priv)); | 800 | MISSING_CASE(INTEL_GEN(dev_priv)); |
688 | } | 801 | } |
689 | 802 | ||
690 | static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, | 803 | struct whitelist { |
691 | i915_reg_t reg) | 804 | i915_reg_t reg[RING_MAX_NONPRIV_SLOTS]; |
692 | { | 805 | unsigned int count; |
693 | struct drm_i915_private *dev_priv = engine->i915; | 806 | u32 nopid; |
694 | struct i915_workarounds *wa = &dev_priv->workarounds; | 807 | }; |
695 | const unsigned int index = wa->hw_whitelist_count[engine->id]; | ||
696 | 808 | ||
697 | if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) | 809 | static void whitelist_reg(struct whitelist *w, i915_reg_t reg) |
698 | return -EINVAL; | 810 | { |
699 | 811 | if (GEM_WARN_ON(w->count >= RING_MAX_NONPRIV_SLOTS)) | |
700 | I915_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), | 812 | return; |
701 | i915_mmio_reg_offset(reg)); | ||
702 | wa->hw_whitelist_count[engine->id]++; | ||
703 | 813 | ||
704 | return 0; | 814 | w->reg[w->count++] = reg; |
705 | } | 815 | } |
706 | 816 | ||
707 | static int bdw_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 817 | static void bdw_whitelist_build(struct whitelist *w) |
708 | { | 818 | { |
709 | return 0; | ||
710 | } | 819 | } |
711 | 820 | ||
712 | static int chv_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 821 | static void chv_whitelist_build(struct whitelist *w) |
713 | { | 822 | { |
714 | return 0; | ||
715 | } | 823 | } |
716 | 824 | ||
717 | static int gen9_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 825 | static void gen9_whitelist_build(struct whitelist *w) |
718 | { | 826 | { |
719 | int ret; | ||
720 | |||
721 | /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ | 827 | /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ |
722 | ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); | 828 | whitelist_reg(w, GEN9_CTX_PREEMPT_REG); |
723 | if (ret) | ||
724 | return ret; | ||
725 | 829 | ||
726 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ | 830 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ |
727 | ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); | 831 | whitelist_reg(w, GEN8_CS_CHICKEN1); |
728 | if (ret) | ||
729 | return ret; | ||
730 | 832 | ||
731 | /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk,cfl */ | 833 | /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk,cfl */ |
732 | ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); | 834 | whitelist_reg(w, GEN8_HDC_CHICKEN1); |
733 | if (ret) | ||
734 | return ret; | ||
735 | |||
736 | return 0; | ||
737 | } | 835 | } |
738 | 836 | ||
739 | static int skl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 837 | static void skl_whitelist_build(struct whitelist *w) |
740 | { | 838 | { |
741 | int ret; | 839 | gen9_whitelist_build(w); |
742 | |||
743 | ret = gen9_whitelist_workarounds_apply(engine); | ||
744 | if (ret) | ||
745 | return ret; | ||
746 | 840 | ||
747 | /* WaDisableLSQCROPERFforOCL:skl */ | 841 | /* WaDisableLSQCROPERFforOCL:skl */ |
748 | ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | 842 | whitelist_reg(w, GEN8_L3SQCREG4); |
749 | if (ret) | ||
750 | return ret; | ||
751 | |||
752 | return 0; | ||
753 | } | 843 | } |
754 | 844 | ||
755 | static int bxt_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 845 | static void bxt_whitelist_build(struct whitelist *w) |
756 | { | 846 | { |
757 | int ret; | 847 | gen9_whitelist_build(w); |
758 | |||
759 | ret = gen9_whitelist_workarounds_apply(engine); | ||
760 | if (ret) | ||
761 | return ret; | ||
762 | |||
763 | return 0; | ||
764 | } | 848 | } |
765 | 849 | ||
766 | static int kbl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 850 | static void kbl_whitelist_build(struct whitelist *w) |
767 | { | 851 | { |
768 | int ret; | 852 | gen9_whitelist_build(w); |
769 | |||
770 | ret = gen9_whitelist_workarounds_apply(engine); | ||
771 | if (ret) | ||
772 | return ret; | ||
773 | 853 | ||
774 | /* WaDisableLSQCROPERFforOCL:kbl */ | 854 | /* WaDisableLSQCROPERFforOCL:kbl */ |
775 | ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); | 855 | whitelist_reg(w, GEN8_L3SQCREG4); |
776 | if (ret) | ||
777 | return ret; | ||
778 | |||
779 | return 0; | ||
780 | } | 856 | } |
781 | 857 | ||
782 | static int glk_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 858 | static void glk_whitelist_build(struct whitelist *w) |
783 | { | 859 | { |
784 | int ret; | 860 | gen9_whitelist_build(w); |
785 | |||
786 | ret = gen9_whitelist_workarounds_apply(engine); | ||
787 | if (ret) | ||
788 | return ret; | ||
789 | 861 | ||
790 | /* WA #0862: Userspace has to set "Barrier Mode" to avoid hangs. */ | 862 | /* WA #0862: Userspace has to set "Barrier Mode" to avoid hangs. */ |
791 | ret = wa_ring_whitelist_reg(engine, GEN9_SLICE_COMMON_ECO_CHICKEN1); | 863 | whitelist_reg(w, GEN9_SLICE_COMMON_ECO_CHICKEN1); |
792 | if (ret) | ||
793 | return ret; | ||
794 | |||
795 | return 0; | ||
796 | } | 864 | } |
797 | 865 | ||
798 | static int cfl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 866 | static void cfl_whitelist_build(struct whitelist *w) |
799 | { | 867 | { |
800 | int ret; | 868 | gen9_whitelist_build(w); |
869 | } | ||
801 | 870 | ||
802 | ret = gen9_whitelist_workarounds_apply(engine); | 871 | static void cnl_whitelist_build(struct whitelist *w) |
803 | if (ret) | 872 | { |
804 | return ret; | 873 | /* WaEnablePreemptionGranularityControlByUMD:cnl */ |
874 | whitelist_reg(w, GEN8_CS_CHICKEN1); | ||
875 | } | ||
805 | 876 | ||
806 | return 0; | 877 | static void icl_whitelist_build(struct whitelist *w) |
878 | { | ||
807 | } | 879 | } |
808 | 880 | ||
809 | static int cnl_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 881 | static struct whitelist *whitelist_build(struct intel_engine_cs *engine, |
882 | struct whitelist *w) | ||
810 | { | 883 | { |
811 | int ret; | 884 | struct drm_i915_private *i915 = engine->i915; |
812 | 885 | ||
813 | /* WaEnablePreemptionGranularityControlByUMD:cnl */ | 886 | GEM_BUG_ON(engine->id != RCS); |
814 | ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); | ||
815 | if (ret) | ||
816 | return ret; | ||
817 | 887 | ||
818 | return 0; | 888 | w->count = 0; |
889 | w->nopid = i915_mmio_reg_offset(RING_NOPID(engine->mmio_base)); | ||
890 | |||
891 | if (INTEL_GEN(i915) < 8) | ||
892 | return NULL; | ||
893 | else if (IS_BROADWELL(i915)) | ||
894 | bdw_whitelist_build(w); | ||
895 | else if (IS_CHERRYVIEW(i915)) | ||
896 | chv_whitelist_build(w); | ||
897 | else if (IS_SKYLAKE(i915)) | ||
898 | skl_whitelist_build(w); | ||
899 | else if (IS_BROXTON(i915)) | ||
900 | bxt_whitelist_build(w); | ||
901 | else if (IS_KABYLAKE(i915)) | ||
902 | kbl_whitelist_build(w); | ||
903 | else if (IS_GEMINILAKE(i915)) | ||
904 | glk_whitelist_build(w); | ||
905 | else if (IS_COFFEELAKE(i915)) | ||
906 | cfl_whitelist_build(w); | ||
907 | else if (IS_CANNONLAKE(i915)) | ||
908 | cnl_whitelist_build(w); | ||
909 | else if (IS_ICELAKE(i915)) | ||
910 | icl_whitelist_build(w); | ||
911 | else | ||
912 | MISSING_CASE(INTEL_GEN(i915)); | ||
913 | |||
914 | return w; | ||
819 | } | 915 | } |
820 | 916 | ||
821 | int intel_whitelist_workarounds_apply(struct intel_engine_cs *engine) | 917 | static void whitelist_apply(struct intel_engine_cs *engine, |
918 | const struct whitelist *w) | ||
822 | { | 919 | { |
823 | struct drm_i915_private *dev_priv = engine->i915; | 920 | struct drm_i915_private *dev_priv = engine->i915; |
824 | int err = 0; | 921 | const u32 base = engine->mmio_base; |
922 | unsigned int i; | ||
825 | 923 | ||
826 | WARN_ON(engine->id != RCS); | 924 | if (!w) |
925 | return; | ||
827 | 926 | ||
828 | dev_priv->workarounds.hw_whitelist_count[engine->id] = 0; | 927 | intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL); |
829 | 928 | ||
830 | if (INTEL_GEN(dev_priv) < 8) | 929 | for (i = 0; i < w->count; i++) |
831 | err = 0; | 930 | I915_WRITE_FW(RING_FORCE_TO_NONPRIV(base, i), |
832 | else if (IS_BROADWELL(dev_priv)) | 931 | i915_mmio_reg_offset(w->reg[i])); |
833 | err = bdw_whitelist_workarounds_apply(engine); | ||
834 | else if (IS_CHERRYVIEW(dev_priv)) | ||
835 | err = chv_whitelist_workarounds_apply(engine); | ||
836 | else if (IS_SKYLAKE(dev_priv)) | ||
837 | err = skl_whitelist_workarounds_apply(engine); | ||
838 | else if (IS_BROXTON(dev_priv)) | ||
839 | err = bxt_whitelist_workarounds_apply(engine); | ||
840 | else if (IS_KABYLAKE(dev_priv)) | ||
841 | err = kbl_whitelist_workarounds_apply(engine); | ||
842 | else if (IS_GEMINILAKE(dev_priv)) | ||
843 | err = glk_whitelist_workarounds_apply(engine); | ||
844 | else if (IS_COFFEELAKE(dev_priv)) | ||
845 | err = cfl_whitelist_workarounds_apply(engine); | ||
846 | else if (IS_CANNONLAKE(dev_priv)) | ||
847 | err = cnl_whitelist_workarounds_apply(engine); | ||
848 | else | ||
849 | MISSING_CASE(INTEL_GEN(dev_priv)); | ||
850 | if (err) | ||
851 | return err; | ||
852 | 932 | ||
853 | DRM_DEBUG_DRIVER("%s: Number of whitelist w/a: %d\n", engine->name, | 933 | /* And clear the rest just in case of garbage */ |
854 | dev_priv->workarounds.hw_whitelist_count[engine->id]); | 934 | for (; i < RING_MAX_NONPRIV_SLOTS; i++) |
855 | return 0; | 935 | I915_WRITE_FW(RING_FORCE_TO_NONPRIV(base, i), w->nopid); |
936 | |||
937 | intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL); | ||
856 | } | 938 | } |
939 | |||
940 | void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine) | ||
941 | { | ||
942 | struct whitelist w; | ||
943 | |||
944 | whitelist_apply(engine, whitelist_build(engine, &w)); | ||
945 | } | ||
946 | |||
947 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | ||
948 | #include "selftests/intel_workarounds.c" | ||
949 | #endif | ||
diff --git a/drivers/gpu/drm/i915/intel_workarounds.h b/drivers/gpu/drm/i915/intel_workarounds.h index d9b0cc5afb4a..b11d0623e626 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.h +++ b/drivers/gpu/drm/i915/intel_workarounds.h | |||
@@ -12,6 +12,6 @@ int intel_ctx_workarounds_emit(struct i915_request *rq); | |||
12 | 12 | ||
13 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv); | 13 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv); |
14 | 14 | ||
15 | int intel_whitelist_workarounds_apply(struct intel_engine_cs *engine); | 15 | void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine); |
16 | 16 | ||
17 | #endif | 17 | #endif |
diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 05bbef363fff..91c72911be3c 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c | |||
@@ -1091,7 +1091,7 @@ static int __igt_write_huge(struct i915_gem_context *ctx, | |||
1091 | out_vma_unpin: | 1091 | out_vma_unpin: |
1092 | i915_vma_unpin(vma); | 1092 | i915_vma_unpin(vma); |
1093 | out_vma_close: | 1093 | out_vma_close: |
1094 | i915_vma_close(vma); | 1094 | i915_vma_destroy(vma); |
1095 | 1095 | ||
1096 | return err; | 1096 | return err; |
1097 | } | 1097 | } |
@@ -1757,6 +1757,9 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv) | |||
1757 | goto out_unlock; | 1757 | goto out_unlock; |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | if (ctx->ppgtt) | ||
1761 | ctx->ppgtt->base.scrub_64K = true; | ||
1762 | |||
1760 | err = i915_subtests(tests, ctx); | 1763 | err = i915_subtests(tests, ctx); |
1761 | 1764 | ||
1762 | out_unlock: | 1765 | out_unlock: |
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 7ecaed50d0b9..ddb03f009232 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "../i915_selftest.h" | 25 | #include "../i915_selftest.h" |
26 | #include "igt_flush_test.h" | ||
26 | 27 | ||
27 | #include "mock_drm.h" | 28 | #include "mock_drm.h" |
28 | #include "huge_gem_object.h" | 29 | #include "huge_gem_object.h" |
@@ -411,6 +412,8 @@ static int igt_ctx_exec(void *arg) | |||
411 | } | 412 | } |
412 | 413 | ||
413 | out_unlock: | 414 | out_unlock: |
415 | if (igt_flush_test(i915, I915_WAIT_LOCKED)) | ||
416 | err = -EIO; | ||
414 | mutex_unlock(&i915->drm.struct_mutex); | 417 | mutex_unlock(&i915->drm.struct_mutex); |
415 | 418 | ||
416 | mock_file_free(i915, file); | 419 | mock_file_free(i915, file); |
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 8bf6aa573226..a00e2bd08bce 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */ | 12 | selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */ |
13 | selftest(uncore, intel_uncore_live_selftests) | 13 | selftest(uncore, intel_uncore_live_selftests) |
14 | selftest(workarounds, intel_workarounds_live_selftests) | ||
14 | selftest(requests, i915_request_live_selftests) | 15 | selftest(requests, i915_request_live_selftests) |
15 | selftest(objects, i915_gem_object_live_selftests) | 16 | selftest(objects, i915_gem_object_live_selftests) |
16 | selftest(dmabuf, i915_gem_dmabuf_live_selftests) | 17 | selftest(dmabuf, i915_gem_dmabuf_live_selftests) |
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c b/drivers/gpu/drm/i915/selftests/i915_timeline.c index 3000e6a7d82d..19f1c6a5c8fb 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c +++ b/drivers/gpu/drm/i915/selftests/i915_timeline.c | |||
@@ -1,25 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2017 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2017-2018 Intel Corporation | ||
23 | */ | 5 | */ |
24 | 6 | ||
25 | #include "../i915_selftest.h" | 7 | #include "../i915_selftest.h" |
@@ -35,21 +17,21 @@ struct __igt_sync { | |||
35 | bool set; | 17 | bool set; |
36 | }; | 18 | }; |
37 | 19 | ||
38 | static int __igt_sync(struct intel_timeline *tl, | 20 | static int __igt_sync(struct i915_timeline *tl, |
39 | u64 ctx, | 21 | u64 ctx, |
40 | const struct __igt_sync *p, | 22 | const struct __igt_sync *p, |
41 | const char *name) | 23 | const char *name) |
42 | { | 24 | { |
43 | int ret; | 25 | int ret; |
44 | 26 | ||
45 | if (__intel_timeline_sync_is_later(tl, ctx, p->seqno) != p->expected) { | 27 | if (__i915_timeline_sync_is_later(tl, ctx, p->seqno) != p->expected) { |
46 | pr_err("%s: %s(ctx=%llu, seqno=%u) expected passed %s but failed\n", | 28 | pr_err("%s: %s(ctx=%llu, seqno=%u) expected passed %s but failed\n", |
47 | name, p->name, ctx, p->seqno, yesno(p->expected)); | 29 | name, p->name, ctx, p->seqno, yesno(p->expected)); |
48 | return -EINVAL; | 30 | return -EINVAL; |
49 | } | 31 | } |
50 | 32 | ||
51 | if (p->set) { | 33 | if (p->set) { |
52 | ret = __intel_timeline_sync_set(tl, ctx, p->seqno); | 34 | ret = __i915_timeline_sync_set(tl, ctx, p->seqno); |
53 | if (ret) | 35 | if (ret) |
54 | return ret; | 36 | return ret; |
55 | } | 37 | } |
@@ -77,37 +59,31 @@ static int igt_sync(void *arg) | |||
77 | { "unwrap", UINT_MAX, true, false }, | 59 | { "unwrap", UINT_MAX, true, false }, |
78 | {}, | 60 | {}, |
79 | }, *p; | 61 | }, *p; |
80 | struct intel_timeline *tl; | 62 | struct i915_timeline tl; |
81 | int order, offset; | 63 | int order, offset; |
82 | int ret = -ENODEV; | 64 | int ret = -ENODEV; |
83 | 65 | ||
84 | tl = mock_timeline(0); | 66 | mock_timeline_init(&tl, 0); |
85 | if (!tl) | ||
86 | return -ENOMEM; | ||
87 | |||
88 | for (p = pass; p->name; p++) { | 67 | for (p = pass; p->name; p++) { |
89 | for (order = 1; order < 64; order++) { | 68 | for (order = 1; order < 64; order++) { |
90 | for (offset = -1; offset <= (order > 1); offset++) { | 69 | for (offset = -1; offset <= (order > 1); offset++) { |
91 | u64 ctx = BIT_ULL(order) + offset; | 70 | u64 ctx = BIT_ULL(order) + offset; |
92 | 71 | ||
93 | ret = __igt_sync(tl, ctx, p, "1"); | 72 | ret = __igt_sync(&tl, ctx, p, "1"); |
94 | if (ret) | 73 | if (ret) |
95 | goto out; | 74 | goto out; |
96 | } | 75 | } |
97 | } | 76 | } |
98 | } | 77 | } |
99 | mock_timeline_destroy(tl); | 78 | mock_timeline_fini(&tl); |
100 | |||
101 | tl = mock_timeline(0); | ||
102 | if (!tl) | ||
103 | return -ENOMEM; | ||
104 | 79 | ||
80 | mock_timeline_init(&tl, 0); | ||
105 | for (order = 1; order < 64; order++) { | 81 | for (order = 1; order < 64; order++) { |
106 | for (offset = -1; offset <= (order > 1); offset++) { | 82 | for (offset = -1; offset <= (order > 1); offset++) { |
107 | u64 ctx = BIT_ULL(order) + offset; | 83 | u64 ctx = BIT_ULL(order) + offset; |
108 | 84 | ||
109 | for (p = pass; p->name; p++) { | 85 | for (p = pass; p->name; p++) { |
110 | ret = __igt_sync(tl, ctx, p, "2"); | 86 | ret = __igt_sync(&tl, ctx, p, "2"); |
111 | if (ret) | 87 | if (ret) |
112 | goto out; | 88 | goto out; |
113 | } | 89 | } |
@@ -115,7 +91,7 @@ static int igt_sync(void *arg) | |||
115 | } | 91 | } |
116 | 92 | ||
117 | out: | 93 | out: |
118 | mock_timeline_destroy(tl); | 94 | mock_timeline_fini(&tl); |
119 | return ret; | 95 | return ret; |
120 | } | 96 | } |
121 | 97 | ||
@@ -127,15 +103,13 @@ static unsigned int random_engine(struct rnd_state *rnd) | |||
127 | static int bench_sync(void *arg) | 103 | static int bench_sync(void *arg) |
128 | { | 104 | { |
129 | struct rnd_state prng; | 105 | struct rnd_state prng; |
130 | struct intel_timeline *tl; | 106 | struct i915_timeline tl; |
131 | unsigned long end_time, count; | 107 | unsigned long end_time, count; |
132 | u64 prng32_1M; | 108 | u64 prng32_1M; |
133 | ktime_t kt; | 109 | ktime_t kt; |
134 | int order, last_order; | 110 | int order, last_order; |
135 | 111 | ||
136 | tl = mock_timeline(0); | 112 | mock_timeline_init(&tl, 0); |
137 | if (!tl) | ||
138 | return -ENOMEM; | ||
139 | 113 | ||
140 | /* Lookups from cache are very fast and so the random number generation | 114 | /* Lookups from cache are very fast and so the random number generation |
141 | * and the loop itself becomes a significant factor in the per-iteration | 115 | * and the loop itself becomes a significant factor in the per-iteration |
@@ -167,7 +141,7 @@ static int bench_sync(void *arg) | |||
167 | do { | 141 | do { |
168 | u64 id = i915_prandom_u64_state(&prng); | 142 | u64 id = i915_prandom_u64_state(&prng); |
169 | 143 | ||
170 | __intel_timeline_sync_set(tl, id, 0); | 144 | __i915_timeline_sync_set(&tl, id, 0); |
171 | count++; | 145 | count++; |
172 | } while (!time_after(jiffies, end_time)); | 146 | } while (!time_after(jiffies, end_time)); |
173 | kt = ktime_sub(ktime_get(), kt); | 147 | kt = ktime_sub(ktime_get(), kt); |
@@ -182,8 +156,8 @@ static int bench_sync(void *arg) | |||
182 | while (end_time--) { | 156 | while (end_time--) { |
183 | u64 id = i915_prandom_u64_state(&prng); | 157 | u64 id = i915_prandom_u64_state(&prng); |
184 | 158 | ||
185 | if (!__intel_timeline_sync_is_later(tl, id, 0)) { | 159 | if (!__i915_timeline_sync_is_later(&tl, id, 0)) { |
186 | mock_timeline_destroy(tl); | 160 | mock_timeline_fini(&tl); |
187 | pr_err("Lookup of %llu failed\n", id); | 161 | pr_err("Lookup of %llu failed\n", id); |
188 | return -EINVAL; | 162 | return -EINVAL; |
189 | } | 163 | } |
@@ -193,19 +167,17 @@ static int bench_sync(void *arg) | |||
193 | pr_info("%s: %lu random lookups, %lluns/lookup\n", | 167 | pr_info("%s: %lu random lookups, %lluns/lookup\n", |
194 | __func__, count, (long long)div64_ul(ktime_to_ns(kt), count)); | 168 | __func__, count, (long long)div64_ul(ktime_to_ns(kt), count)); |
195 | 169 | ||
196 | mock_timeline_destroy(tl); | 170 | mock_timeline_fini(&tl); |
197 | cond_resched(); | 171 | cond_resched(); |
198 | 172 | ||
199 | tl = mock_timeline(0); | 173 | mock_timeline_init(&tl, 0); |
200 | if (!tl) | ||
201 | return -ENOMEM; | ||
202 | 174 | ||
203 | /* Benchmark setting the first N (in order) contexts */ | 175 | /* Benchmark setting the first N (in order) contexts */ |
204 | count = 0; | 176 | count = 0; |
205 | kt = ktime_get(); | 177 | kt = ktime_get(); |
206 | end_time = jiffies + HZ/10; | 178 | end_time = jiffies + HZ/10; |
207 | do { | 179 | do { |
208 | __intel_timeline_sync_set(tl, count++, 0); | 180 | __i915_timeline_sync_set(&tl, count++, 0); |
209 | } while (!time_after(jiffies, end_time)); | 181 | } while (!time_after(jiffies, end_time)); |
210 | kt = ktime_sub(ktime_get(), kt); | 182 | kt = ktime_sub(ktime_get(), kt); |
211 | pr_info("%s: %lu in-order insertions, %lluns/insert\n", | 183 | pr_info("%s: %lu in-order insertions, %lluns/insert\n", |
@@ -215,9 +187,9 @@ static int bench_sync(void *arg) | |||
215 | end_time = count; | 187 | end_time = count; |
216 | kt = ktime_get(); | 188 | kt = ktime_get(); |
217 | while (end_time--) { | 189 | while (end_time--) { |
218 | if (!__intel_timeline_sync_is_later(tl, end_time, 0)) { | 190 | if (!__i915_timeline_sync_is_later(&tl, end_time, 0)) { |
219 | pr_err("Lookup of %lu failed\n", end_time); | 191 | pr_err("Lookup of %lu failed\n", end_time); |
220 | mock_timeline_destroy(tl); | 192 | mock_timeline_fini(&tl); |
221 | return -EINVAL; | 193 | return -EINVAL; |
222 | } | 194 | } |
223 | } | 195 | } |
@@ -225,12 +197,10 @@ static int bench_sync(void *arg) | |||
225 | pr_info("%s: %lu in-order lookups, %lluns/lookup\n", | 197 | pr_info("%s: %lu in-order lookups, %lluns/lookup\n", |
226 | __func__, count, (long long)div64_ul(ktime_to_ns(kt), count)); | 198 | __func__, count, (long long)div64_ul(ktime_to_ns(kt), count)); |
227 | 199 | ||
228 | mock_timeline_destroy(tl); | 200 | mock_timeline_fini(&tl); |
229 | cond_resched(); | 201 | cond_resched(); |
230 | 202 | ||
231 | tl = mock_timeline(0); | 203 | mock_timeline_init(&tl, 0); |
232 | if (!tl) | ||
233 | return -ENOMEM; | ||
234 | 204 | ||
235 | /* Benchmark searching for a random context id and maybe changing it */ | 205 | /* Benchmark searching for a random context id and maybe changing it */ |
236 | prandom_seed_state(&prng, i915_selftest.random_seed); | 206 | prandom_seed_state(&prng, i915_selftest.random_seed); |
@@ -241,8 +211,8 @@ static int bench_sync(void *arg) | |||
241 | u32 id = random_engine(&prng); | 211 | u32 id = random_engine(&prng); |
242 | u32 seqno = prandom_u32_state(&prng); | 212 | u32 seqno = prandom_u32_state(&prng); |
243 | 213 | ||
244 | if (!__intel_timeline_sync_is_later(tl, id, seqno)) | 214 | if (!__i915_timeline_sync_is_later(&tl, id, seqno)) |
245 | __intel_timeline_sync_set(tl, id, seqno); | 215 | __i915_timeline_sync_set(&tl, id, seqno); |
246 | 216 | ||
247 | count++; | 217 | count++; |
248 | } while (!time_after(jiffies, end_time)); | 218 | } while (!time_after(jiffies, end_time)); |
@@ -250,7 +220,7 @@ static int bench_sync(void *arg) | |||
250 | kt = ktime_sub_ns(kt, (count * prng32_1M * 2) >> 20); | 220 | kt = ktime_sub_ns(kt, (count * prng32_1M * 2) >> 20); |
251 | pr_info("%s: %lu repeated insert/lookups, %lluns/op\n", | 221 | pr_info("%s: %lu repeated insert/lookups, %lluns/op\n", |
252 | __func__, count, (long long)div64_ul(ktime_to_ns(kt), count)); | 222 | __func__, count, (long long)div64_ul(ktime_to_ns(kt), count)); |
253 | mock_timeline_destroy(tl); | 223 | mock_timeline_fini(&tl); |
254 | cond_resched(); | 224 | cond_resched(); |
255 | 225 | ||
256 | /* Benchmark searching for a known context id and changing the seqno */ | 226 | /* Benchmark searching for a known context id and changing the seqno */ |
@@ -258,9 +228,7 @@ static int bench_sync(void *arg) | |||
258 | ({ int tmp = last_order; last_order = order; order += tmp; })) { | 228 | ({ int tmp = last_order; last_order = order; order += tmp; })) { |
259 | unsigned int mask = BIT(order) - 1; | 229 | unsigned int mask = BIT(order) - 1; |
260 | 230 | ||
261 | tl = mock_timeline(0); | 231 | mock_timeline_init(&tl, 0); |
262 | if (!tl) | ||
263 | return -ENOMEM; | ||
264 | 232 | ||
265 | count = 0; | 233 | count = 0; |
266 | kt = ktime_get(); | 234 | kt = ktime_get(); |
@@ -272,8 +240,8 @@ static int bench_sync(void *arg) | |||
272 | */ | 240 | */ |
273 | u64 id = (u64)(count & mask) << order; | 241 | u64 id = (u64)(count & mask) << order; |
274 | 242 | ||
275 | __intel_timeline_sync_is_later(tl, id, 0); | 243 | __i915_timeline_sync_is_later(&tl, id, 0); |
276 | __intel_timeline_sync_set(tl, id, 0); | 244 | __i915_timeline_sync_set(&tl, id, 0); |
277 | 245 | ||
278 | count++; | 246 | count++; |
279 | } while (!time_after(jiffies, end_time)); | 247 | } while (!time_after(jiffies, end_time)); |
@@ -281,7 +249,7 @@ static int bench_sync(void *arg) | |||
281 | pr_info("%s: %lu cyclic/%d insert/lookups, %lluns/op\n", | 249 | pr_info("%s: %lu cyclic/%d insert/lookups, %lluns/op\n", |
282 | __func__, count, order, | 250 | __func__, count, order, |
283 | (long long)div64_ul(ktime_to_ns(kt), count)); | 251 | (long long)div64_ul(ktime_to_ns(kt), count)); |
284 | mock_timeline_destroy(tl); | 252 | mock_timeline_fini(&tl); |
285 | cond_resched(); | 253 | cond_resched(); |
286 | } | 254 | } |
287 | 255 | ||
diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index eb89e301b602..e90f97236e50 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c | |||
@@ -81,7 +81,7 @@ checked_vma_instance(struct drm_i915_gem_object *obj, | |||
81 | } | 81 | } |
82 | 82 | ||
83 | if (i915_vma_compare(vma, vm, view)) { | 83 | if (i915_vma_compare(vma, vm, view)) { |
84 | pr_err("i915_vma_compare failed with create parmaters!\n"); | 84 | pr_err("i915_vma_compare failed with create parameters!\n"); |
85 | return ERR_PTR(-EINVAL); | 85 | return ERR_PTR(-EINVAL); |
86 | } | 86 | } |
87 | 87 | ||
diff --git a/drivers/gpu/drm/i915/selftests/igt_flush_test.c b/drivers/gpu/drm/i915/selftests/igt_flush_test.c new file mode 100644 index 000000000000..0d06f559243f --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/igt_flush_test.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "../i915_drv.h" | ||
8 | |||
9 | #include "../i915_selftest.h" | ||
10 | #include "igt_flush_test.h" | ||
11 | |||
12 | struct wedge_me { | ||
13 | struct delayed_work work; | ||
14 | struct drm_i915_private *i915; | ||
15 | const void *symbol; | ||
16 | }; | ||
17 | |||
18 | static void wedge_me(struct work_struct *work) | ||
19 | { | ||
20 | struct wedge_me *w = container_of(work, typeof(*w), work.work); | ||
21 | |||
22 | pr_err("%pS timed out, cancelling all further testing.\n", w->symbol); | ||
23 | |||
24 | GEM_TRACE("%pS timed out.\n", w->symbol); | ||
25 | GEM_TRACE_DUMP(); | ||
26 | |||
27 | i915_gem_set_wedged(w->i915); | ||
28 | } | ||
29 | |||
30 | static void __init_wedge(struct wedge_me *w, | ||
31 | struct drm_i915_private *i915, | ||
32 | long timeout, | ||
33 | const void *symbol) | ||
34 | { | ||
35 | w->i915 = i915; | ||
36 | w->symbol = symbol; | ||
37 | |||
38 | INIT_DELAYED_WORK_ONSTACK(&w->work, wedge_me); | ||
39 | schedule_delayed_work(&w->work, timeout); | ||
40 | } | ||
41 | |||
42 | static void __fini_wedge(struct wedge_me *w) | ||
43 | { | ||
44 | cancel_delayed_work_sync(&w->work); | ||
45 | destroy_delayed_work_on_stack(&w->work); | ||
46 | w->i915 = NULL; | ||
47 | } | ||
48 | |||
49 | #define wedge_on_timeout(W, DEV, TIMEOUT) \ | ||
50 | for (__init_wedge((W), (DEV), (TIMEOUT), __builtin_return_address(0)); \ | ||
51 | (W)->i915; \ | ||
52 | __fini_wedge((W))) | ||
53 | |||
54 | int igt_flush_test(struct drm_i915_private *i915, unsigned int flags) | ||
55 | { | ||
56 | struct wedge_me w; | ||
57 | |||
58 | cond_resched(); | ||
59 | |||
60 | if (flags & I915_WAIT_LOCKED && | ||
61 | i915_gem_switch_to_kernel_context(i915)) { | ||
62 | pr_err("Failed to switch back to kernel context; declaring wedged\n"); | ||
63 | i915_gem_set_wedged(i915); | ||
64 | } | ||
65 | |||
66 | wedge_on_timeout(&w, i915, HZ) | ||
67 | i915_gem_wait_for_idle(i915, flags); | ||
68 | |||
69 | return i915_terminally_wedged(&i915->gpu_error) ? -EIO : 0; | ||
70 | } | ||
diff --git a/drivers/gpu/drm/i915/selftests/igt_flush_test.h b/drivers/gpu/drm/i915/selftests/igt_flush_test.h new file mode 100644 index 000000000000..63e009927c43 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/igt_flush_test.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #ifndef IGT_FLUSH_TEST_H | ||
8 | #define IGT_FLUSH_TEST_H | ||
9 | |||
10 | struct drm_i915_private; | ||
11 | |||
12 | int igt_flush_test(struct drm_i915_private *i915, unsigned int flags); | ||
13 | |||
14 | #endif /* IGT_FLUSH_TEST_H */ | ||
diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c index 46580026c7fc..d6926e7820e5 100644 --- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | |||
@@ -412,10 +412,11 @@ static int igt_wakeup(void *arg) | |||
412 | * that they are ready for the next test. We wait until all | 412 | * that they are ready for the next test. We wait until all |
413 | * threads are complete and waiting for us (i.e. not a seqno). | 413 | * threads are complete and waiting for us (i.e. not a seqno). |
414 | */ | 414 | */ |
415 | err = wait_var_event_timeout(&done, !atomic_read(&done), 10 * HZ); | 415 | if (!wait_var_event_timeout(&done, |
416 | if (err) { | 416 | !atomic_read(&done), 10 * HZ)) { |
417 | pr_err("Timed out waiting for %d remaining waiters\n", | 417 | pr_err("Timed out waiting for %d remaining waiters\n", |
418 | atomic_read(&done)); | 418 | atomic_read(&done)); |
419 | err = -ETIMEDOUT; | ||
419 | break; | 420 | break; |
420 | } | 421 | } |
421 | 422 | ||
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 24f913f26a7b..438e0b045a2c 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c | |||
@@ -26,10 +26,13 @@ | |||
26 | 26 | ||
27 | #include "../i915_selftest.h" | 27 | #include "../i915_selftest.h" |
28 | #include "i915_random.h" | 28 | #include "i915_random.h" |
29 | #include "igt_flush_test.h" | ||
29 | 30 | ||
30 | #include "mock_context.h" | 31 | #include "mock_context.h" |
31 | #include "mock_drm.h" | 32 | #include "mock_drm.h" |
32 | 33 | ||
34 | #define IGT_IDLE_TIMEOUT 50 /* ms; time to wait after flushing between tests */ | ||
35 | |||
33 | struct hang { | 36 | struct hang { |
34 | struct drm_i915_private *i915; | 37 | struct drm_i915_private *i915; |
35 | struct drm_i915_gem_object *hws; | 38 | struct drm_i915_gem_object *hws; |
@@ -251,61 +254,6 @@ static u32 hws_seqno(const struct hang *h, const struct i915_request *rq) | |||
251 | return READ_ONCE(h->seqno[rq->fence.context % (PAGE_SIZE/sizeof(u32))]); | 254 | return READ_ONCE(h->seqno[rq->fence.context % (PAGE_SIZE/sizeof(u32))]); |
252 | } | 255 | } |
253 | 256 | ||
254 | struct wedge_me { | ||
255 | struct delayed_work work; | ||
256 | struct drm_i915_private *i915; | ||
257 | const void *symbol; | ||
258 | }; | ||
259 | |||
260 | static void wedge_me(struct work_struct *work) | ||
261 | { | ||
262 | struct wedge_me *w = container_of(work, typeof(*w), work.work); | ||
263 | |||
264 | pr_err("%pS timed out, cancelling all further testing.\n", w->symbol); | ||
265 | |||
266 | GEM_TRACE("%pS timed out.\n", w->symbol); | ||
267 | GEM_TRACE_DUMP(); | ||
268 | |||
269 | i915_gem_set_wedged(w->i915); | ||
270 | } | ||
271 | |||
272 | static void __init_wedge(struct wedge_me *w, | ||
273 | struct drm_i915_private *i915, | ||
274 | long timeout, | ||
275 | const void *symbol) | ||
276 | { | ||
277 | w->i915 = i915; | ||
278 | w->symbol = symbol; | ||
279 | |||
280 | INIT_DELAYED_WORK_ONSTACK(&w->work, wedge_me); | ||
281 | schedule_delayed_work(&w->work, timeout); | ||
282 | } | ||
283 | |||
284 | static void __fini_wedge(struct wedge_me *w) | ||
285 | { | ||
286 | cancel_delayed_work_sync(&w->work); | ||
287 | destroy_delayed_work_on_stack(&w->work); | ||
288 | w->i915 = NULL; | ||
289 | } | ||
290 | |||
291 | #define wedge_on_timeout(W, DEV, TIMEOUT) \ | ||
292 | for (__init_wedge((W), (DEV), (TIMEOUT), __builtin_return_address(0)); \ | ||
293 | (W)->i915; \ | ||
294 | __fini_wedge((W))) | ||
295 | |||
296 | static noinline int | ||
297 | flush_test(struct drm_i915_private *i915, unsigned int flags) | ||
298 | { | ||
299 | struct wedge_me w; | ||
300 | |||
301 | cond_resched(); | ||
302 | |||
303 | wedge_on_timeout(&w, i915, HZ) | ||
304 | i915_gem_wait_for_idle(i915, flags); | ||
305 | |||
306 | return i915_terminally_wedged(&i915->gpu_error) ? -EIO : 0; | ||
307 | } | ||
308 | |||
309 | static void hang_fini(struct hang *h) | 257 | static void hang_fini(struct hang *h) |
310 | { | 258 | { |
311 | *h->batch = MI_BATCH_BUFFER_END; | 259 | *h->batch = MI_BATCH_BUFFER_END; |
@@ -319,7 +267,7 @@ static void hang_fini(struct hang *h) | |||
319 | 267 | ||
320 | kernel_context_close(h->ctx); | 268 | kernel_context_close(h->ctx); |
321 | 269 | ||
322 | flush_test(h->i915, I915_WAIT_LOCKED); | 270 | igt_flush_test(h->i915, I915_WAIT_LOCKED); |
323 | } | 271 | } |
324 | 272 | ||
325 | static bool wait_until_running(struct hang *h, struct i915_request *rq) | 273 | static bool wait_until_running(struct hang *h, struct i915_request *rq) |
@@ -454,6 +402,11 @@ static int igt_global_reset(void *arg) | |||
454 | return err; | 402 | return err; |
455 | } | 403 | } |
456 | 404 | ||
405 | static bool wait_for_idle(struct intel_engine_cs *engine) | ||
406 | { | ||
407 | return wait_for(intel_engine_is_idle(engine), IGT_IDLE_TIMEOUT) == 0; | ||
408 | } | ||
409 | |||
457 | static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | 410 | static int __igt_reset_engine(struct drm_i915_private *i915, bool active) |
458 | { | 411 | { |
459 | struct intel_engine_cs *engine; | 412 | struct intel_engine_cs *engine; |
@@ -481,6 +434,13 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | |||
481 | if (active && !intel_engine_can_store_dword(engine)) | 434 | if (active && !intel_engine_can_store_dword(engine)) |
482 | continue; | 435 | continue; |
483 | 436 | ||
437 | if (!wait_for_idle(engine)) { | ||
438 | pr_err("%s failed to idle before reset\n", | ||
439 | engine->name); | ||
440 | err = -EIO; | ||
441 | break; | ||
442 | } | ||
443 | |||
484 | reset_count = i915_reset_count(&i915->gpu_error); | 444 | reset_count = i915_reset_count(&i915->gpu_error); |
485 | reset_engine_count = i915_reset_engine_count(&i915->gpu_error, | 445 | reset_engine_count = i915_reset_engine_count(&i915->gpu_error, |
486 | engine); | 446 | engine); |
@@ -542,13 +502,26 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) | |||
542 | err = -EINVAL; | 502 | err = -EINVAL; |
543 | break; | 503 | break; |
544 | } | 504 | } |
505 | |||
506 | if (!wait_for_idle(engine)) { | ||
507 | struct drm_printer p = | ||
508 | drm_info_printer(i915->drm.dev); | ||
509 | |||
510 | pr_err("%s failed to idle after reset\n", | ||
511 | engine->name); | ||
512 | intel_engine_dump(engine, &p, | ||
513 | "%s\n", engine->name); | ||
514 | |||
515 | err = -EIO; | ||
516 | break; | ||
517 | } | ||
545 | } while (time_before(jiffies, end_time)); | 518 | } while (time_before(jiffies, end_time)); |
546 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); | 519 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
547 | 520 | ||
548 | if (err) | 521 | if (err) |
549 | break; | 522 | break; |
550 | 523 | ||
551 | err = flush_test(i915, 0); | 524 | err = igt_flush_test(i915, 0); |
552 | if (err) | 525 | if (err) |
553 | break; | 526 | break; |
554 | } | 527 | } |
@@ -628,7 +601,7 @@ static int active_engine(void *data) | |||
628 | } | 601 | } |
629 | 602 | ||
630 | if (arg->flags & TEST_PRIORITY) | 603 | if (arg->flags & TEST_PRIORITY) |
631 | ctx[idx]->priority = | 604 | ctx[idx]->sched.priority = |
632 | i915_prandom_u32_max_state(512, &prng); | 605 | i915_prandom_u32_max_state(512, &prng); |
633 | 606 | ||
634 | rq[idx] = i915_request_get(new); | 607 | rq[idx] = i915_request_get(new); |
@@ -683,7 +656,7 @@ static int __igt_reset_engines(struct drm_i915_private *i915, | |||
683 | return err; | 656 | return err; |
684 | 657 | ||
685 | if (flags & TEST_PRIORITY) | 658 | if (flags & TEST_PRIORITY) |
686 | h.ctx->priority = 1024; | 659 | h.ctx->sched.priority = 1024; |
687 | } | 660 | } |
688 | 661 | ||
689 | for_each_engine(engine, i915, id) { | 662 | for_each_engine(engine, i915, id) { |
@@ -696,6 +669,13 @@ static int __igt_reset_engines(struct drm_i915_private *i915, | |||
696 | !intel_engine_can_store_dword(engine)) | 669 | !intel_engine_can_store_dword(engine)) |
697 | continue; | 670 | continue; |
698 | 671 | ||
672 | if (!wait_for_idle(engine)) { | ||
673 | pr_err("i915_reset_engine(%s:%s): failed to idle before reset\n", | ||
674 | engine->name, test_name); | ||
675 | err = -EIO; | ||
676 | break; | ||
677 | } | ||
678 | |||
699 | memset(threads, 0, sizeof(threads)); | 679 | memset(threads, 0, sizeof(threads)); |
700 | for_each_engine(other, i915, tmp) { | 680 | for_each_engine(other, i915, tmp) { |
701 | struct task_struct *tsk; | 681 | struct task_struct *tsk; |
@@ -772,6 +752,20 @@ static int __igt_reset_engines(struct drm_i915_private *i915, | |||
772 | i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT); | 752 | i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT); |
773 | i915_request_put(rq); | 753 | i915_request_put(rq); |
774 | } | 754 | } |
755 | |||
756 | if (!(flags & TEST_SELF) && !wait_for_idle(engine)) { | ||
757 | struct drm_printer p = | ||
758 | drm_info_printer(i915->drm.dev); | ||
759 | |||
760 | pr_err("i915_reset_engine(%s:%s):" | ||
761 | " failed to idle after reset\n", | ||
762 | engine->name, test_name); | ||
763 | intel_engine_dump(engine, &p, | ||
764 | "%s\n", engine->name); | ||
765 | |||
766 | err = -EIO; | ||
767 | break; | ||
768 | } | ||
775 | } while (time_before(jiffies, end_time)); | 769 | } while (time_before(jiffies, end_time)); |
776 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); | 770 | clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); |
777 | pr_info("i915_reset_engine(%s:%s): %lu resets\n", | 771 | pr_info("i915_reset_engine(%s:%s): %lu resets\n", |
@@ -826,7 +820,7 @@ unwind: | |||
826 | if (err) | 820 | if (err) |
827 | break; | 821 | break; |
828 | 822 | ||
829 | err = flush_test(i915, 0); | 823 | err = igt_flush_test(i915, 0); |
830 | if (err) | 824 | if (err) |
831 | break; | 825 | break; |
832 | } | 826 | } |
@@ -981,7 +975,7 @@ static int wait_for_others(struct drm_i915_private *i915, | |||
981 | if (engine == exclude) | 975 | if (engine == exclude) |
982 | continue; | 976 | continue; |
983 | 977 | ||
984 | if (wait_for(intel_engine_is_idle(engine), 10)) | 978 | if (!wait_for_idle(engine)) |
985 | return -EIO; | 979 | return -EIO; |
986 | } | 980 | } |
987 | 981 | ||
@@ -1120,7 +1114,7 @@ static int igt_reset_queue(void *arg) | |||
1120 | 1114 | ||
1121 | i915_request_put(prev); | 1115 | i915_request_put(prev); |
1122 | 1116 | ||
1123 | err = flush_test(i915, I915_WAIT_LOCKED); | 1117 | err = igt_flush_test(i915, I915_WAIT_LOCKED); |
1124 | if (err) | 1118 | if (err) |
1125 | break; | 1119 | break; |
1126 | } | 1120 | } |
@@ -1232,7 +1226,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915) | |||
1232 | err = i915_subtests(tests, i915); | 1226 | err = i915_subtests(tests, i915); |
1233 | 1227 | ||
1234 | mutex_lock(&i915->drm.struct_mutex); | 1228 | mutex_lock(&i915->drm.struct_mutex); |
1235 | flush_test(i915, I915_WAIT_LOCKED); | 1229 | igt_flush_test(i915, I915_WAIT_LOCKED); |
1236 | mutex_unlock(&i915->drm.struct_mutex); | 1230 | mutex_unlock(&i915->drm.struct_mutex); |
1237 | 1231 | ||
1238 | i915_modparams.enable_hangcheck = saved_hangcheck; | 1232 | i915_modparams.enable_hangcheck = saved_hangcheck; |
diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c index 0481e2e01146..1b8a07125150 100644 --- a/drivers/gpu/drm/i915/selftests/intel_lrc.c +++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c | |||
@@ -5,6 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "../i915_selftest.h" | 7 | #include "../i915_selftest.h" |
8 | #include "igt_flush_test.h" | ||
8 | 9 | ||
9 | #include "mock_context.h" | 10 | #include "mock_context.h" |
10 | 11 | ||
@@ -168,61 +169,6 @@ static u32 hws_seqno(const struct spinner *spin, const struct i915_request *rq) | |||
168 | return READ_ONCE(*seqno); | 169 | return READ_ONCE(*seqno); |
169 | } | 170 | } |
170 | 171 | ||
171 | struct wedge_me { | ||
172 | struct delayed_work work; | ||
173 | struct drm_i915_private *i915; | ||
174 | const void *symbol; | ||
175 | }; | ||
176 | |||
177 | static void wedge_me(struct work_struct *work) | ||
178 | { | ||
179 | struct wedge_me *w = container_of(work, typeof(*w), work.work); | ||
180 | |||
181 | pr_err("%pS timed out, cancelling all further testing.\n", w->symbol); | ||
182 | |||
183 | GEM_TRACE("%pS timed out.\n", w->symbol); | ||
184 | GEM_TRACE_DUMP(); | ||
185 | |||
186 | i915_gem_set_wedged(w->i915); | ||
187 | } | ||
188 | |||
189 | static void __init_wedge(struct wedge_me *w, | ||
190 | struct drm_i915_private *i915, | ||
191 | long timeout, | ||
192 | const void *symbol) | ||
193 | { | ||
194 | w->i915 = i915; | ||
195 | w->symbol = symbol; | ||
196 | |||
197 | INIT_DELAYED_WORK_ONSTACK(&w->work, wedge_me); | ||
198 | schedule_delayed_work(&w->work, timeout); | ||
199 | } | ||
200 | |||
201 | static void __fini_wedge(struct wedge_me *w) | ||
202 | { | ||
203 | cancel_delayed_work_sync(&w->work); | ||
204 | destroy_delayed_work_on_stack(&w->work); | ||
205 | w->i915 = NULL; | ||
206 | } | ||
207 | |||
208 | #define wedge_on_timeout(W, DEV, TIMEOUT) \ | ||
209 | for (__init_wedge((W), (DEV), (TIMEOUT), __builtin_return_address(0)); \ | ||
210 | (W)->i915; \ | ||
211 | __fini_wedge((W))) | ||
212 | |||
213 | static noinline int | ||
214 | flush_test(struct drm_i915_private *i915, unsigned int flags) | ||
215 | { | ||
216 | struct wedge_me w; | ||
217 | |||
218 | cond_resched(); | ||
219 | |||
220 | wedge_on_timeout(&w, i915, HZ) | ||
221 | i915_gem_wait_for_idle(i915, flags); | ||
222 | |||
223 | return i915_terminally_wedged(&i915->gpu_error) ? -EIO : 0; | ||
224 | } | ||
225 | |||
226 | static void spinner_end(struct spinner *spin) | 172 | static void spinner_end(struct spinner *spin) |
227 | { | 173 | { |
228 | *spin->batch = MI_BATCH_BUFFER_END; | 174 | *spin->batch = MI_BATCH_BUFFER_END; |
@@ -295,7 +241,7 @@ static int live_sanitycheck(void *arg) | |||
295 | } | 241 | } |
296 | 242 | ||
297 | spinner_end(&spin); | 243 | spinner_end(&spin); |
298 | if (flush_test(i915, I915_WAIT_LOCKED)) { | 244 | if (igt_flush_test(i915, I915_WAIT_LOCKED)) { |
299 | err = -EIO; | 245 | err = -EIO; |
300 | goto err_ctx; | 246 | goto err_ctx; |
301 | } | 247 | } |
@@ -307,7 +253,7 @@ err_ctx: | |||
307 | err_spin: | 253 | err_spin: |
308 | spinner_fini(&spin); | 254 | spinner_fini(&spin); |
309 | err_unlock: | 255 | err_unlock: |
310 | flush_test(i915, I915_WAIT_LOCKED); | 256 | igt_flush_test(i915, I915_WAIT_LOCKED); |
311 | mutex_unlock(&i915->drm.struct_mutex); | 257 | mutex_unlock(&i915->drm.struct_mutex); |
312 | return err; | 258 | return err; |
313 | } | 259 | } |
@@ -335,12 +281,12 @@ static int live_preempt(void *arg) | |||
335 | ctx_hi = kernel_context(i915); | 281 | ctx_hi = kernel_context(i915); |
336 | if (!ctx_hi) | 282 | if (!ctx_hi) |
337 | goto err_spin_lo; | 283 | goto err_spin_lo; |
338 | ctx_hi->priority = I915_CONTEXT_MAX_USER_PRIORITY; | 284 | ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY; |
339 | 285 | ||
340 | ctx_lo = kernel_context(i915); | 286 | ctx_lo = kernel_context(i915); |
341 | if (!ctx_lo) | 287 | if (!ctx_lo) |
342 | goto err_ctx_hi; | 288 | goto err_ctx_hi; |
343 | ctx_lo->priority = I915_CONTEXT_MIN_USER_PRIORITY; | 289 | ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY; |
344 | 290 | ||
345 | for_each_engine(engine, i915, id) { | 291 | for_each_engine(engine, i915, id) { |
346 | struct i915_request *rq; | 292 | struct i915_request *rq; |
@@ -380,7 +326,7 @@ static int live_preempt(void *arg) | |||
380 | 326 | ||
381 | spinner_end(&spin_hi); | 327 | spinner_end(&spin_hi); |
382 | spinner_end(&spin_lo); | 328 | spinner_end(&spin_lo); |
383 | if (flush_test(i915, I915_WAIT_LOCKED)) { | 329 | if (igt_flush_test(i915, I915_WAIT_LOCKED)) { |
384 | err = -EIO; | 330 | err = -EIO; |
385 | goto err_ctx_lo; | 331 | goto err_ctx_lo; |
386 | } | 332 | } |
@@ -396,7 +342,7 @@ err_spin_lo: | |||
396 | err_spin_hi: | 342 | err_spin_hi: |
397 | spinner_fini(&spin_hi); | 343 | spinner_fini(&spin_hi); |
398 | err_unlock: | 344 | err_unlock: |
399 | flush_test(i915, I915_WAIT_LOCKED); | 345 | igt_flush_test(i915, I915_WAIT_LOCKED); |
400 | mutex_unlock(&i915->drm.struct_mutex); | 346 | mutex_unlock(&i915->drm.struct_mutex); |
401 | return err; | 347 | return err; |
402 | } | 348 | } |
@@ -407,6 +353,7 @@ static int live_late_preempt(void *arg) | |||
407 | struct i915_gem_context *ctx_hi, *ctx_lo; | 353 | struct i915_gem_context *ctx_hi, *ctx_lo; |
408 | struct spinner spin_hi, spin_lo; | 354 | struct spinner spin_hi, spin_lo; |
409 | struct intel_engine_cs *engine; | 355 | struct intel_engine_cs *engine; |
356 | struct i915_sched_attr attr = {}; | ||
410 | enum intel_engine_id id; | 357 | enum intel_engine_id id; |
411 | int err = -ENOMEM; | 358 | int err = -ENOMEM; |
412 | 359 | ||
@@ -458,7 +405,8 @@ static int live_late_preempt(void *arg) | |||
458 | goto err_wedged; | 405 | goto err_wedged; |
459 | } | 406 | } |
460 | 407 | ||
461 | engine->schedule(rq, I915_PRIORITY_MAX); | 408 | attr.priority = I915_PRIORITY_MAX; |
409 | engine->schedule(rq, &attr); | ||
462 | 410 | ||
463 | if (!wait_for_spinner(&spin_hi, rq)) { | 411 | if (!wait_for_spinner(&spin_hi, rq)) { |
464 | pr_err("High priority context failed to preempt the low priority context\n"); | 412 | pr_err("High priority context failed to preempt the low priority context\n"); |
@@ -468,7 +416,7 @@ static int live_late_preempt(void *arg) | |||
468 | 416 | ||
469 | spinner_end(&spin_hi); | 417 | spinner_end(&spin_hi); |
470 | spinner_end(&spin_lo); | 418 | spinner_end(&spin_lo); |
471 | if (flush_test(i915, I915_WAIT_LOCKED)) { | 419 | if (igt_flush_test(i915, I915_WAIT_LOCKED)) { |
472 | err = -EIO; | 420 | err = -EIO; |
473 | goto err_ctx_lo; | 421 | goto err_ctx_lo; |
474 | } | 422 | } |
@@ -484,7 +432,7 @@ err_spin_lo: | |||
484 | err_spin_hi: | 432 | err_spin_hi: |
485 | spinner_fini(&spin_hi); | 433 | spinner_fini(&spin_hi); |
486 | err_unlock: | 434 | err_unlock: |
487 | flush_test(i915, I915_WAIT_LOCKED); | 435 | igt_flush_test(i915, I915_WAIT_LOCKED); |
488 | mutex_unlock(&i915->drm.struct_mutex); | 436 | mutex_unlock(&i915->drm.struct_mutex); |
489 | return err; | 437 | return err; |
490 | 438 | ||
@@ -503,5 +451,9 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915) | |||
503 | SUBTEST(live_preempt), | 451 | SUBTEST(live_preempt), |
504 | SUBTEST(live_late_preempt), | 452 | SUBTEST(live_late_preempt), |
505 | }; | 453 | }; |
454 | |||
455 | if (!HAS_EXECLISTS(i915)) | ||
456 | return 0; | ||
457 | |||
506 | return i915_subtests(tests, i915); | 458 | return i915_subtests(tests, i915); |
507 | } | 459 | } |
diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c new file mode 100644 index 000000000000..17444a3abbb9 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * SPDX-License-Identifier: MIT | ||
3 | * | ||
4 | * Copyright © 2018 Intel Corporation | ||
5 | */ | ||
6 | |||
7 | #include "../i915_selftest.h" | ||
8 | |||
9 | #include "mock_context.h" | ||
10 | |||
11 | static struct drm_i915_gem_object * | ||
12 | read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine) | ||
13 | { | ||
14 | struct drm_i915_gem_object *result; | ||
15 | struct i915_request *rq; | ||
16 | struct i915_vma *vma; | ||
17 | const u32 base = engine->mmio_base; | ||
18 | u32 srm, *cs; | ||
19 | int err; | ||
20 | int i; | ||
21 | |||
22 | result = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); | ||
23 | if (IS_ERR(result)) | ||
24 | return result; | ||
25 | |||
26 | i915_gem_object_set_cache_level(result, I915_CACHE_LLC); | ||
27 | |||
28 | cs = i915_gem_object_pin_map(result, I915_MAP_WB); | ||
29 | if (IS_ERR(cs)) { | ||
30 | err = PTR_ERR(cs); | ||
31 | goto err_obj; | ||
32 | } | ||
33 | memset(cs, 0xc5, PAGE_SIZE); | ||
34 | i915_gem_object_unpin_map(result); | ||
35 | |||
36 | vma = i915_vma_instance(result, &engine->i915->ggtt.base, NULL); | ||
37 | if (IS_ERR(vma)) { | ||
38 | err = PTR_ERR(vma); | ||
39 | goto err_obj; | ||
40 | } | ||
41 | |||
42 | err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL); | ||
43 | if (err) | ||
44 | goto err_obj; | ||
45 | |||
46 | rq = i915_request_alloc(engine, ctx); | ||
47 | if (IS_ERR(rq)) { | ||
48 | err = PTR_ERR(rq); | ||
49 | goto err_pin; | ||
50 | } | ||
51 | |||
52 | srm = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; | ||
53 | if (INTEL_GEN(ctx->i915) >= 8) | ||
54 | srm++; | ||
55 | |||
56 | cs = intel_ring_begin(rq, 4 * RING_MAX_NONPRIV_SLOTS); | ||
57 | if (IS_ERR(cs)) { | ||
58 | err = PTR_ERR(cs); | ||
59 | goto err_req; | ||
60 | } | ||
61 | |||
62 | for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) { | ||
63 | *cs++ = srm; | ||
64 | *cs++ = i915_mmio_reg_offset(RING_FORCE_TO_NONPRIV(base, i)); | ||
65 | *cs++ = i915_ggtt_offset(vma) + sizeof(u32) * i; | ||
66 | *cs++ = 0; | ||
67 | } | ||
68 | intel_ring_advance(rq, cs); | ||
69 | |||
70 | i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); | ||
71 | reservation_object_lock(vma->resv, NULL); | ||
72 | reservation_object_add_excl_fence(vma->resv, &rq->fence); | ||
73 | reservation_object_unlock(vma->resv); | ||
74 | |||
75 | i915_gem_object_get(result); | ||
76 | i915_gem_object_set_active_reference(result); | ||
77 | |||
78 | __i915_request_add(rq, true); | ||
79 | i915_vma_unpin(vma); | ||
80 | |||
81 | return result; | ||
82 | |||
83 | err_req: | ||
84 | i915_request_add(rq); | ||
85 | err_pin: | ||
86 | i915_vma_unpin(vma); | ||
87 | err_obj: | ||
88 | i915_gem_object_put(result); | ||
89 | return ERR_PTR(err); | ||
90 | } | ||
91 | |||
92 | static u32 get_whitelist_reg(const struct whitelist *w, unsigned int i) | ||
93 | { | ||
94 | return i < w->count ? i915_mmio_reg_offset(w->reg[i]) : w->nopid; | ||
95 | } | ||
96 | |||
97 | static void print_results(const struct whitelist *w, const u32 *results) | ||
98 | { | ||
99 | unsigned int i; | ||
100 | |||
101 | for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) { | ||
102 | u32 expected = get_whitelist_reg(w, i); | ||
103 | u32 actual = results[i]; | ||
104 | |||
105 | pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n", | ||
106 | i, expected, actual); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static int check_whitelist(const struct whitelist *w, | ||
111 | struct i915_gem_context *ctx, | ||
112 | struct intel_engine_cs *engine) | ||
113 | { | ||
114 | struct drm_i915_gem_object *results; | ||
115 | u32 *vaddr; | ||
116 | int err; | ||
117 | int i; | ||
118 | |||
119 | results = read_nonprivs(ctx, engine); | ||
120 | if (IS_ERR(results)) | ||
121 | return PTR_ERR(results); | ||
122 | |||
123 | err = i915_gem_object_set_to_cpu_domain(results, false); | ||
124 | if (err) | ||
125 | goto out_put; | ||
126 | |||
127 | vaddr = i915_gem_object_pin_map(results, I915_MAP_WB); | ||
128 | if (IS_ERR(vaddr)) { | ||
129 | err = PTR_ERR(vaddr); | ||
130 | goto out_put; | ||
131 | } | ||
132 | |||
133 | for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) { | ||
134 | u32 expected = get_whitelist_reg(w, i); | ||
135 | u32 actual = vaddr[i]; | ||
136 | |||
137 | if (expected != actual) { | ||
138 | print_results(w, vaddr); | ||
139 | pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n", | ||
140 | i, expected, actual); | ||
141 | |||
142 | err = -EINVAL; | ||
143 | break; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | i915_gem_object_unpin_map(results); | ||
148 | out_put: | ||
149 | i915_gem_object_put(results); | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | static int do_device_reset(struct intel_engine_cs *engine) | ||
154 | { | ||
155 | i915_reset(engine->i915, ENGINE_MASK(engine->id), NULL); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int do_engine_reset(struct intel_engine_cs *engine) | ||
160 | { | ||
161 | return i915_reset_engine(engine, NULL); | ||
162 | } | ||
163 | |||
164 | static int switch_to_scratch_context(struct intel_engine_cs *engine) | ||
165 | { | ||
166 | struct i915_gem_context *ctx; | ||
167 | struct i915_request *rq; | ||
168 | |||
169 | ctx = kernel_context(engine->i915); | ||
170 | if (IS_ERR(ctx)) | ||
171 | return PTR_ERR(ctx); | ||
172 | |||
173 | rq = i915_request_alloc(engine, ctx); | ||
174 | kernel_context_close(ctx); | ||
175 | if (IS_ERR(rq)) | ||
176 | return PTR_ERR(rq); | ||
177 | |||
178 | i915_request_add(rq); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int check_whitelist_across_reset(struct intel_engine_cs *engine, | ||
184 | int (*reset)(struct intel_engine_cs *), | ||
185 | const struct whitelist *w, | ||
186 | const char *name) | ||
187 | { | ||
188 | struct i915_gem_context *ctx; | ||
189 | int err; | ||
190 | |||
191 | ctx = kernel_context(engine->i915); | ||
192 | if (IS_ERR(ctx)) | ||
193 | return PTR_ERR(ctx); | ||
194 | |||
195 | err = check_whitelist(w, ctx, engine); | ||
196 | if (err) { | ||
197 | pr_err("Invalid whitelist *before* %s reset!\n", name); | ||
198 | goto out; | ||
199 | } | ||
200 | |||
201 | err = switch_to_scratch_context(engine); | ||
202 | if (err) | ||
203 | goto out; | ||
204 | |||
205 | err = reset(engine); | ||
206 | if (err) { | ||
207 | pr_err("%s reset failed\n", name); | ||
208 | goto out; | ||
209 | } | ||
210 | |||
211 | err = check_whitelist(w, ctx, engine); | ||
212 | if (err) { | ||
213 | pr_err("Whitelist not preserved in context across %s reset!\n", | ||
214 | name); | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | kernel_context_close(ctx); | ||
219 | |||
220 | ctx = kernel_context(engine->i915); | ||
221 | if (IS_ERR(ctx)) | ||
222 | return PTR_ERR(ctx); | ||
223 | |||
224 | err = check_whitelist(w, ctx, engine); | ||
225 | if (err) { | ||
226 | pr_err("Invalid whitelist *after* %s reset in fresh context!\n", | ||
227 | name); | ||
228 | goto out; | ||
229 | } | ||
230 | |||
231 | out: | ||
232 | kernel_context_close(ctx); | ||
233 | return err; | ||
234 | } | ||
235 | |||
236 | static int live_reset_whitelist(void *arg) | ||
237 | { | ||
238 | struct drm_i915_private *i915 = arg; | ||
239 | struct intel_engine_cs *engine = i915->engine[RCS]; | ||
240 | struct i915_gpu_error *error = &i915->gpu_error; | ||
241 | struct whitelist w; | ||
242 | int err = 0; | ||
243 | |||
244 | /* If we reset the gpu, we should not lose the RING_NONPRIV */ | ||
245 | |||
246 | if (!engine) | ||
247 | return 0; | ||
248 | |||
249 | if (!whitelist_build(engine, &w)) | ||
250 | return 0; | ||
251 | |||
252 | pr_info("Checking %d whitelisted registers (RING_NONPRIV)\n", w.count); | ||
253 | |||
254 | set_bit(I915_RESET_BACKOFF, &error->flags); | ||
255 | set_bit(I915_RESET_ENGINE + engine->id, &error->flags); | ||
256 | |||
257 | if (intel_has_reset_engine(i915)) { | ||
258 | err = check_whitelist_across_reset(engine, | ||
259 | do_engine_reset, &w, | ||
260 | "engine"); | ||
261 | if (err) | ||
262 | goto out; | ||
263 | } | ||
264 | |||
265 | if (intel_has_gpu_reset(i915)) { | ||
266 | err = check_whitelist_across_reset(engine, | ||
267 | do_device_reset, &w, | ||
268 | "device"); | ||
269 | if (err) | ||
270 | goto out; | ||
271 | } | ||
272 | |||
273 | out: | ||
274 | clear_bit(I915_RESET_ENGINE + engine->id, &error->flags); | ||
275 | clear_bit(I915_RESET_BACKOFF, &error->flags); | ||
276 | return err; | ||
277 | } | ||
278 | |||
279 | int intel_workarounds_live_selftests(struct drm_i915_private *i915) | ||
280 | { | ||
281 | static const struct i915_subtest tests[] = { | ||
282 | SUBTEST(live_reset_whitelist), | ||
283 | }; | ||
284 | int err; | ||
285 | |||
286 | mutex_lock(&i915->drm.struct_mutex); | ||
287 | err = i915_subtests(tests, i915); | ||
288 | mutex_unlock(&i915->drm.struct_mutex); | ||
289 | |||
290 | return err; | ||
291 | } | ||
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c index 78a89efa1119..26bf29d97007 100644 --- a/drivers/gpu/drm/i915/selftests/mock_engine.c +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c | |||
@@ -25,6 +25,11 @@ | |||
25 | #include "mock_engine.h" | 25 | #include "mock_engine.h" |
26 | #include "mock_request.h" | 26 | #include "mock_request.h" |
27 | 27 | ||
28 | struct mock_ring { | ||
29 | struct intel_ring base; | ||
30 | struct i915_timeline timeline; | ||
31 | }; | ||
32 | |||
28 | static struct mock_request *first_request(struct mock_engine *engine) | 33 | static struct mock_request *first_request(struct mock_engine *engine) |
29 | { | 34 | { |
30 | return list_first_entry_or_null(&engine->hw_queue, | 35 | return list_first_entry_or_null(&engine->hw_queue, |
@@ -71,14 +76,21 @@ static struct intel_ring * | |||
71 | mock_context_pin(struct intel_engine_cs *engine, | 76 | mock_context_pin(struct intel_engine_cs *engine, |
72 | struct i915_gem_context *ctx) | 77 | struct i915_gem_context *ctx) |
73 | { | 78 | { |
74 | i915_gem_context_get(ctx); | 79 | struct intel_context *ce = to_intel_context(ctx, engine); |
80 | |||
81 | if (!ce->pin_count++) | ||
82 | i915_gem_context_get(ctx); | ||
83 | |||
75 | return engine->buffer; | 84 | return engine->buffer; |
76 | } | 85 | } |
77 | 86 | ||
78 | static void mock_context_unpin(struct intel_engine_cs *engine, | 87 | static void mock_context_unpin(struct intel_engine_cs *engine, |
79 | struct i915_gem_context *ctx) | 88 | struct i915_gem_context *ctx) |
80 | { | 89 | { |
81 | i915_gem_context_put(ctx); | 90 | struct intel_context *ce = to_intel_context(ctx, engine); |
91 | |||
92 | if (!--ce->pin_count) | ||
93 | i915_gem_context_put(ctx); | ||
82 | } | 94 | } |
83 | 95 | ||
84 | static int mock_request_alloc(struct i915_request *request) | 96 | static int mock_request_alloc(struct i915_request *request) |
@@ -125,7 +137,7 @@ static void mock_submit_request(struct i915_request *request) | |||
125 | static struct intel_ring *mock_ring(struct intel_engine_cs *engine) | 137 | static struct intel_ring *mock_ring(struct intel_engine_cs *engine) |
126 | { | 138 | { |
127 | const unsigned long sz = PAGE_SIZE / 2; | 139 | const unsigned long sz = PAGE_SIZE / 2; |
128 | struct intel_ring *ring; | 140 | struct mock_ring *ring; |
129 | 141 | ||
130 | BUILD_BUG_ON(MIN_SPACE_FOR_ADD_REQUEST > sz); | 142 | BUILD_BUG_ON(MIN_SPACE_FOR_ADD_REQUEST > sz); |
131 | 143 | ||
@@ -133,14 +145,25 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine) | |||
133 | if (!ring) | 145 | if (!ring) |
134 | return NULL; | 146 | return NULL; |
135 | 147 | ||
136 | ring->size = sz; | 148 | i915_timeline_init(engine->i915, &ring->timeline, engine->name); |
137 | ring->effective_size = sz; | 149 | |
138 | ring->vaddr = (void *)(ring + 1); | 150 | ring->base.size = sz; |
151 | ring->base.effective_size = sz; | ||
152 | ring->base.vaddr = (void *)(ring + 1); | ||
153 | ring->base.timeline = &ring->timeline; | ||
139 | 154 | ||
140 | INIT_LIST_HEAD(&ring->request_list); | 155 | INIT_LIST_HEAD(&ring->base.request_list); |
141 | intel_ring_update_space(ring); | 156 | intel_ring_update_space(&ring->base); |
142 | 157 | ||
143 | return ring; | 158 | return &ring->base; |
159 | } | ||
160 | |||
161 | static void mock_ring_free(struct intel_ring *base) | ||
162 | { | ||
163 | struct mock_ring *ring = container_of(base, typeof(*ring), base); | ||
164 | |||
165 | i915_timeline_fini(&ring->timeline); | ||
166 | kfree(ring); | ||
144 | } | 167 | } |
145 | 168 | ||
146 | struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, | 169 | struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, |
@@ -155,12 +178,6 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, | |||
155 | if (!engine) | 178 | if (!engine) |
156 | return NULL; | 179 | return NULL; |
157 | 180 | ||
158 | engine->base.buffer = mock_ring(&engine->base); | ||
159 | if (!engine->base.buffer) { | ||
160 | kfree(engine); | ||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | /* minimal engine setup for requests */ | 181 | /* minimal engine setup for requests */ |
165 | engine->base.i915 = i915; | 182 | engine->base.i915 = i915; |
166 | snprintf(engine->base.name, sizeof(engine->base.name), "%s", name); | 183 | snprintf(engine->base.name, sizeof(engine->base.name), "%s", name); |
@@ -174,9 +191,7 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, | |||
174 | engine->base.emit_breadcrumb = mock_emit_breadcrumb; | 191 | engine->base.emit_breadcrumb = mock_emit_breadcrumb; |
175 | engine->base.submit_request = mock_submit_request; | 192 | engine->base.submit_request = mock_submit_request; |
176 | 193 | ||
177 | engine->base.timeline = | 194 | i915_timeline_init(i915, &engine->base.timeline, engine->base.name); |
178 | &i915->gt.global_timeline.engine[engine->base.id]; | ||
179 | |||
180 | intel_engine_init_breadcrumbs(&engine->base); | 195 | intel_engine_init_breadcrumbs(&engine->base); |
181 | engine->base.breadcrumbs.mock = true; /* prevent touching HW for irqs */ | 196 | engine->base.breadcrumbs.mock = true; /* prevent touching HW for irqs */ |
182 | 197 | ||
@@ -185,7 +200,17 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, | |||
185 | timer_setup(&engine->hw_delay, hw_delay_complete, 0); | 200 | timer_setup(&engine->hw_delay, hw_delay_complete, 0); |
186 | INIT_LIST_HEAD(&engine->hw_queue); | 201 | INIT_LIST_HEAD(&engine->hw_queue); |
187 | 202 | ||
203 | engine->base.buffer = mock_ring(&engine->base); | ||
204 | if (!engine->base.buffer) | ||
205 | goto err_breadcrumbs; | ||
206 | |||
188 | return &engine->base; | 207 | return &engine->base; |
208 | |||
209 | err_breadcrumbs: | ||
210 | intel_engine_fini_breadcrumbs(&engine->base); | ||
211 | i915_timeline_fini(&engine->base.timeline); | ||
212 | kfree(engine); | ||
213 | return NULL; | ||
189 | } | 214 | } |
190 | 215 | ||
191 | void mock_engine_flush(struct intel_engine_cs *engine) | 216 | void mock_engine_flush(struct intel_engine_cs *engine) |
@@ -217,10 +242,12 @@ void mock_engine_free(struct intel_engine_cs *engine) | |||
217 | GEM_BUG_ON(timer_pending(&mock->hw_delay)); | 242 | GEM_BUG_ON(timer_pending(&mock->hw_delay)); |
218 | 243 | ||
219 | if (engine->last_retired_context) | 244 | if (engine->last_retired_context) |
220 | engine->context_unpin(engine, engine->last_retired_context); | 245 | intel_context_unpin(engine->last_retired_context, engine); |
246 | |||
247 | mock_ring_free(engine->buffer); | ||
221 | 248 | ||
222 | intel_engine_fini_breadcrumbs(engine); | 249 | intel_engine_fini_breadcrumbs(engine); |
250 | i915_timeline_fini(&engine->timeline); | ||
223 | 251 | ||
224 | kfree(engine->buffer); | ||
225 | kfree(engine); | 252 | kfree(engine); |
226 | } | 253 | } |
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index e6d4b882599a..94baedfa0f74 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c | |||
@@ -44,6 +44,7 @@ void mock_device_flush(struct drm_i915_private *i915) | |||
44 | mock_engine_flush(engine); | 44 | mock_engine_flush(engine); |
45 | 45 | ||
46 | i915_retire_requests(i915); | 46 | i915_retire_requests(i915); |
47 | GEM_BUG_ON(i915->gt.active_requests); | ||
47 | } | 48 | } |
48 | 49 | ||
49 | static void mock_device_release(struct drm_device *dev) | 50 | static void mock_device_release(struct drm_device *dev) |
@@ -72,8 +73,8 @@ static void mock_device_release(struct drm_device *dev) | |||
72 | 73 | ||
73 | mutex_lock(&i915->drm.struct_mutex); | 74 | mutex_lock(&i915->drm.struct_mutex); |
74 | mock_fini_ggtt(i915); | 75 | mock_fini_ggtt(i915); |
75 | i915_gem_timeline_fini(&i915->gt.global_timeline); | ||
76 | mutex_unlock(&i915->drm.struct_mutex); | 76 | mutex_unlock(&i915->drm.struct_mutex); |
77 | WARN_ON(!list_empty(&i915->gt.timelines)); | ||
77 | 78 | ||
78 | destroy_workqueue(i915->wq); | 79 | destroy_workqueue(i915->wq); |
79 | 80 | ||
@@ -223,26 +224,25 @@ struct drm_i915_private *mock_gem_device(void) | |||
223 | if (!i915->priorities) | 224 | if (!i915->priorities) |
224 | goto err_dependencies; | 225 | goto err_dependencies; |
225 | 226 | ||
226 | mutex_lock(&i915->drm.struct_mutex); | ||
227 | INIT_LIST_HEAD(&i915->gt.timelines); | 227 | INIT_LIST_HEAD(&i915->gt.timelines); |
228 | err = i915_gem_timeline_init__global(i915); | 228 | INIT_LIST_HEAD(&i915->gt.active_rings); |
229 | if (err) { | 229 | INIT_LIST_HEAD(&i915->gt.closed_vma); |
230 | mutex_unlock(&i915->drm.struct_mutex); | 230 | |
231 | goto err_priorities; | 231 | mutex_lock(&i915->drm.struct_mutex); |
232 | } | ||
233 | 232 | ||
234 | mock_init_ggtt(i915); | 233 | mock_init_ggtt(i915); |
235 | mutex_unlock(&i915->drm.struct_mutex); | ||
236 | 234 | ||
237 | mkwrite_device_info(i915)->ring_mask = BIT(0); | 235 | mkwrite_device_info(i915)->ring_mask = BIT(0); |
238 | i915->engine[RCS] = mock_engine(i915, "mock", RCS); | 236 | i915->engine[RCS] = mock_engine(i915, "mock", RCS); |
239 | if (!i915->engine[RCS]) | 237 | if (!i915->engine[RCS]) |
240 | goto err_priorities; | 238 | goto err_unlock; |
241 | 239 | ||
242 | i915->kernel_context = mock_context(i915, NULL); | 240 | i915->kernel_context = mock_context(i915, NULL); |
243 | if (!i915->kernel_context) | 241 | if (!i915->kernel_context) |
244 | goto err_engine; | 242 | goto err_engine; |
245 | 243 | ||
244 | mutex_unlock(&i915->drm.struct_mutex); | ||
245 | |||
246 | WARN_ON(i915_gemfs_init(i915)); | 246 | WARN_ON(i915_gemfs_init(i915)); |
247 | 247 | ||
248 | return i915; | 248 | return i915; |
@@ -250,7 +250,8 @@ struct drm_i915_private *mock_gem_device(void) | |||
250 | err_engine: | 250 | err_engine: |
251 | for_each_engine(engine, i915, id) | 251 | for_each_engine(engine, i915, id) |
252 | mock_engine_free(engine); | 252 | mock_engine_free(engine); |
253 | err_priorities: | 253 | err_unlock: |
254 | mutex_unlock(&i915->drm.struct_mutex); | ||
254 | kmem_cache_destroy(i915->priorities); | 255 | kmem_cache_destroy(i915->priorities); |
255 | err_dependencies: | 256 | err_dependencies: |
256 | kmem_cache_destroy(i915->dependencies); | 257 | kmem_cache_destroy(i915->dependencies); |
diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index e96873f96116..36c112088940 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c | |||
@@ -76,7 +76,6 @@ mock_ppgtt(struct drm_i915_private *i915, | |||
76 | 76 | ||
77 | INIT_LIST_HEAD(&ppgtt->base.global_link); | 77 | INIT_LIST_HEAD(&ppgtt->base.global_link); |
78 | drm_mm_init(&ppgtt->base.mm, 0, ppgtt->base.total); | 78 | drm_mm_init(&ppgtt->base.mm, 0, ppgtt->base.total); |
79 | i915_gem_timeline_init(i915, &ppgtt->base.timeline, name); | ||
80 | 79 | ||
81 | ppgtt->base.clear_range = nop_clear_range; | 80 | ppgtt->base.clear_range = nop_clear_range; |
82 | ppgtt->base.insert_page = mock_insert_page; | 81 | ppgtt->base.insert_page = mock_insert_page; |
diff --git a/drivers/gpu/drm/i915/selftests/mock_timeline.c b/drivers/gpu/drm/i915/selftests/mock_timeline.c index 47b1f47c5812..dcf3b16f5a07 100644 --- a/drivers/gpu/drm/i915/selftests/mock_timeline.c +++ b/drivers/gpu/drm/i915/selftests/mock_timeline.c | |||
@@ -1,45 +1,28 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2017 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2017-2018 Intel Corporation | ||
23 | */ | 5 | */ |
24 | 6 | ||
7 | #include "../i915_timeline.h" | ||
8 | |||
25 | #include "mock_timeline.h" | 9 | #include "mock_timeline.h" |
26 | 10 | ||
27 | struct intel_timeline *mock_timeline(u64 context) | 11 | void mock_timeline_init(struct i915_timeline *timeline, u64 context) |
28 | { | 12 | { |
29 | static struct lock_class_key class; | 13 | timeline->fence_context = context; |
30 | struct intel_timeline *tl; | 14 | |
15 | spin_lock_init(&timeline->lock); | ||
31 | 16 | ||
32 | tl = kzalloc(sizeof(*tl), GFP_KERNEL); | 17 | init_request_active(&timeline->last_request, NULL); |
33 | if (!tl) | 18 | INIT_LIST_HEAD(&timeline->requests); |
34 | return NULL; | ||
35 | 19 | ||
36 | __intel_timeline_init(tl, NULL, context, &class, "mock"); | 20 | i915_syncmap_init(&timeline->sync); |
37 | 21 | ||
38 | return tl; | 22 | INIT_LIST_HEAD(&timeline->link); |
39 | } | 23 | } |
40 | 24 | ||
41 | void mock_timeline_destroy(struct intel_timeline *tl) | 25 | void mock_timeline_fini(struct i915_timeline *timeline) |
42 | { | 26 | { |
43 | __intel_timeline_fini(tl); | 27 | i915_timeline_fini(timeline); |
44 | kfree(tl); | ||
45 | } | 28 | } |
diff --git a/drivers/gpu/drm/i915/selftests/mock_timeline.h b/drivers/gpu/drm/i915/selftests/mock_timeline.h index c27ff4639b8b..b6deaa61110d 100644 --- a/drivers/gpu/drm/i915/selftests/mock_timeline.h +++ b/drivers/gpu/drm/i915/selftests/mock_timeline.h | |||
@@ -1,33 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2017 Intel Corporation | 2 | * SPDX-License-Identifier: MIT |
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | 3 | * |
4 | * Copyright © 2017-2018 Intel Corporation | ||
23 | */ | 5 | */ |
24 | 6 | ||
25 | #ifndef __MOCK_TIMELINE__ | 7 | #ifndef __MOCK_TIMELINE__ |
26 | #define __MOCK_TIMELINE__ | 8 | #define __MOCK_TIMELINE__ |
27 | 9 | ||
28 | #include "../i915_gem_timeline.h" | 10 | struct i915_timeline; |
29 | 11 | ||
30 | struct intel_timeline *mock_timeline(u64 context); | 12 | void mock_timeline_init(struct i915_timeline *timeline, u64 context); |
31 | void mock_timeline_destroy(struct intel_timeline *tl); | 13 | void mock_timeline_fini(struct i915_timeline *timeline); |
32 | 14 | ||
33 | #endif /* !__MOCK_TIMELINE__ */ | 15 | #endif /* !__MOCK_TIMELINE__ */ |
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 70f0c2535b87..bab70ff6e78b 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h | |||
@@ -349,6 +349,7 @@ | |||
349 | #define INTEL_KBL_GT2_IDS(info) \ | 349 | #define INTEL_KBL_GT2_IDS(info) \ |
350 | INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \ | 350 | INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \ |
351 | INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */ \ | 351 | INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */ \ |
352 | INTEL_VGA_DEVICE(0x591C, info), /* ULX GT2 */ \ | ||
352 | INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \ | 353 | INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \ |
353 | INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \ | 354 | INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \ |
354 | INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \ | 355 | INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \ |