提交 b8a71080 编写于 作者: D Dave Airlie

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: NDave 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
......@@ -1716,11 +1716,15 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
}
}
if (config->funcs->atomic_check)
if (config->funcs->atomic_check) {
ret = config->funcs->atomic_check(state->dev, state);
if (ret)
return ret;
if (ret) {
DRM_DEBUG_ATOMIC("atomic driver check for %p failed: %d\n",
state, ret);
return ret;
}
}
if (!state->allow_modeset) {
for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
......
......@@ -18,6 +18,10 @@ subdir-ccflags-y += $(call cc-disable-warning, type-limits)
subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers)
subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough)
subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)
# clang warnings
subdir-ccflags-y += $(call cc-disable-warning, sign-compare)
subdir-ccflags-y += $(call cc-disable-warning, sometimes-uninitialized)
subdir-ccflags-y += $(call cc-disable-warning, initializer-overrides)
subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
# Fine grained warnings disable
......@@ -67,11 +71,11 @@ i915-y += i915_cmd_parser.o \
i915_gem_shrinker.o \
i915_gem_stolen.o \
i915_gem_tiling.o \
i915_gem_timeline.o \
i915_gem_userptr.o \
i915_gemfs.o \
i915_query.o \
i915_request.o \
i915_timeline.o \
i915_trace_points.o \
i915_vma.o \
intel_breadcrumbs.o \
......@@ -154,7 +158,8 @@ i915-y += dvo_ch7017.o \
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
i915-$(CONFIG_DRM_I915_SELFTEST) += \
selftests/i915_random.o \
selftests/i915_selftest.o
selftests/i915_selftest.o \
selftests/igt_flush_test.o
# virtual gpu code
i915-y += i915_vgpu.o
......
......@@ -813,15 +813,31 @@ static inline bool is_force_nonpriv_mmio(unsigned int offset)
}
static int force_nonpriv_reg_handler(struct parser_exec_state *s,
unsigned int offset, unsigned int index)
unsigned int offset, unsigned int index, char *cmd)
{
struct intel_gvt *gvt = s->vgpu->gvt;
unsigned int data = cmd_val(s, index + 1);
unsigned int data;
u32 ring_base;
u32 nopid;
struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
if (!strcmp(cmd, "lri"))
data = cmd_val(s, index + 1);
else {
gvt_err("Unexpected forcenonpriv 0x%x write from cmd %s\n",
offset, cmd);
return -EINVAL;
}
ring_base = dev_priv->engine[s->ring_id]->mmio_base;
nopid = i915_mmio_reg_offset(RING_NOPID(ring_base));
if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data)) {
if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data) &&
data != nopid) {
gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n",
offset, data);
return -EPERM;
patch_value(s, cmd_ptr(s, index), nopid);
return 0;
}
return 0;
}
......@@ -869,7 +885,7 @@ static int cmd_reg_handler(struct parser_exec_state *s,
return -EINVAL;
if (is_force_nonpriv_mmio(offset) &&
force_nonpriv_reg_handler(s, offset, index))
force_nonpriv_reg_handler(s, offset, index, cmd))
return -EPERM;
if (offset == i915_mmio_reg_offset(DERRMR) ||
......@@ -1604,7 +1620,8 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s)
if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)
|| IS_KABYLAKE(gvt->dev_priv)) {
/* BDW decides privilege based on address space */
if (cmd_val(s, 0) & (1 << 8))
if (cmd_val(s, 0) & (1 << 8) &&
!(s->vgpu->scan_nonprivbb & (1 << s->ring_id)))
return 0;
}
return 1;
......@@ -1618,6 +1635,8 @@ static int find_bb_size(struct parser_exec_state *s, unsigned long *bb_size)
bool bb_end = false;
struct intel_vgpu *vgpu = s->vgpu;
u32 cmd;
struct intel_vgpu_mm *mm = (s->buf_addr_type == GTT_BUFFER) ?
s->vgpu->gtt.ggtt_mm : s->workload->shadow_mm;
*bb_size = 0;
......@@ -1629,18 +1648,22 @@ static int find_bb_size(struct parser_exec_state *s, unsigned long *bb_size)
cmd = cmd_val(s, 0);
info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
if (info == NULL) {
gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",
cmd, get_opcode(cmd, s->ring_id));
gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x, addr_type=%s, ring %d, workload=%p\n",
cmd, get_opcode(cmd, s->ring_id),
(s->buf_addr_type == PPGTT_BUFFER) ?
"ppgtt" : "ggtt", s->ring_id, s->workload);
return -EBADRQC;
}
do {
if (copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
if (copy_gma_to_hva(s->vgpu, mm,
gma, gma + 4, &cmd) < 0)
return -EFAULT;
info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
if (info == NULL) {
gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",
cmd, get_opcode(cmd, s->ring_id));
gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x, addr_type=%s, ring %d, workload=%p\n",
cmd, get_opcode(cmd, s->ring_id),
(s->buf_addr_type == PPGTT_BUFFER) ?
"ppgtt" : "ggtt", s->ring_id, s->workload);
return -EBADRQC;
}
......@@ -1666,6 +1689,9 @@ static int perform_bb_shadow(struct parser_exec_state *s)
unsigned long gma = 0;
unsigned long bb_size;
int ret = 0;
struct intel_vgpu_mm *mm = (s->buf_addr_type == GTT_BUFFER) ?
s->vgpu->gtt.ggtt_mm : s->workload->shadow_mm;
unsigned long gma_start_offset = 0;
/* get the start gm address of the batch buffer */
gma = get_gma_bb_from_cmd(s, 1);
......@@ -1680,8 +1706,24 @@ static int perform_bb_shadow(struct parser_exec_state *s)
if (!bb)
return -ENOMEM;
bb->ppgtt = (s->buf_addr_type == GTT_BUFFER) ? false : true;
/* the gma_start_offset stores the batch buffer's start gma's
* offset relative to page boundary. so for non-privileged batch
* buffer, the shadowed gem object holds exactly the same page
* layout as original gem object. This is for the convience of
* replacing the whole non-privilged batch buffer page to this
* shadowed one in PPGTT at the same gma address. (this replacing
* action is not implemented yet now, but may be necessary in
* future).
* for prileged batch buffer, we just change start gma address to
* that of shadowed page.
*/
if (bb->ppgtt)
gma_start_offset = gma & ~I915_GTT_PAGE_MASK;
bb->obj = i915_gem_object_create(s->vgpu->gvt->dev_priv,
roundup(bb_size, PAGE_SIZE));
roundup(bb_size + gma_start_offset, PAGE_SIZE));
if (IS_ERR(bb->obj)) {
ret = PTR_ERR(bb->obj);
goto err_free_bb;
......@@ -1702,9 +1744,9 @@ static int perform_bb_shadow(struct parser_exec_state *s)
bb->clflush &= ~CLFLUSH_BEFORE;
}
ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
ret = copy_gma_to_hva(s->vgpu, mm,
gma, gma + bb_size,
bb->va);
bb->va + gma_start_offset);
if (ret < 0) {
gvt_vgpu_err("fail to copy guest ring buffer\n");
ret = -EFAULT;
......@@ -1730,7 +1772,7 @@ static int perform_bb_shadow(struct parser_exec_state *s)
* buffer's gma in pair. After all, we don't want to pin the shadow
* buffer here (too early).
*/
s->ip_va = bb->va;
s->ip_va = bb->va + gma_start_offset;
s->ip_gma = gma;
return 0;
err_unmap:
......@@ -2469,15 +2511,18 @@ static int cmd_parser_exec(struct parser_exec_state *s)
info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
if (info == NULL) {
gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",
cmd, get_opcode(cmd, s->ring_id));
gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x, addr_type=%s, ring %d, workload=%p\n",
cmd, get_opcode(cmd, s->ring_id),
(s->buf_addr_type == PPGTT_BUFFER) ?
"ppgtt" : "ggtt", s->ring_id, s->workload);
return -EBADRQC;
}
s->info = info;
trace_gvt_command(vgpu->id, s->ring_id, s->ip_gma, s->ip_va,
cmd_length(s), s->buf_type);
cmd_length(s), s->buf_type, s->buf_addr_type,
s->workload, info->name);
if (info->handler) {
ret = info->handler(s);
......
......@@ -124,6 +124,68 @@ static int vgpu_mmio_diff_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff);
static int
vgpu_scan_nonprivbb_get(void *data, u64 *val)
{
struct intel_vgpu *vgpu = (struct intel_vgpu *)data;
*val = vgpu->scan_nonprivbb;
return 0;
}
/*
* set/unset bit engine_id of vgpu->scan_nonprivbb to turn on/off scanning
* of non-privileged batch buffer. e.g.
* if vgpu->scan_nonprivbb=3, then it will scan non-privileged batch buffer
* on engine 0 and 1.
*/
static int
vgpu_scan_nonprivbb_set(void *data, u64 val)
{
struct intel_vgpu *vgpu = (struct intel_vgpu *)data;
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
enum intel_engine_id id;
char buf[128], *s;
int len;
val &= (1 << I915_NUM_ENGINES) - 1;
if (vgpu->scan_nonprivbb == val)
return 0;
if (!val)
goto done;
len = sprintf(buf,
"gvt: vgpu %d turns on non-privileged batch buffers scanning on Engines:",
vgpu->id);
s = buf + len;
for (id = 0; id < I915_NUM_ENGINES; id++) {
struct intel_engine_cs *engine;
engine = dev_priv->engine[id];
if (engine && (val & (1 << id))) {
len = snprintf(s, 4, "%d, ", engine->id);
s += len;
} else
val &= ~(1 << id);
}
if (val)
sprintf(s, "low performance expected.");
pr_warn("%s\n", buf);
done:
vgpu->scan_nonprivbb = val;
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(vgpu_scan_nonprivbb_fops,
vgpu_scan_nonprivbb_get, vgpu_scan_nonprivbb_set,
"0x%llx\n");
/**
* intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU
* @vgpu: a vGPU
......@@ -151,6 +213,11 @@ int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu)
if (!ent)
return -ENOMEM;
ent = debugfs_create_file("scan_nonprivbb", 0644, vgpu->debugfs,
vgpu, &vgpu_scan_nonprivbb_fops);
if (!ent)
return -ENOMEM;
return 0;
}
......
......@@ -99,7 +99,6 @@ struct intel_vgpu_fence {
struct intel_vgpu_mmio {
void *vreg;
void *sreg;
bool disable_warn_untrack;
};
#define INTEL_GVT_MAX_BAR_NUM 4
......@@ -226,6 +225,7 @@ struct intel_vgpu {
struct completion vblank_done;
u32 scan_nonprivbb;
};
/* validating GM healthy status*/
......
......@@ -191,6 +191,8 @@ static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu,
unsigned int max_fence = vgpu_fence_sz(vgpu);
if (fence_num >= max_fence) {
gvt_vgpu_err("access oob fence reg %d/%d\n",
fence_num, max_fence);
/* When guest access oob fence regs without access
* pv_info first, we treat guest not supporting GVT,
......@@ -200,11 +202,6 @@ static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu,
enter_failsafe_mode(vgpu,
GVT_FAILSAFE_UNSUPPORTED_GUEST);
if (!vgpu->mmio.disable_warn_untrack) {
gvt_vgpu_err("found oob fence register access\n");
gvt_vgpu_err("total fence %d, access fence %d\n",
max_fence, fence_num);
}
memset(p_data, 0, bytes);
return -EINVAL;
}
......@@ -477,22 +474,28 @@ static int force_nonpriv_write(struct intel_vgpu *vgpu,
unsigned int offset, void *p_data, unsigned int bytes)
{
u32 reg_nonpriv = *(u32 *)p_data;
int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset);
u32 ring_base;
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
int ret = -EINVAL;
if ((bytes != 4) || ((offset & (bytes - 1)) != 0)) {
gvt_err("vgpu(%d) Invalid FORCE_NONPRIV offset %x(%dB)\n",
vgpu->id, offset, bytes);
if ((bytes != 4) || ((offset & (bytes - 1)) != 0) || ring_id < 0) {
gvt_err("vgpu(%d) ring %d Invalid FORCE_NONPRIV offset %x(%dB)\n",
vgpu->id, ring_id, offset, bytes);
return ret;
}
if (in_whitelist(reg_nonpriv)) {
ring_base = dev_priv->engine[ring_id]->mmio_base;
if (in_whitelist(reg_nonpriv) ||
reg_nonpriv == i915_mmio_reg_offset(RING_NOPID(ring_base))) {
ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data,
bytes);
} else {
gvt_err("vgpu(%d) Invalid FORCE_NONPRIV write %x\n",
vgpu->id, reg_nonpriv);
}
return ret;
} else
gvt_err("vgpu(%d) Invalid FORCE_NONPRIV write %x at offset %x\n",
vgpu->id, reg_nonpriv, offset);
return 0;
}
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,
*/
mmio_info = find_mmio_info(gvt, offset);
if (!mmio_info) {
if (!vgpu->mmio.disable_warn_untrack)
gvt_vgpu_err("untracked MMIO %08x len %d\n",
offset, bytes);
gvt_dbg_mmio("untracked MMIO %08x len %d\n", offset, bytes);
goto default_rw;
}
......
......@@ -244,8 +244,6 @@ void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr)
/* set the bit 0:2(Core C-State ) to C0 */
vgpu_vreg_t(vgpu, GEN6_GT_CORE_STATUS) = 0;
vgpu->mmio.disable_warn_untrack = false;
} else {
#define GVT_GEN8_MMIO_RESET_OFFSET (0x44200)
/* only reset the engine related, so starting with 0x44200
......
......@@ -448,7 +448,7 @@ static void switch_mocs(struct intel_vgpu *pre, struct intel_vgpu *next,
bool is_inhibit_context(struct i915_gem_context *ctx, int ring_id)
{
u32 *reg_state = ctx->engine[ring_id].lrc_reg_state;
u32 *reg_state = ctx->__engine[ring_id].lrc_reg_state;
u32 inhibit_mask =
_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
......
......@@ -53,7 +53,6 @@ struct vgpu_sched_data {
bool active;
ktime_t sched_in_time;
ktime_t sched_out_time;
ktime_t sched_time;
ktime_t left_ts;
ktime_t allocated_ts;
......@@ -66,17 +65,22 @@ struct gvt_sched_data {
struct hrtimer timer;
unsigned long period;
struct list_head lru_runq_head;
ktime_t expire_time;
};
static void vgpu_update_timeslice(struct intel_vgpu *pre_vgpu)
static void vgpu_update_timeslice(struct intel_vgpu *vgpu, ktime_t cur_time)
{
ktime_t delta_ts;
struct vgpu_sched_data *vgpu_data = pre_vgpu->sched_data;
struct vgpu_sched_data *vgpu_data;
delta_ts = vgpu_data->sched_out_time - vgpu_data->sched_in_time;
if (!vgpu || vgpu == vgpu->gvt->idle_vgpu)
return;
vgpu_data->sched_time += delta_ts;
vgpu_data->left_ts -= delta_ts;
vgpu_data = vgpu->sched_data;
delta_ts = ktime_sub(cur_time, vgpu_data->sched_in_time);
vgpu_data->sched_time = ktime_add(vgpu_data->sched_time, delta_ts);
vgpu_data->left_ts = ktime_sub(vgpu_data->left_ts, delta_ts);
vgpu_data->sched_in_time = cur_time;
}
#define GVT_TS_BALANCE_PERIOD_MS 100
......@@ -150,11 +154,7 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
}
cur_time = ktime_get();
if (scheduler->current_vgpu) {
vgpu_data = scheduler->current_vgpu->sched_data;
vgpu_data->sched_out_time = cur_time;
vgpu_update_timeslice(scheduler->current_vgpu);
}
vgpu_update_timeslice(scheduler->current_vgpu, cur_time);
vgpu_data = scheduler->next_vgpu->sched_data;
vgpu_data->sched_in_time = cur_time;
......@@ -226,17 +226,22 @@ static void tbs_sched_func(struct gvt_sched_data *sched_data)
void intel_gvt_schedule(struct intel_gvt *gvt)
{
struct gvt_sched_data *sched_data = gvt->scheduler.sched_data;
static uint64_t timer_check;
ktime_t cur_time;
mutex_lock(&gvt->lock);
cur_time = ktime_get();
if (test_and_clear_bit(INTEL_GVT_REQUEST_SCHED,
(void *)&gvt->service_request)) {
if (!(timer_check++ % GVT_TS_BALANCE_PERIOD_MS))
if (cur_time >= sched_data->expire_time) {
gvt_balance_timeslice(sched_data);
sched_data->expire_time = ktime_add_ms(
cur_time, GVT_TS_BALANCE_PERIOD_MS);
}
}
clear_bit(INTEL_GVT_REQUEST_EVENT_SCHED, (void *)&gvt->service_request);
vgpu_update_timeslice(gvt->scheduler.current_vgpu, cur_time);
tbs_sched_func(sched_data);
mutex_unlock(&gvt->lock);
......
......@@ -58,7 +58,7 @@ static void update_shadow_pdps(struct intel_vgpu_workload *workload)
int ring_id = workload->ring_id;
struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx;
struct drm_i915_gem_object *ctx_obj =
shadow_ctx->engine[ring_id].state->obj;
shadow_ctx->__engine[ring_id].state->obj;
struct execlist_ring_context *shadow_ring_context;
struct page *page;
......@@ -97,7 +97,7 @@ static void sr_oa_regs(struct intel_vgpu_workload *workload,
i915_mmio_reg_offset(EU_PERF_CNTL6),
};
if (!workload || !reg_state || workload->ring_id != RCS)
if (workload->ring_id != RCS)
return;
if (save) {
......@@ -130,7 +130,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
int ring_id = workload->ring_id;
struct i915_gem_context *shadow_ctx = vgpu->submission.shadow_ctx;
struct drm_i915_gem_object *ctx_obj =
shadow_ctx->engine[ring_id].state->obj;
shadow_ctx->__engine[ring_id].state->obj;
struct execlist_ring_context *shadow_ring_context;
struct page *page;
void *dst;
......@@ -283,7 +283,7 @@ static int shadow_context_status_change(struct notifier_block *nb,
static void shadow_context_descriptor_update(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct intel_context *ce = &ctx->engine[engine->id];
struct intel_context *ce = to_intel_context(ctx, engine);
u64 desc = 0;
desc = ce->lrc_desc;
......@@ -389,7 +389,7 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
* shadow_ctx pages invalid. So gvt need to pin itself. After update
* the guest context, gvt can unpin the shadow_ctx safely.
*/
ring = engine->context_pin(engine, shadow_ctx);
ring = intel_context_pin(shadow_ctx, engine);
if (IS_ERR(ring)) {
ret = PTR_ERR(ring);
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)
return 0;
err_unpin:
engine->context_unpin(engine, shadow_ctx);
intel_context_unpin(shadow_ctx, engine);
err_shadow:
release_shadow_wa_ctx(&workload->wa_ctx);
err_scan:
......@@ -437,7 +437,7 @@ static int intel_gvt_generate_request(struct intel_vgpu_workload *workload)
return 0;
err_unpin:
engine->context_unpin(engine, shadow_ctx);
intel_context_unpin(shadow_ctx, engine);
release_shadow_wa_ctx(&workload->wa_ctx);
return ret;
}
......@@ -452,12 +452,6 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)
int ret;
list_for_each_entry(bb, &workload->shadow_bb, list) {
bb->vma = i915_gem_object_ggtt_pin(bb->obj, NULL, 0, 0, 0);
if (IS_ERR(bb->vma)) {
ret = PTR_ERR(bb->vma);
goto err;
}
/* For privilge batch buffer and not wa_ctx, the bb_start_cmd_va
* is only updated into ring_scan_buffer, not real ring address
* 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)
bb->bb_start_cmd_va = workload->shadow_ring_buffer_va
+ bb->bb_offset;
/* relocate shadow batch buffer */
bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma);
if (gmadr_bytes == 8)
bb->bb_start_cmd_va[2] = 0;
if (bb->ppgtt) {
/* for non-priv bb, scan&shadow is only for
* debugging purpose, so the content of shadow bb
* is the same as original bb. Therefore,
* here, rather than switch to shadow bb's gma
* address, we directly use original batch buffer's
* gma address, and send original bb to hardware
* directly
*/
if (bb->clflush & CLFLUSH_AFTER) {
drm_clflush_virt_range(bb->va,
bb->obj->base.size);
bb->clflush &= ~CLFLUSH_AFTER;
}
i915_gem_obj_finish_shmem_access(bb->obj);
bb->accessing = false;
} else {
bb->vma = i915_gem_object_ggtt_pin(bb->obj,
NULL, 0, 0, 0);
if (IS_ERR(bb->vma)) {
ret = PTR_ERR(bb->vma);
goto err;
}
/* No one is going to touch shadow bb from now on. */
if (bb->clflush & CLFLUSH_AFTER) {
drm_clflush_virt_range(bb->va, bb->obj->base.size);
bb->clflush &= ~CLFLUSH_AFTER;
}
/* relocate shadow batch buffer */
bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma);
if (gmadr_bytes == 8)
bb->bb_start_cmd_va[2] = 0;
ret = i915_gem_object_set_to_gtt_domain(bb->obj, false);
if (ret)
goto err;
/* No one is going to touch shadow bb from now on. */
if (bb->clflush & CLFLUSH_AFTER) {
drm_clflush_virt_range(bb->va,
bb->obj->base.size);
bb->clflush &= ~CLFLUSH_AFTER;
}
i915_gem_obj_finish_shmem_access(bb->obj);
bb->accessing = false;
ret = i915_gem_object_set_to_gtt_domain(bb->obj,
false);
if (ret)
goto err;
i915_vma_move_to_active(bb->vma, workload->req, 0);
i915_gem_obj_finish_shmem_access(bb->obj);
bb->accessing = false;
i915_vma_move_to_active(bb->vma, workload->req, 0);
}
}
return 0;
err:
......@@ -504,7 +526,7 @@ static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx)
struct intel_vgpu_submission *s = &workload->vgpu->submission;
struct i915_gem_context *shadow_ctx = s->shadow_ctx;
struct drm_i915_gem_object *ctx_obj =
shadow_ctx->engine[ring_id].state->obj;
shadow_ctx->__engine[ring_id].state->obj;
struct execlist_ring_context *shadow_ring_context;
struct page *page;
......@@ -666,7 +688,7 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
ret = prepare_workload(workload);
if (ret) {
engine->context_unpin(engine, shadow_ctx);
intel_context_unpin(shadow_ctx, engine);
goto out;
}
......@@ -749,7 +771,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload)
struct i915_gem_context *shadow_ctx = s->shadow_ctx;
int ring_id = workload->ring_id;
struct drm_i915_gem_object *ctx_obj =
shadow_ctx->engine[ring_id].state->obj;
shadow_ctx->__engine[ring_id].state->obj;
struct execlist_ring_context *shadow_ring_context;
struct page *page;
void *src;
......@@ -876,7 +898,7 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
}
mutex_lock(&dev_priv->drm.struct_mutex);
/* unpin shadow ctx as the shadow_ctx update is done */
engine->context_unpin(engine, s->shadow_ctx);
intel_context_unpin(s->shadow_ctx, engine);
mutex_unlock(&dev_priv->drm.struct_mutex);
}
......@@ -1134,9 +1156,6 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu)
if (IS_ERR(s->shadow_ctx))
return PTR_ERR(s->shadow_ctx);
if (HAS_LOGICAL_RING_PREEMPTION(vgpu->gvt->dev_priv))
s->shadow_ctx->priority = INT_MAX;
bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES);
s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload",
......
......@@ -125,6 +125,7 @@ struct intel_vgpu_shadow_bb {
unsigned int clflush;
bool accessing;
unsigned long bb_offset;
bool ppgtt;
};
#define workload_q_head(vgpu, ring_id) \
......
......@@ -224,19 +224,25 @@ TRACE_EVENT(oos_sync,
TP_printk("%s", __entry->buf)
);
#define GVT_CMD_STR_LEN 40
TRACE_EVENT(gvt_command,
TP_PROTO(u8 vgpu_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, u32 cmd_len,
u32 buf_type),
TP_PROTO(u8 vgpu_id, u8 ring_id, u32 ip_gma, u32 *cmd_va,
u32 cmd_len, u32 buf_type, u32 buf_addr_type,
void *workload, char *cmd_name),
TP_ARGS(vgpu_id, ring_id, ip_gma, cmd_va, cmd_len, buf_type),
TP_ARGS(vgpu_id, ring_id, ip_gma, cmd_va, cmd_len, buf_type,
buf_addr_type, workload, cmd_name),
TP_STRUCT__entry(
__field(u8, vgpu_id)
__field(u8, ring_id)
__field(u32, ip_gma)
__field(u32, buf_type)
__field(u32, buf_addr_type)
__field(u32, cmd_len)
__field(void*, workload)
__dynamic_array(u32, raw_cmd, cmd_len)
__array(char, cmd_name, GVT_CMD_STR_LEN)
),
TP_fast_assign(
......@@ -244,17 +250,25 @@ TRACE_EVENT(gvt_command,
__entry->ring_id = ring_id;
__entry->ip_gma = ip_gma;
__entry->buf_type = buf_type;
__entry->buf_addr_type = buf_addr_type;
__entry->cmd_len = cmd_len;
__entry->workload = workload;
snprintf(__entry->cmd_name, GVT_CMD_STR_LEN, "%s", cmd_name);
memcpy(__get_dynamic_array(raw_cmd), cmd_va, cmd_len * sizeof(*cmd_va));
),
TP_printk("vgpu%d ring %d: buf_type %u, ip_gma %08x, raw cmd %s",
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",
__entry->vgpu_id,
__entry->ring_id,
__entry->buf_addr_type,
__entry->buf_type,
__entry->ip_gma,
__print_array(__get_dynamic_array(raw_cmd), __entry->cmd_len, 4))
__entry->cmd_name,
__entry->cmd_len,
__print_array(__get_dynamic_array(raw_cmd),
__entry->cmd_len, 4),
__entry->workload)
);
#define GVT_TEMP_STR_LEN 10
......
......@@ -377,16 +377,19 @@ static void print_batch_pool_stats(struct seq_file *m,
print_file_stats(m, "[k]batch pool", stats);
}
static int per_file_ctx_stats(int id, void *ptr, void *data)
static int per_file_ctx_stats(int idx, void *ptr, void *data)
{
struct i915_gem_context *ctx = ptr;
int n;
struct intel_engine_cs *engine;
enum intel_engine_id id;
for_each_engine(engine, ctx->i915, id) {
struct intel_context *ce = to_intel_context(ctx, engine);
for (n = 0; n < ARRAY_SIZE(ctx->engine); n++) {
if (ctx->engine[n].state)
per_file_stats(0, ctx->engine[n].state->obj, data);
if (ctx->engine[n].ring)
per_file_stats(0, ctx->engine[n].ring->vma->obj, data);
if (ce->state)
per_file_stats(0, ce->state->obj, data);
if (ce->ring)
per_file_stats(0, ce->ring->vma->obj, data);
}
return 0;
......@@ -1340,10 +1343,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
struct rb_node *rb;
seq_printf(m, "%s:\n", engine->name);
seq_printf(m, "\tseqno = %x [current %x, last %x], inflight %d\n",
seq_printf(m, "\tseqno = %x [current %x, last %x]\n",
engine->hangcheck.seqno, seqno[id],
intel_engine_last_submit(engine),
engine->timeline->inflight_seqnos);
intel_engine_last_submit(engine));
seq_printf(m, "\twaiters? %s, fake irq active? %s, stalled? %s\n",
yesno(intel_engine_has_waiter(engine)),
yesno(test_bit(engine->id,
......@@ -1960,7 +1962,8 @@ static int i915_context_status(struct seq_file *m, void *unused)
seq_putc(m, '\n');
for_each_engine(engine, dev_priv, id) {
struct intel_context *ce = &ctx->engine[engine->id];
struct intel_context *ce =
to_intel_context(ctx, engine);
seq_printf(m, "%s: ", engine->name);
if (ce->state)
......@@ -2603,6 +2606,26 @@ static const char *psr2_live_status(u32 val)
return "unknown";
}
static const char *psr_sink_status(u8 val)
{
static const char * const sink_status[] = {
"inactive",
"transition to active, capture and display",
"active, display from RFB",
"active, capture and display on sink device timings",
"transition to inactive, capture and display, timing re-sync",
"reserved",
"reserved",
"sink internal error"
};
val &= DP_PSR_SINK_STATE_MASK;
if (val < ARRAY_SIZE(sink_status))
return sink_status[val];
return "unknown";
}
static int i915_edp_psr_status(struct seq_file *m, void *data)
{
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)
seq_printf(m, "EDP_PSR2_STATUS: %x [%s]\n",
psr2, psr2_live_status(psr2));
}
if (dev_priv->psr.enabled) {
struct drm_dp_aux *aux = &dev_priv->psr.enabled->aux;
u8 val;
if (drm_dp_dpcd_readb(aux, DP_PSR_STATUS, &val) == 1)
seq_printf(m, "Sink PSR status: 0x%x [%s]\n", val,
psr_sink_status(val));
}
mutex_unlock(&dev_priv->psr.lock);
if (READ_ONCE(dev_priv->psr.debug)) {
seq_printf(m, "Last attempted entry at: %lld\n",
dev_priv->psr.last_entry_attempt);
seq_printf(m, "Last exit at: %lld\n",
dev_priv->psr.last_exit);
}
intel_runtime_pm_put(dev_priv);
return 0;
}
static int
i915_edp_psr_debug_set(void *data, u64 val)
{
struct drm_i915_private *dev_priv = data;
if (!CAN_PSR(dev_priv))
return -ENODEV;
DRM_DEBUG_KMS("PSR debug %s\n", enableddisabled(val));
intel_runtime_pm_get(dev_priv);
intel_psr_irq_control(dev_priv, !!val);
intel_runtime_pm_put(dev_priv);
return 0;
}
static int
i915_edp_psr_debug_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
if (!CAN_PSR(dev_priv))
return -ENODEV;
*val = READ_ONCE(dev_priv->psr.debug);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
i915_edp_psr_debug_get, i915_edp_psr_debug_set,
"%llu\n");
static int i915_sink_crc(struct seq_file *m, void *data)
{
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)
seq_printf(m, " fp0: 0x%08x\n", pll->state.hw_state.fp0);
seq_printf(m, " fp1: 0x%08x\n", pll->state.hw_state.fp1);
seq_printf(m, " wrpll: 0x%08x\n", pll->state.hw_state.wrpll);
seq_printf(m, " cfgcr0: 0x%08x\n", pll->state.hw_state.cfgcr0);
seq_printf(m, " cfgcr1: 0x%08x\n", pll->state.hw_state.cfgcr1);
seq_printf(m, " mg_refclkin_ctl: 0x%08x\n",
pll->state.hw_state.mg_refclkin_ctl);
seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
pll->state.hw_state.mg_clktop2_coreclkctl1);
seq_printf(m, " mg_clktop2_hsclkctl: 0x%08x\n",
pll->state.hw_state.mg_clktop2_hsclkctl);
seq_printf(m, " mg_pll_div0: 0x%08x\n",
pll->state.hw_state.mg_pll_div0);
seq_printf(m, " mg_pll_div1: 0x%08x\n",
pll->state.hw_state.mg_pll_div1);
seq_printf(m, " mg_pll_lf: 0x%08x\n",
pll->state.hw_state.mg_pll_lf);
seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
pll->state.hw_state.mg_pll_frac_lock);
seq_printf(m, " mg_pll_ssc: 0x%08x\n",
pll->state.hw_state.mg_pll_ssc);
seq_printf(m, " mg_pll_bias: 0x%08x\n",
pll->state.hw_state.mg_pll_bias);
seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
pll->state.hw_state.mg_pll_tdc_coldst_bias);
}
drm_modeset_unlock_all(dev);
......@@ -3304,24 +3398,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
static int i915_wa_registers(struct seq_file *m, void *unused)
{
int i;
int ret;
struct intel_engine_cs *engine;
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct drm_device *dev = &dev_priv->drm;
struct i915_workarounds *workarounds = &dev_priv->workarounds;
enum intel_engine_id id;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
int i;
intel_runtime_pm_get(dev_priv);
seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
for_each_engine(engine, dev_priv, id)
seq_printf(m, "HW whitelist count for %s: %d\n",
engine->name, workarounds->hw_whitelist_count[id]);
for (i = 0; i < workarounds->count; ++i) {
i915_reg_t addr;
u32 mask, value, read;
......@@ -3337,7 +3420,6 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
}
intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex);
return 0;
}
......@@ -4176,119 +4258,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops,
i915_drop_caches_get, i915_drop_caches_set,
"0x%08llx\n");
static int
i915_max_freq_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
if (INTEL_GEN(dev_priv) < 6)
return -ENODEV;
*val = intel_gpu_freq(dev_priv, dev_priv->gt_pm.rps.max_freq_softlimit);
return 0;
}
static int
i915_max_freq_set(void *data, u64 val)
{
struct drm_i915_private *dev_priv = data;
struct intel_rps *rps = &dev_priv->gt_pm.rps;
u32 hw_max, hw_min;
int ret;
if (INTEL_GEN(dev_priv) < 6)
return -ENODEV;
DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val);
ret = mutex_lock_interruptible(&dev_priv->pcu_lock);
if (ret)
return ret;
/*
* Turbo will still be enabled, but won't go above the set value.
*/
val = intel_freq_opcode(dev_priv, val);
hw_max = rps->max_freq;
hw_min = rps->min_freq;
if (val < hw_min || val > hw_max || val < rps->min_freq_softlimit) {
mutex_unlock(&dev_priv->pcu_lock);
return -EINVAL;
}
rps->max_freq_softlimit = val;
if (intel_set_rps(dev_priv, val))
DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n");
mutex_unlock(&dev_priv->pcu_lock);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_max_freq_fops,
i915_max_freq_get, i915_max_freq_set,
"%llu\n");
static int
i915_min_freq_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
if (INTEL_GEN(dev_priv) < 6)
return -ENODEV;
*val = intel_gpu_freq(dev_priv, dev_priv->gt_pm.rps.min_freq_softlimit);
return 0;
}
static int
i915_min_freq_set(void *data, u64 val)
{
struct drm_i915_private *dev_priv = data;
struct intel_rps *rps = &dev_priv->gt_pm.rps;
u32 hw_max, hw_min;
int ret;
if (INTEL_GEN(dev_priv) < 6)
return -ENODEV;
DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val);
ret = mutex_lock_interruptible(&dev_priv->pcu_lock);
if (ret)
return ret;
/*
* Turbo will still be enabled, but won't go below the set value.
*/
val = intel_freq_opcode(dev_priv, val);
hw_max = rps->max_freq;
hw_min = rps->min_freq;
if (val < hw_min ||
val > hw_max || val > rps->max_freq_softlimit) {
mutex_unlock(&dev_priv->pcu_lock);
return -EINVAL;
}
rps->min_freq_softlimit = val;
if (intel_set_rps(dev_priv, val))
DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n");
mutex_unlock(&dev_priv->pcu_lock);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops,
i915_min_freq_get, i915_min_freq_set,
"%llu\n");
static int
i915_cache_sharing_get(void *data, u64 *val)
{
......@@ -4850,8 +4819,6 @@ static const struct i915_debugfs_files {
const struct file_operations *fops;
} i915_debugfs_files[] = {
{"i915_wedged", &i915_wedged_fops},
{"i915_max_freq", &i915_max_freq_fops},
{"i915_min_freq", &i915_min_freq_fops},
{"i915_cache_sharing", &i915_cache_sharing_fops},
{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
{"i915_ring_test_irq", &i915_ring_test_irq_fops},
......@@ -4874,7 +4841,8 @@ static const struct i915_debugfs_files {
{"i915_guc_log_relay", &i915_guc_log_relay_fops},
{"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops},
{"i915_ipc_status", &i915_ipc_status_fops},
{"i915_drrs_ctl", &i915_drrs_ctl_fops}
{"i915_drrs_ctl", &i915_drrs_ctl_fops},
{"i915_edp_psr_debug", &i915_edp_psr_debug_fops}
};
int i915_debugfs_register(struct drm_i915_private *dev_priv)
......
......@@ -101,7 +101,13 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
__builtin_return_address(0), &vaf);
if (is_error && !shown_bug_once) {
dev_notice(kdev, "%s", FDO_BUG_MSG);
/*
* Ask the user to file a bug report for the error, except
* if they may have caused the bug by fiddling with unsafe
* module parameters.
*/
if (!test_taint(TAINT_USER))
dev_notice(kdev, "%s", FDO_BUG_MSG);
shown_bug_once = true;
}
......@@ -2468,10 +2474,13 @@ static void vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv,
/*
* RC6 transitioning can be delayed up to 2 msec (see
* valleyview_enable_rps), use 3 msec for safety.
*
* This can fail to turn off the rc6 if the GPU is stuck after a failed
* reset and we are trying to force the machine to sleep.
*/
if (vlv_wait_for_pw_status(dev_priv, mask, val))
DRM_ERROR("timeout waiting for GT wells to go %s\n",
onoff(wait_for_on));
DRM_DEBUG_DRIVER("timeout waiting for GT wells to go %s\n",
onoff(wait_for_on));
}
static void vlv_check_no_gt_access(struct drm_i915_private *dev_priv)
......
......@@ -72,9 +72,10 @@
#include "i915_gem_fence_reg.h"
#include "i915_gem_object.h"
#include "i915_gem_gtt.h"
#include "i915_gem_timeline.h"
#include "i915_gpu_error.h"
#include "i915_request.h"
#include "i915_scheduler.h"
#include "i915_timeline.h"
#include "i915_vma.h"
#include "intel_gvt.h"
......@@ -84,8 +85,8 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20180413"
#define DRIVER_TIMESTAMP 1523611258
#define DRIVER_DATE "20180514"
#define DRIVER_TIMESTAMP 1526300884
/* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and
* WARN_ON()) for hw state sanity checks to check for unexpected conditions
......@@ -609,6 +610,9 @@ struct i915_psr {
bool has_hw_tracking;
bool psr2_enabled;
u8 sink_sync_latency;
bool debug;
ktime_t last_entry_attempt;
ktime_t last_exit;
void (*enable_source)(struct intel_dp *,
const struct intel_crtc_state *);
......@@ -1069,6 +1073,7 @@ struct intel_vbt_data {
} edp;
struct {
bool enable;
bool full_link;
bool require_aux_wakeup;
int idle_frames;
......@@ -1185,6 +1190,7 @@ struct skl_ddb_allocation {
/* packed/y */
struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES];
struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES];
u8 enabled_slices; /* GEN11 has configurable 2 slices */
};
struct skl_ddb_values {
......@@ -1297,7 +1303,6 @@ struct i915_wa_reg {
struct i915_workarounds {
struct i915_wa_reg reg[I915_MAX_WA_REGS];
u32 count;
u32 hw_whitelist_count[I915_NUM_ENGINES];
};
struct i915_virtual_gpu {
......@@ -2056,8 +2061,11 @@ struct drm_i915_private {
void (*cleanup_engine)(struct intel_engine_cs *engine);
struct list_head timelines;
struct i915_gem_timeline global_timeline;
struct list_head active_rings;
struct list_head closed_vma;
u32 active_requests;
u32 request_serial;
/**
* Is the GPU currently considered idle, or busy executing
......@@ -2462,6 +2470,15 @@ intel_info(const struct drm_i915_private *dev_priv)
#define IS_CNL_REVID(p, since, until) \
(IS_CANNONLAKE(p) && IS_REVID(p, since, until))
#define ICL_REVID_A0 0x0
#define ICL_REVID_A2 0x1
#define ICL_REVID_B0 0x3
#define ICL_REVID_B2 0x4
#define ICL_REVID_C0 0x5
#define IS_ICL_REVID(p, since, until) \
(IS_ICELAKE(p) && IS_REVID(p, since, until))
/*
* The genX designation typically refers to the render engine, so render
* 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,
struct intel_rps_client *rps);
int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
unsigned int flags,
int priority);
const struct i915_sched_attr *attr);
#define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX
int __must_check
......@@ -3228,16 +3245,6 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
return ctx;
}
static inline struct intel_timeline *
i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct i915_address_space *vm;
vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base;
return &vm->timeline.engine[engine->id];
}
int i915_perf_open_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
......
......@@ -141,6 +141,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
{
lockdep_assert_held(&i915->drm.struct_mutex);
GEM_BUG_ON(i915->gt.active_requests);
GEM_BUG_ON(!list_empty(&i915->gt.active_rings));
if (!i915->gt.awake)
return I915_EPOCH_INVALID;
......@@ -161,9 +162,10 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
synchronize_irq(i915->drm.irq);
intel_engines_park(i915);
i915_gem_timelines_park(i915);
i915_timelines_park(i915);
i915_pmu_gt_parked(i915);
i915_vma_parked(i915);
i915->gt.awake = false;
......@@ -564,7 +566,8 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
return timeout;
}
static void __fence_set_priority(struct dma_fence *fence, int prio)
static void __fence_set_priority(struct dma_fence *fence,
const struct i915_sched_attr *attr)
{
struct i915_request *rq;
struct intel_engine_cs *engine;
......@@ -575,13 +578,16 @@ static void __fence_set_priority(struct dma_fence *fence, int prio)
rq = to_request(fence);
engine = rq->engine;
rcu_read_lock();
local_bh_disable();
rcu_read_lock(); /* RCU serialisation for set-wedged protection */
if (engine->schedule)
engine->schedule(rq, prio);
engine->schedule(rq, attr);
rcu_read_unlock();
local_bh_enable(); /* kick the tasklets if queues were reprioritised */
}
static void fence_set_priority(struct dma_fence *fence, int prio)
static void fence_set_priority(struct dma_fence *fence,
const struct i915_sched_attr *attr)
{
/* Recurse once into a fence-array */
if (dma_fence_is_array(fence)) {
......@@ -589,16 +595,16 @@ static void fence_set_priority(struct dma_fence *fence, int prio)
int i;
for (i = 0; i < array->num_fences; i++)
__fence_set_priority(array->fences[i], prio);
__fence_set_priority(array->fences[i], attr);
} else {
__fence_set_priority(fence, prio);
__fence_set_priority(fence, attr);
}
}
int
i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
unsigned int flags,
int prio)
const struct i915_sched_attr *attr)
{
struct dma_fence *excl;
......@@ -613,7 +619,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
return ret;
for (i = 0; i < count; i++) {
fence_set_priority(shared[i], prio);
fence_set_priority(shared[i], attr);
dma_fence_put(shared[i]);
}
......@@ -623,7 +629,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
}
if (excl) {
fence_set_priority(excl, prio);
fence_set_priority(excl, attr);
dma_fence_put(excl);
}
return 0;
......@@ -2974,8 +2980,8 @@ i915_gem_find_active_request(struct intel_engine_cs *engine)
* extra delay for a recent interrupt is pointless. Hence, we do
* not need an engine->irq_seqno_barrier() before the seqno reads.
*/
spin_lock_irqsave(&engine->timeline->lock, flags);
list_for_each_entry(request, &engine->timeline->requests, link) {
spin_lock_irqsave(&engine->timeline.lock, flags);
list_for_each_entry(request, &engine->timeline.requests, link) {
if (__i915_request_completed(request, request->global_seqno))
continue;
......@@ -2986,7 +2992,7 @@ i915_gem_find_active_request(struct intel_engine_cs *engine)
active = request;
break;
}
spin_unlock_irqrestore(&engine->timeline->lock, flags);
spin_unlock_irqrestore(&engine->timeline.lock, flags);
return active;
}
......@@ -3107,15 +3113,15 @@ static void engine_skip_context(struct i915_request *request)
{
struct intel_engine_cs *engine = request->engine;
struct i915_gem_context *hung_ctx = request->ctx;
struct intel_timeline *timeline;
struct i915_timeline *timeline = request->timeline;
unsigned long flags;
timeline = i915_gem_context_lookup_timeline(hung_ctx, engine);
GEM_BUG_ON(timeline == &engine->timeline);
spin_lock_irqsave(&engine->timeline->lock, flags);
spin_lock(&timeline->lock);
spin_lock_irqsave(&engine->timeline.lock, flags);
spin_lock_nested(&timeline->lock, SINGLE_DEPTH_NESTING);
list_for_each_entry_continue(request, &engine->timeline->requests, link)
list_for_each_entry_continue(request, &engine->timeline.requests, link)
if (request->ctx == hung_ctx)
skip_request(request);
......@@ -3123,7 +3129,7 @@ static void engine_skip_context(struct i915_request *request)
skip_request(request);
spin_unlock(&timeline->lock);
spin_unlock_irqrestore(&engine->timeline->lock, flags);
spin_unlock_irqrestore(&engine->timeline.lock, flags);
}
/* Returns the request if it was guilty of the hang */
......@@ -3180,11 +3186,11 @@ i915_gem_reset_request(struct intel_engine_cs *engine,
dma_fence_set_error(&request->fence, -EAGAIN);
/* Rewind the engine to replay the incomplete rq */
spin_lock_irq(&engine->timeline->lock);
spin_lock_irq(&engine->timeline.lock);
request = list_prev_entry(request, link);
if (&request->link == &engine->timeline->requests)
if (&request->link == &engine->timeline.requests)
request = NULL;
spin_unlock_irq(&engine->timeline->lock);
spin_unlock_irq(&engine->timeline.lock);
}
}
......@@ -3232,7 +3238,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv,
stalled_mask & ENGINE_MASK(id));
ctx = fetch_and_zero(&engine->last_retired_context);
if (ctx)
engine->context_unpin(engine, ctx);
intel_context_unpin(ctx, engine);
/*
* Ostensibily, we always want a context loaded for powersaving,
......@@ -3297,10 +3303,10 @@ static void nop_complete_submit_request(struct i915_request *request)
request->fence.context, request->fence.seqno);
dma_fence_set_error(&request->fence, -EIO);
spin_lock_irqsave(&request->engine->timeline->lock, flags);
spin_lock_irqsave(&request->engine->timeline.lock, flags);
__i915_request_submit(request);
intel_engine_init_global_seqno(request->engine, request->global_seqno);
spin_unlock_irqrestore(&request->engine->timeline->lock, flags);
spin_unlock_irqrestore(&request->engine->timeline.lock, flags);
}
void i915_gem_set_wedged(struct drm_i915_private *i915)
......@@ -3310,7 +3316,7 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
GEM_TRACE("start\n");
if (drm_debug & DRM_UT_DRIVER) {
if (GEM_SHOW_DEBUG()) {
struct drm_printer p = drm_debug_printer(__func__);
for_each_engine(engine, i915, id)
......@@ -3369,10 +3375,10 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
* (lockless) lookup doesn't try and wait upon the request as we
* reset it.
*/
spin_lock_irqsave(&engine->timeline->lock, flags);
spin_lock_irqsave(&engine->timeline.lock, flags);
intel_engine_init_global_seqno(engine,
intel_engine_last_submit(engine));
spin_unlock_irqrestore(&engine->timeline->lock, flags);
spin_unlock_irqrestore(&engine->timeline.lock, flags);
i915_gem_reset_finish_engine(engine);
}
......@@ -3384,8 +3390,7 @@ void i915_gem_set_wedged(struct drm_i915_private *i915)
bool i915_gem_unset_wedged(struct drm_i915_private *i915)
{
struct i915_gem_timeline *tl;
int i;
struct i915_timeline *tl;
lockdep_assert_held(&i915->drm.struct_mutex);
if (!test_bit(I915_WEDGED, &i915->gpu_error.flags))
......@@ -3404,29 +3409,27 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915)
* No more can be submitted until we reset the wedged bit.
*/
list_for_each_entry(tl, &i915->gt.timelines, link) {
for (i = 0; i < ARRAY_SIZE(tl->engine); i++) {
struct i915_request *rq;
struct i915_request *rq;
rq = i915_gem_active_peek(&tl->engine[i].last_request,
&i915->drm.struct_mutex);
if (!rq)
continue;
rq = i915_gem_active_peek(&tl->last_request,
&i915->drm.struct_mutex);
if (!rq)
continue;
/*
* We can't use our normal waiter as we want to
* avoid recursively trying to handle the current
* reset. The basic dma_fence_default_wait() installs
* a callback for dma_fence_signal(), which is
* triggered by our nop handler (indirectly, the
* callback enables the signaler thread which is
* woken by the nop_submit_request() advancing the seqno
* and when the seqno passes the fence, the signaler
* then signals the fence waking us up).
*/
if (dma_fence_default_wait(&rq->fence, true,
MAX_SCHEDULE_TIMEOUT) < 0)
return false;
}
/*
* We can't use our normal waiter as we want to
* avoid recursively trying to handle the current
* reset. The basic dma_fence_default_wait() installs
* a callback for dma_fence_signal(), which is
* triggered by our nop handler (indirectly, the
* callback enables the signaler thread which is
* woken by the nop_submit_request() advancing the seqno
* and when the seqno passes the fence, the signaler
* then signals the fence waking us up).
*/
if (dma_fence_default_wait(&rq->fence, true,
MAX_SCHEDULE_TIMEOUT) < 0)
return false;
}
i915_retire_requests(i915);
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)
return ret;
}
static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags)
static int wait_for_timeline(struct i915_timeline *tl, unsigned int flags)
{
int ret, i;
for (i = 0; i < ARRAY_SIZE(tl->engine); i++) {
ret = i915_gem_active_wait(&tl->engine[i].last_request, flags);
if (ret)
return ret;
}
return 0;
return i915_gem_active_wait(&tl->last_request, flags);
}
static int wait_for_engines(struct drm_i915_private *i915)
......@@ -3759,30 +3754,37 @@ static int wait_for_engines(struct drm_i915_private *i915)
int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
{
int ret;
/* If the device is asleep, we have no requests outstanding */
if (!READ_ONCE(i915->gt.awake))
return 0;
if (flags & I915_WAIT_LOCKED) {
struct i915_gem_timeline *tl;
struct i915_timeline *tl;
int err;
lockdep_assert_held(&i915->drm.struct_mutex);
list_for_each_entry(tl, &i915->gt.timelines, link) {
ret = wait_for_timeline(tl, flags);
if (ret)
return ret;
err = wait_for_timeline(tl, flags);
if (err)
return err;
}
i915_retire_requests(i915);
ret = wait_for_engines(i915);
return wait_for_engines(i915);
} else {
ret = wait_for_timeline(&i915->gt.global_timeline, flags);
}
struct intel_engine_cs *engine;
enum intel_engine_id id;
int err;
return ret;
for_each_engine(engine, i915, id) {
err = wait_for_timeline(&engine->timeline, flags);
if (err)
return err;
}
return 0;
}
}
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,
&obj->vma_list, obj_link) {
GEM_BUG_ON(i915_vma_is_active(vma));
vma->flags &= ~I915_VMA_PIN_MASK;
i915_vma_close(vma);
i915_vma_destroy(vma);
}
GEM_BUG_ON(!list_empty(&obj->vma_list));
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)
enum intel_engine_id id;
for_each_engine(engine, i915, id) {
GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline->last_request));
GEM_BUG_ON(__i915_gem_active_peek(&engine->timeline.last_request));
GEM_BUG_ON(engine->last_retired_context != kernel_context);
}
}
......@@ -5289,7 +5291,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915)
for_each_engine(engine, i915, id) {
struct i915_vma *state;
state = ctx->engine[id].state;
state = to_intel_context(ctx, engine)->state;
if (!state)
continue;
......@@ -5597,12 +5599,9 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv)
if (!dev_priv->priorities)
goto err_dependencies;
mutex_lock(&dev_priv->drm.struct_mutex);
INIT_LIST_HEAD(&dev_priv->gt.timelines);
err = i915_gem_timeline_init__global(dev_priv);
mutex_unlock(&dev_priv->drm.struct_mutex);
if (err)
goto err_priorities;
INIT_LIST_HEAD(&dev_priv->gt.active_rings);
INIT_LIST_HEAD(&dev_priv->gt.closed_vma);
i915_gem_init__mm(dev_priv);
......@@ -5623,8 +5622,6 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv)
return 0;
err_priorities:
kmem_cache_destroy(dev_priv->priorities);
err_dependencies:
kmem_cache_destroy(dev_priv->dependencies);
err_requests:
......@@ -5645,11 +5642,7 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list));
GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count));
WARN_ON(dev_priv->mm.object_count);
mutex_lock(&dev_priv->drm.struct_mutex);
i915_gem_timeline_fini(&dev_priv->gt.global_timeline);
WARN_ON(!list_empty(&dev_priv->gt.timelines));
mutex_unlock(&dev_priv->drm.struct_mutex);
kmem_cache_destroy(dev_priv->priorities);
kmem_cache_destroy(dev_priv->dependencies);
......
......@@ -30,6 +30,9 @@
struct drm_i915_private;
#ifdef CONFIG_DRM_I915_DEBUG_GEM
#define GEM_SHOW_DEBUG() (drm_debug & DRM_UT_DRIVER)
#define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \
pr_err("%s:%d GEM_BUG_ON(%s)\n", \
__func__, __LINE__, __stringify(condition)); \
......@@ -45,6 +48,9 @@ struct drm_i915_private;
#define GEM_DEBUG_BUG_ON(expr) GEM_BUG_ON(expr)
#else
#define GEM_SHOW_DEBUG() (0)
#define GEM_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
#define GEM_WARN_ON(expr) (BUILD_BUG_ON_INVALID(expr), 0)
......
......@@ -117,15 +117,15 @@ static void lut_close(struct i915_gem_context *ctx)
static void i915_gem_context_free(struct i915_gem_context *ctx)
{
int i;
unsigned int n;
lockdep_assert_held(&ctx->i915->drm.struct_mutex);
GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
i915_ppgtt_put(ctx->ppgtt);
for (i = 0; i < I915_NUM_ENGINES; i++) {
struct intel_context *ce = &ctx->engine[i];
for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) {
struct intel_context *ce = &ctx->__engine[n];
if (!ce->state)
continue;
......@@ -281,7 +281,7 @@ __create_hw_context(struct drm_i915_private *dev_priv,
kref_init(&ctx->ref);
list_add_tail(&ctx->link, &dev_priv->contexts.list);
ctx->i915 = dev_priv;
ctx->priority = I915_PRIORITY_NORMAL;
ctx->sched.priority = I915_PRIORITY_NORMAL;
INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
INIT_LIST_HEAD(&ctx->handles_list);
......@@ -431,7 +431,7 @@ i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio)
return ctx;
i915_gem_context_clear_bannable(ctx);
ctx->priority = prio;
ctx->sched.priority = prio;
ctx->ring_size = PAGE_SIZE;
GEM_BUG_ON(!i915_gem_context_is_kernel(ctx));
......@@ -521,7 +521,7 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv)
if (!engine->last_retired_context)
continue;
engine->context_unpin(engine, engine->last_retired_context);
intel_context_unpin(engine->last_retired_context, engine);
engine->last_retired_context = NULL;
}
}
......@@ -577,19 +577,29 @@ void i915_gem_context_close(struct drm_file *file)
idr_destroy(&file_priv->context_idr);
}
static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine)
static struct i915_request *
last_request_on_engine(struct i915_timeline *timeline,
struct intel_engine_cs *engine)
{
struct i915_gem_timeline *timeline;
struct i915_request *rq;
list_for_each_entry(timeline, &engine->i915->gt.timelines, link) {
struct intel_timeline *tl;
if (timeline == &engine->timeline)
return NULL;
if (timeline == &engine->i915->gt.global_timeline)
continue;
rq = i915_gem_active_raw(&timeline->last_request,
&engine->i915->drm.struct_mutex);
if (rq && rq->engine == engine)
return rq;
return NULL;
}
tl = &timeline->engine[engine->id];
if (i915_gem_active_peek(&tl->last_request,
&engine->i915->drm.struct_mutex))
static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine)
{
struct i915_timeline *timeline;
list_for_each_entry(timeline, &engine->i915->gt.timelines, link) {
if (last_request_on_engine(timeline, engine))
return false;
}
......@@ -599,7 +609,7 @@ static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine)
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
struct i915_gem_timeline *timeline;
struct i915_timeline *timeline;
enum intel_engine_id id;
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)
/* Queue this switch after all other activity */
list_for_each_entry(timeline, &dev_priv->gt.timelines, link) {
struct i915_request *prev;
struct intel_timeline *tl;
tl = &timeline->engine[engine->id];
prev = i915_gem_active_raw(&tl->last_request,
&dev_priv->drm.struct_mutex);
prev = last_request_on_engine(timeline, engine);
if (prev)
i915_sw_fence_await_sw_fence_gfp(&rq->submit,
&prev->submit,
......@@ -753,7 +760,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
args->value = i915_gem_context_is_bannable(ctx);
break;
case I915_CONTEXT_PARAM_PRIORITY:
args->value = ctx->priority;
args->value = ctx->sched.priority;
break;
default:
ret = -EINVAL;
......@@ -826,7 +833,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
!capable(CAP_SYS_NICE))
ret = -EPERM;
else
ctx->priority = priority;
ctx->sched.priority = priority;
}
break;
......
......@@ -137,18 +137,7 @@ struct i915_gem_context {
*/
u32 user_handle;
/**
* @priority: execution and service priority
*
* All clients are equal, but some are more equal than others!
*
* Requests from a context with a greater (more positive) value of
* @priority will be executed before those with a lower @priority
* value, forming a simple QoS.
*
* The &drm_i915_private.kernel_context is assigned the lowest priority.
*/
int priority;
struct i915_sched_attr sched;
/** ggtt_offset_bias: placement restriction for context objects */
u32 ggtt_offset_bias;
......@@ -160,7 +149,7 @@ struct i915_gem_context {
u32 *lrc_reg_state;
u64 lrc_desc;
int pin_count;
} engine[I915_NUM_ENGINES];
} __engine[I915_NUM_ENGINES];
/** ring_size: size for allocating the per-engine ring buffer */
u32 ring_size;
......@@ -267,6 +256,34 @@ static inline bool i915_gem_context_is_kernel(struct i915_gem_context *ctx)
return !ctx->file_priv;
}
static inline struct intel_context *
to_intel_context(struct i915_gem_context *ctx,
const struct intel_engine_cs *engine)
{
return &ctx->__engine[engine->id];
}
static inline struct intel_ring *
intel_context_pin(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
{
return engine->context_pin(engine, ctx);
}
static inline void __intel_context_pin(struct i915_gem_context *ctx,
const struct intel_engine_cs *engine)
{
struct intel_context *ce = to_intel_context(ctx, engine);
GEM_BUG_ON(!ce->pin_count);
ce->pin_count++;
}
static inline void intel_context_unpin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
engine->context_unpin(engine, ctx);
}
/* i915_gem_context.c */
int __must_check i915_gem_contexts_init(struct drm_i915_private *dev_priv);
void i915_gem_contexts_lost(struct drm_i915_private *dev_priv);
......
......@@ -762,7 +762,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
}
/* transfer ref to ctx */
vma->open_count++;
if (!vma->open_count++)
i915_vma_reopen(vma);
list_add(&lut->obj_link, &obj->lut_list);
list_add(&lut->ctx_link, &eb->ctx->handles_list);
lut->ctx = eb->ctx;
......
......@@ -110,7 +110,8 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma);
static void gen6_ggtt_invalidate(struct drm_i915_private *dev_priv)
{
/* Note that as an uncached mmio write, this should flush the
/*
* Note that as an uncached mmio write, this will flush the
* WCB of the writes into the GGTT before it triggers the invalidate.
*/
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,
vaddr[idx.pde] |= GEN8_PDE_IPS_64K;
kunmap_atomic(vaddr);
page_size = I915_GTT_PAGE_SIZE_64K;
/*
* We write all 4K page entries, even when using 64K
* pages. In order to verify that the HW isn't cheating
* by using the 4K PTE instead of the 64K PTE, we want
* to remove all the surplus entries. If the HW skipped
* the 64K PTE, it will read/write into the scratch page
* instead - which we detect as missing results during
* selftests.
*/
if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) {
u16 i;
encode = pte_encode | vma->vm->scratch_page.daddr;
vaddr = kmap_atomic_px(pd->page_table[idx.pde]);
for (i = 1; i < index; i += 16)
memset64(vaddr + i, encode, 15);
kunmap_atomic(vaddr);
}
}
vma->page_sizes.gtt |= page_size;
......@@ -2111,8 +2133,6 @@ static void i915_address_space_init(struct i915_address_space *vm,
struct drm_i915_private *dev_priv,
const char *name)
{
i915_gem_timeline_init(dev_priv, &vm->timeline, name);
drm_mm_init(&vm->mm, 0, vm->total);
vm->mm.head_node.color = I915_COLOR_UNEVICTABLE;
......@@ -2129,7 +2149,6 @@ static void i915_address_space_fini(struct i915_address_space *vm)
if (pagevec_count(&vm->free_pages))
vm_free_pages_release(vm, true);
i915_gem_timeline_fini(&vm->timeline);
drm_mm_takedown(&vm->mm);
list_del(&vm->global_link);
}
......@@ -2140,15 +2159,15 @@ static void gtt_write_workarounds(struct drm_i915_private *dev_priv)
* called on driver load and after a GPU reset, so you can place
* workarounds here even if they get overwritten by GPU reset.
*/
/* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl,cnl */
/* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl,cnl,icl */
if (IS_BROADWELL(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW);
else if (IS_CHERRYVIEW(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV);
else if (IS_GEN9_BC(dev_priv) || IS_GEN10(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
else if (IS_GEN9_LP(dev_priv))
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
else if (INTEL_GEN(dev_priv) >= 9)
I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
/*
* To support 64K PTEs we need to first enable the use of the
......@@ -2221,6 +2240,12 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv,
}
void i915_ppgtt_close(struct i915_address_space *vm)
{
GEM_BUG_ON(vm->closed);
vm->closed = true;
}
static void ppgtt_destroy_vma(struct i915_address_space *vm)
{
struct list_head *phases[] = {
&vm->active_list,
......@@ -2229,15 +2254,12 @@ void i915_ppgtt_close(struct i915_address_space *vm)
NULL,
}, **phase;
GEM_BUG_ON(vm->closed);
vm->closed = true;
for (phase = phases; *phase; phase++) {
struct i915_vma *vma, *vn;
list_for_each_entry_safe(vma, vn, *phase, vm_link)
if (!i915_vma_is_closed(vma))
i915_vma_close(vma);
i915_vma_destroy(vma);
}
}
......@@ -2248,7 +2270,8 @@ void i915_ppgtt_release(struct kref *kref)
trace_i915_ppgtt_release(&ppgtt->base);
/* vmas should already be unbound and destroyed */
ppgtt_destroy_vma(&ppgtt->base);
GEM_BUG_ON(!list_empty(&ppgtt->base.active_list));
GEM_BUG_ON(!list_empty(&ppgtt->base.inactive_list));
GEM_BUG_ON(!list_empty(&ppgtt->base.unbound_list));
......@@ -2417,11 +2440,9 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
for_each_sgt_dma(addr, sgt_iter, vma->pages)
gen8_set_pte(gtt_entries++, pte_encode | addr);
wmb();
/* This next bit makes the above posting read even more important. We
* want to flush the TLBs only after we're certain all the PTE updates
* have finished.
/*
* We want to flush the TLBs only after we're certain all the PTE
* updates have finished.
*/
ggtt->invalidate(vm->i915);
}
......@@ -2459,11 +2480,10 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
dma_addr_t addr;
for_each_sgt_dma(addr, iter, vma->pages)
iowrite32(vm->pte_encode(addr, level, flags), &entries[i++]);
wmb();
/* This next bit makes the above posting read even more important. We
* want to flush the TLBs only after we're certain all the PTE updates
* have finished.
/*
* We want to flush the TLBs only after we're certain all the PTE
* updates have finished.
*/
ggtt->invalidate(vm->i915);
}
......@@ -3325,14 +3345,10 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
DRM_ERROR("Can't set DMA mask/consistent mask (%d)\n", err);
pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
if (INTEL_GEN(dev_priv) >= 9) {
size = gen8_get_total_gtt_size(snb_gmch_ctl);
} else if (IS_CHERRYVIEW(dev_priv)) {
if (IS_CHERRYVIEW(dev_priv))
size = chv_get_total_gtt_size(snb_gmch_ctl);
} else {
else
size = gen8_get_total_gtt_size(snb_gmch_ctl);
}
ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
ggtt->base.cleanup = gen6_gmch_remove;
......
......@@ -38,10 +38,9 @@
#include <linux/mm.h>
#include <linux/pagevec.h>
#include "i915_gem_timeline.h"
#include "i915_request.h"
#include "i915_selftest.h"
#include "i915_timeline.h"
#define I915_GTT_PAGE_SIZE_4K BIT(12)
#define I915_GTT_PAGE_SIZE_64K BIT(16)
......@@ -257,7 +256,6 @@ struct i915_pml4 {
struct i915_address_space {
struct drm_mm mm;
struct i915_gem_timeline timeline;
struct drm_i915_private *i915;
struct device *dma;
/* Every address space belongs to a struct file - except for the global
......@@ -344,6 +342,7 @@ struct i915_address_space {
void (*clear_pages)(struct i915_vma *vma);
I915_SELFTEST_DECLARE(struct fault_attr fault_attr);
I915_SELFTEST_DECLARE(bool scrub_64K);
};
#define i915_is_ggtt(V) (!(V)->file)
......
......@@ -51,6 +51,10 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return -ENODEV;
/* WaSkipStolenMemoryFirstPage:bdw+ */
if (INTEL_GEN(dev_priv) >= 8 && start < 4096)
start = 4096;
mutex_lock(&dev_priv->mm.stolen_lock);
ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node,
size, alignment, 0,
......@@ -343,7 +347,6 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
{
resource_size_t reserved_base, stolen_top;
resource_size_t reserved_total, reserved_size;
resource_size_t stolen_usable_start;
mutex_init(&dev_priv->mm.stolen_lock);
......@@ -435,17 +438,11 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
(u64)resource_size(&dev_priv->dsm) >> 10,
((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10);
stolen_usable_start = 0;
/* WaSkipStolenMemoryFirstPage:bdw+ */
if (INTEL_GEN(dev_priv) >= 8)
stolen_usable_start = 4096;
dev_priv->stolen_usable_size =
resource_size(&dev_priv->dsm) - reserved_total - stolen_usable_start;
resource_size(&dev_priv->dsm) - reserved_total;
/* Basic memrange allocator for stolen space. */
drm_mm_init(&dev_priv->mm.stolen, stolen_usable_start,
dev_priv->stolen_usable_size);
drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->stolen_usable_size);
return 0;
}
......
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
*/
#include "i915_drv.h"
#include "i915_syncmap.h"
static void __intel_timeline_init(struct intel_timeline *tl,
struct i915_gem_timeline *parent,
u64 context,
struct lock_class_key *lockclass,
const char *lockname)
{
tl->fence_context = context;
tl->common = parent;
spin_lock_init(&tl->lock);
lockdep_set_class_and_name(&tl->lock, lockclass, lockname);
init_request_active(&tl->last_request, NULL);
INIT_LIST_HEAD(&tl->requests);
i915_syncmap_init(&tl->sync);
}
static void __intel_timeline_fini(struct intel_timeline *tl)
{
GEM_BUG_ON(!list_empty(&tl->requests));
i915_syncmap_free(&tl->sync);
}
static int __i915_gem_timeline_init(struct drm_i915_private *i915,
struct i915_gem_timeline *timeline,
const char *name,
struct lock_class_key *lockclass,
const char *lockname)
{
unsigned int i;
u64 fences;
lockdep_assert_held(&i915->drm.struct_mutex);
/*
* Ideally we want a set of engines on a single leaf as we expect
* to mostly be tracking synchronisation between engines. It is not
* a huge issue if this is not the case, but we may want to mitigate
* any page crossing penalties if they become an issue.
*/
BUILD_BUG_ON(KSYNCMAP < I915_NUM_ENGINES);
timeline->i915 = i915;
timeline->name = kstrdup(name ?: "[kernel]", GFP_KERNEL);
if (!timeline->name)
return -ENOMEM;
list_add(&timeline->link, &i915->gt.timelines);
/* Called during early_init before we know how many engines there are */
fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine));
for (i = 0; i < ARRAY_SIZE(timeline->engine); i++)
__intel_timeline_init(&timeline->engine[i],
timeline, fences++,
lockclass, lockname);
return 0;
}
int i915_gem_timeline_init(struct drm_i915_private *i915,
struct i915_gem_timeline *timeline,
const char *name)
{
static struct lock_class_key class;
return __i915_gem_timeline_init(i915, timeline, name,
&class, "&timeline->lock");
}
int i915_gem_timeline_init__global(struct drm_i915_private *i915)
{
static struct lock_class_key class;
return __i915_gem_timeline_init(i915,
&i915->gt.global_timeline,
"[execution]",
&class, "&global_timeline->lock");
}
/**
* i915_gem_timelines_park - called when the driver idles
* @i915: the drm_i915_private device
*
* When the driver is completely idle, we know that all of our sync points
* have been signaled and our tracking is then entirely redundant. Any request
* to wait upon an older sync point will be completed instantly as we know
* the fence is signaled and therefore we will not even look them up in the
* sync point map.
*/
void i915_gem_timelines_park(struct drm_i915_private *i915)
{
struct i915_gem_timeline *timeline;
int i;
lockdep_assert_held(&i915->drm.struct_mutex);
list_for_each_entry(timeline, &i915->gt.timelines, link) {
for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) {
struct intel_timeline *tl = &timeline->engine[i];
/*
* All known fences are completed so we can scrap
* the current sync point tracking and start afresh,
* any attempt to wait upon a previous sync point
* will be skipped as the fence was signaled.
*/
i915_syncmap_free(&tl->sync);
}
}
}
void i915_gem_timeline_fini(struct i915_gem_timeline *timeline)
{
int i;
lockdep_assert_held(&timeline->i915->drm.struct_mutex);
for (i = 0; i < ARRAY_SIZE(timeline->engine); i++)
__intel_timeline_fini(&timeline->engine[i]);
list_del(&timeline->link);
kfree(timeline->name);
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_timeline.c"
#include "selftests/i915_gem_timeline.c"
#endif
......@@ -778,6 +778,9 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
I915_USERPTR_UNSYNCHRONIZED))
return -EINVAL;
if (!args->user_size)
return -EINVAL;
if (offset_in_page(args->user_ptr | args->user_size))
return -EINVAL;
......
......@@ -404,16 +404,17 @@ static const char *bannable(const struct drm_i915_error_context *ctx)
static void error_print_request(struct drm_i915_error_state_buf *m,
const char *prefix,
const struct drm_i915_error_request *erq)
const struct drm_i915_error_request *erq,
const unsigned long epoch)
{
if (!erq->seqno)
return;
err_printf(m, "%s pid %d, ban score %d, seqno %8x:%08x, prio %d, emitted %dms ago, head %08x, tail %08x\n",
err_printf(m, "%s pid %d, ban score %d, seqno %8x:%08x, prio %d, emitted %dms, start %08x, head %08x, tail %08x\n",
prefix, erq->pid, erq->ban_score,
erq->context, erq->seqno, erq->priority,
jiffies_to_msecs(jiffies - erq->jiffies),
erq->head, erq->tail);
erq->context, erq->seqno, erq->sched_attr.priority,
jiffies_to_msecs(erq->jiffies - epoch),
erq->start, erq->head, erq->tail);
}
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,
{
err_printf(m, "%s%s[%d] user_handle %d hw_id %d, prio %d, ban score %d%s guilty %d active %d\n",
header, ctx->comm, ctx->pid, ctx->handle, ctx->hw_id,
ctx->priority, ctx->ban_score, bannable(ctx),
ctx->sched_attr.priority, ctx->ban_score, bannable(ctx),
ctx->guilty, ctx->active);
}
static void error_print_engine(struct drm_i915_error_state_buf *m,
const struct drm_i915_error_engine *ee)
const struct drm_i915_error_engine *ee,
const unsigned long epoch)
{
int n;
......@@ -497,14 +499,15 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
err_printf(m, " hangcheck stall: %s\n", yesno(ee->hangcheck_stalled));
err_printf(m, " hangcheck action: %s\n",
hangcheck_action_to_str(ee->hangcheck_action));
err_printf(m, " hangcheck action timestamp: %lu, %u ms ago\n",
err_printf(m, " hangcheck action timestamp: %dms (%lu%s)\n",
jiffies_to_msecs(ee->hangcheck_timestamp - epoch),
ee->hangcheck_timestamp,
jiffies_to_msecs(jiffies - ee->hangcheck_timestamp));
ee->hangcheck_timestamp == epoch ? "; epoch" : "");
err_printf(m, " engine reset count: %u\n", ee->reset_count);
for (n = 0; n < ee->num_ports; n++) {
err_printf(m, " ELSP[%d]:", n);
error_print_request(m, " ", &ee->execlist[n]);
error_print_request(m, " ", &ee->execlist[n], epoch);
}
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,
ts = ktime_to_timespec64(error->uptime);
err_printf(m, "Uptime: %lld s %ld us\n",
(s64)ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC);
err_printf(m, "Epoch: %lu jiffies (%u HZ)\n", error->epoch, HZ);
err_printf(m, "Capture: %lu jiffies; %d ms ago, %d ms after epoch\n",
error->capture,
jiffies_to_msecs(jiffies - error->capture),
jiffies_to_msecs(error->capture - error->epoch));
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled &&
......@@ -710,7 +718,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].engine_id != -1)
error_print_engine(m, &error->engine[i]);
error_print_engine(m, &error->engine[i], error->epoch);
}
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,
dev_priv->engine[i]->name,
ee->num_requests);
for (j = 0; j < ee->num_requests; j++)
error_print_request(m, " ", &ee->requests[j]);
error_print_request(m, " ",
&ee->requests[j],
error->epoch);
}
if (IS_ERR(ee->waiters)) {
......@@ -1278,10 +1288,11 @@ static void record_request(struct i915_request *request,
struct drm_i915_error_request *erq)
{
erq->context = request->ctx->hw_id;
erq->priority = request->priotree.priority;
erq->sched_attr = request->sched.attr;
erq->ban_score = atomic_read(&request->ctx->ban_score);
erq->seqno = request->global_seqno;
erq->jiffies = request->emitted_jiffies;
erq->start = i915_ggtt_offset(request->ring->vma);
erq->head = request->head;
erq->tail = request->tail;
......@@ -1299,7 +1310,7 @@ static void engine_record_requests(struct intel_engine_cs *engine,
count = 0;
request = first;
list_for_each_entry_from(request, &engine->timeline->requests, link)
list_for_each_entry_from(request, &engine->timeline.requests, link)
count++;
if (!count)
return;
......@@ -1312,7 +1323,7 @@ static void engine_record_requests(struct intel_engine_cs *engine,
count = 0;
request = first;
list_for_each_entry_from(request, &engine->timeline->requests, link) {
list_for_each_entry_from(request, &engine->timeline.requests, link) {
if (count >= ee->num_requests) {
/*
* If the ring request list was changed in
......@@ -1372,7 +1383,7 @@ static void record_context(struct drm_i915_error_context *e,
e->handle = ctx->user_handle;
e->hw_id = ctx->hw_id;
e->priority = ctx->priority;
e->sched_attr = ctx->sched;
e->ban_score = atomic_read(&ctx->ban_score);
e->bannable = i915_gem_context_is_bannable(ctx);
e->guilty = atomic_read(&ctx->guilty_count);
......@@ -1472,7 +1483,8 @@ static void gem_record_rings(struct i915_gpu_state *error)
ee->ctx =
i915_error_object_create(i915,
request->ctx->engine[i].state);
to_intel_context(request->ctx,
engine)->state);
error->simulated |=
i915_gem_context_no_error_capture(request->ctx);
......@@ -1735,6 +1747,22 @@ static void capture_params(struct i915_gpu_state *error)
#undef DUP
}
static unsigned long capture_find_epoch(const struct i915_gpu_state *error)
{
unsigned long epoch = error->capture;
int i;
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
const struct drm_i915_error_engine *ee = &error->engine[i];
if (ee->hangcheck_stalled &&
time_before(ee->hangcheck_timestamp, epoch))
epoch = ee->hangcheck_timestamp;
}
return epoch;
}
static int capture(void *data)
{
struct i915_gpu_state *error = data;
......@@ -1743,6 +1771,7 @@ static int capture(void *data)
error->boottime = ktime_get_boottime();
error->uptime = ktime_sub(ktime_get(),
error->i915->gt.last_init_time);
error->capture = jiffies;
capture_params(error);
capture_gen_state(error);
......@@ -1756,6 +1785,8 @@ static int capture(void *data)
error->overlay = intel_overlay_capture_error_state(error->i915);
error->display = intel_display_capture_error_state(error->i915);
error->epoch = capture_find_epoch(error);
return 0;
}
......
......@@ -20,6 +20,7 @@
#include "i915_gem.h"
#include "i915_gem_gtt.h"
#include "i915_params.h"
#include "i915_scheduler.h"
struct drm_i915_private;
struct intel_overlay_error_state;
......@@ -30,6 +31,8 @@ struct i915_gpu_state {
ktime_t time;
ktime_t boottime;
ktime_t uptime;
unsigned long capture;
unsigned long epoch;
struct drm_i915_private *i915;
......@@ -122,11 +125,11 @@ struct i915_gpu_state {
pid_t pid;
u32 handle;
u32 hw_id;
int priority;
int ban_score;
int active;
int guilty;
bool bannable;
struct i915_sched_attr sched_attr;
} context;
struct drm_i915_error_object {
......@@ -147,11 +150,12 @@ struct i915_gpu_state {
long jiffies;
pid_t pid;
u32 context;
int priority;
int ban_score;
u32 seqno;
u32 start;
u32 head;
u32 tail;
struct i915_sched_attr sched_attr;
} *requests, execlist[EXECLIST_MAX_PORTS];
unsigned int num_ports;
......
......@@ -247,9 +247,9 @@ static u32
gen11_gt_engine_identity(struct drm_i915_private * const i915,
const unsigned int bank, const unsigned int bit);
static bool gen11_reset_one_iir(struct drm_i915_private * const i915,
const unsigned int bank,
const unsigned int bit)
bool gen11_reset_one_iir(struct drm_i915_private * const i915,
const unsigned int bank,
const unsigned int bit)
{
void __iomem * const regs = i915->regs;
u32 dw;
......@@ -2464,6 +2464,13 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
if (de_iir & DE_ERR_INT_IVB)
ivb_err_int_handler(dev_priv);
if (de_iir & DE_EDP_PSR_INT_HSW) {
u32 psr_iir = I915_READ(EDP_PSR_IIR);
intel_psr_irq_handler(dev_priv, psr_iir);
I915_WRITE(EDP_PSR_IIR, psr_iir);
}
if (de_iir & DE_AUX_CHANNEL_A_IVB)
dp_aux_irq_handler(dev_priv);
......@@ -2593,11 +2600,25 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
if (master_ctl & GEN8_DE_MISC_IRQ) {
iir = I915_READ(GEN8_DE_MISC_IIR);
if (iir) {
bool found = false;
I915_WRITE(GEN8_DE_MISC_IIR, iir);
ret = IRQ_HANDLED;
if (iir & GEN8_DE_MISC_GSE)
if (iir & GEN8_DE_MISC_GSE) {
intel_opregion_asle_intr(dev_priv);
else
found = true;
}
if (iir & GEN8_DE_EDP_PSR) {
u32 psr_iir = I915_READ(EDP_PSR_IIR);
intel_psr_irq_handler(dev_priv, psr_iir);
I915_WRITE(EDP_PSR_IIR, psr_iir);
found = true;
}
if (!found)
DRM_ERROR("Unexpected DE Misc interrupt\n");
}
else
......@@ -3348,6 +3369,11 @@ static void ironlake_irq_reset(struct drm_device *dev)
if (IS_GEN7(dev_priv))
I915_WRITE(GEN7_ERR_INT, 0xffffffff);
if (IS_HASWELL(dev_priv)) {
I915_WRITE(EDP_PSR_IMR, 0xffffffff);
I915_WRITE(EDP_PSR_IIR, 0xffffffff);
}
gen5_gt_irq_reset(dev_priv);
ibx_irq_reset(dev_priv);
......@@ -3386,6 +3412,9 @@ static void gen8_irq_reset(struct drm_device *dev)
gen8_gt_irq_reset(dev_priv);
I915_WRITE(EDP_PSR_IMR, 0xffffffff);
I915_WRITE(EDP_PSR_IIR, 0xffffffff);
for_each_pipe(dev_priv, pipe)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
......@@ -3762,6 +3791,12 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
DE_DP_A_HOTPLUG);
}
if (IS_HASWELL(dev_priv)) {
gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR);
intel_psr_irq_control(dev_priv, dev_priv->psr.debug);
display_mask |= DE_EDP_PSR_INT_HSW;
}
dev_priv->irq_mask = ~display_mask;
ibx_irq_pre_postinstall(dev);
......@@ -3872,7 +3907,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
uint32_t de_pipe_enables;
u32 de_port_masked = GEN8_AUX_CHANNEL_A;
u32 de_port_enables;
u32 de_misc_masked = GEN8_DE_MISC_GSE;
u32 de_misc_masked = GEN8_DE_MISC_GSE | GEN8_DE_EDP_PSR;
enum pipe pipe;
if (INTEL_GEN(dev_priv) >= 9) {
......@@ -3897,6 +3932,9 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
else if (IS_BROADWELL(dev_priv))
de_port_enables |= GEN8_PORT_DP_A_HOTPLUG;
gen3_assert_iir_is_zero(dev_priv, EDP_PSR_IIR);
intel_psr_irq_control(dev_priv, dev_priv->psr.debug);
for_each_pipe(dev_priv, pipe) {
dev_priv->de_irq_mask[pipe] = ~de_pipe_masked;
......
......@@ -164,6 +164,9 @@ i915_param_named_unsafe(guc_firmware_path, charp, 0400,
i915_param_named_unsafe(huc_firmware_path, charp, 0400,
"HuC firmware path to use instead of the default one");
i915_param_named_unsafe(dmc_firmware_path, charp, 0400,
"DMC firmware path to use instead of the default one");
i915_param_named_unsafe(enable_dp_mst, bool, 0600,
"Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)");
......
......@@ -51,6 +51,7 @@ struct drm_printer;
param(int, guc_log_level, -1) \
param(char *, guc_firmware_path, NULL) \
param(char *, huc_firmware_path, NULL) \
param(char *, dmc_firmware_path, NULL) \
param(int, mmio_debug, 0) \
param(int, edp_vswing, 0) \
param(int, reset, 2) \
......
......@@ -1234,7 +1234,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
*
* NB: implied RCS engine...
*/
ring = engine->context_pin(engine, stream->ctx);
ring = intel_context_pin(stream->ctx, engine);
mutex_unlock(&dev_priv->drm.struct_mutex);
if (IS_ERR(ring))
return PTR_ERR(ring);
......@@ -1246,7 +1246,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
* with gen8+ and execlists
*/
dev_priv->perf.oa.specific_ctx_id =
i915_ggtt_offset(stream->ctx->engine[engine->id].state);
i915_ggtt_offset(to_intel_context(stream->ctx, engine)->state);
}
return 0;
......@@ -1271,7 +1271,7 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream)
mutex_lock(&dev_priv->drm.struct_mutex);
dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID;
engine->context_unpin(engine, stream->ctx);
intel_context_unpin(stream->ctx, engine);
mutex_unlock(&dev_priv->drm.struct_mutex);
}
......@@ -1695,7 +1695,7 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr
const struct i915_oa_config *oa_config)
{
struct intel_engine_cs *engine = dev_priv->engine[RCS];
struct i915_gem_timeline *timeline;
struct i915_timeline *timeline;
struct i915_request *rq;
int ret;
......@@ -1716,15 +1716,11 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr
/* Queue this switch after all other activity */
list_for_each_entry(timeline, &dev_priv->gt.timelines, link) {
struct i915_request *prev;
struct intel_timeline *tl;
tl = &timeline->engine[engine->id];
prev = i915_gem_active_raw(&tl->last_request,
prev = i915_gem_active_raw(&timeline->last_request,
&dev_priv->drm.struct_mutex);
if (prev)
i915_sw_fence_await_sw_fence_gfp(&rq->submit,
&prev->submit,
GFP_KERNEL);
i915_request_await_dma_fence(rq, &prev->fence);
}
i915_request_add(rq);
......@@ -1759,6 +1755,7 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr
static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
const struct i915_oa_config *oa_config)
{
struct intel_engine_cs *engine = dev_priv->engine[RCS];
struct i915_gem_context *ctx;
int ret;
unsigned int wait_flags = I915_WAIT_LOCKED;
......@@ -1789,7 +1786,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv,
/* Update all contexts now that we've stalled the submission. */
list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
struct intel_context *ce = &ctx->engine[RCS];
struct intel_context *ce = to_intel_context(ctx, engine);
u32 *regs;
/* OA settings will be set upon first use */
......@@ -1963,11 +1960,19 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream)
static void gen7_oa_disable(struct drm_i915_private *dev_priv)
{
I915_WRITE(GEN7_OACONTROL, 0);
if (intel_wait_for_register(dev_priv,
GEN7_OACONTROL, GEN7_OACONTROL_ENABLE, 0,
50))
DRM_ERROR("wait for OA to be disabled timed out\n");
}
static void gen8_oa_disable(struct drm_i915_private *dev_priv)
{
I915_WRITE(GEN8_OACONTROL, 0);
if (intel_wait_for_register(dev_priv,
GEN8_OACONTROL, GEN8_OA_COUNTER_ENABLE, 0,
50))
DRM_ERROR("wait for OA to be disabled timed out\n");
}
/**
......
......@@ -3840,6 +3840,7 @@ enum {
#define SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4)
#define SARBUNIT_CLKGATE_DIS (1 << 5)
#define RCCUNIT_CLKGATE_DIS (1 << 7)
#define MSCUNIT_CLKGATE_DIS (1 << 10)
#define SUBSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9524)
#define GWUNIT_CLKGATE_DIS (1 << 16)
......@@ -3847,6 +3848,9 @@ enum {
#define UNSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9434)
#define VFUNIT_CLKGATE_DIS (1 << 20)
#define INF_UNIT_LEVEL_CLKGATE _MMIO(0x9560)
#define CGPSF_CLKGATE_DIS (1 << 3)
/*
* Display engine regs
*/
......@@ -4026,6 +4030,13 @@ enum {
#define EDP_PSR_TP1_TIME_0us (3<<4)
#define EDP_PSR_IDLE_FRAME_SHIFT 0
/* Bspec claims those aren't shifted but stay at 0x64800 */
#define EDP_PSR_IMR _MMIO(0x64834)
#define EDP_PSR_IIR _MMIO(0x64838)
#define EDP_PSR_ERROR(trans) (1 << (((trans) * 8 + 10) & 31))
#define EDP_PSR_POST_EXIT(trans) (1 << (((trans) * 8 + 9) & 31))
#define EDP_PSR_PRE_ENTRY(trans) (1 << (((trans) * 8 + 8) & 31))
#define EDP_PSR_AUX_CTL _MMIO(dev_priv->psr_mmio_base + 0x10)
#define EDP_PSR_AUX_CTL_TIME_OUT_MASK (3 << 26)
#define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK (0x1f << 20)
......@@ -4088,6 +4099,29 @@ enum {
#define EDP_PSR2_IDLE_FRAME_MASK 0xf
#define EDP_PSR2_IDLE_FRAME_SHIFT 0
#define _PSR_EVENT_TRANS_A 0x60848
#define _PSR_EVENT_TRANS_B 0x61848
#define _PSR_EVENT_TRANS_C 0x62848
#define _PSR_EVENT_TRANS_D 0x63848
#define _PSR_EVENT_TRANS_EDP 0x6F848
#define PSR_EVENT(trans) _MMIO_TRANS2(trans, _PSR_EVENT_TRANS_A)
#define PSR_EVENT_PSR2_WD_TIMER_EXPIRE (1 << 17)
#define PSR_EVENT_PSR2_DISABLED (1 << 16)
#define PSR_EVENT_SU_DIRTY_FIFO_UNDERRUN (1 << 15)
#define PSR_EVENT_SU_CRC_FIFO_UNDERRUN (1 << 14)
#define PSR_EVENT_GRAPHICS_RESET (1 << 12)
#define PSR_EVENT_PCH_INTERRUPT (1 << 11)
#define PSR_EVENT_MEMORY_UP (1 << 10)
#define PSR_EVENT_FRONT_BUFFER_MODIFY (1 << 9)
#define PSR_EVENT_WD_TIMER_EXPIRE (1 << 8)
#define PSR_EVENT_PIPE_REGISTERS_UPDATE (1 << 6)
#define PSR_EVENT_REGISTER_UPDATE (1 << 5)
#define PSR_EVENT_HDCP_ENABLE (1 << 4)
#define PSR_EVENT_KVMR_SESSION_ENABLE (1 << 3)
#define PSR_EVENT_VBI_ENABLE (1 << 2)
#define PSR_EVENT_LPSP_MODE_EXIT (1 << 1)
#define PSR_EVENT_PSR_DISABLE (1 << 0)
#define EDP_PSR2_STATUS _MMIO(0x6f940)
#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28)
#define EDP_PSR2_STATUS_STATE_SHIFT 28
......@@ -6377,9 +6411,9 @@ enum {
#define _PLANE_COLOR_CTL_1_A 0x701CC /* GLK+ */
#define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */
#define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */
#define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30)
#define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-ICL */
#define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28)
#define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23)
#define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23) /* Pre-ICL */
#define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17)
#define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709 (1 << 17)
#define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17)
......@@ -6474,6 +6508,9 @@ enum {
#define _PLANE_BUF_CFG_1_B 0x7127c
#define _PLANE_BUF_CFG_2_B 0x7137c
#define SKL_DDB_ENTRY_MASK 0x3FF
#define ICL_DDB_ENTRY_MASK 0x7FF
#define DDB_ENTRY_END_SHIFT 16
#define _PLANE_BUF_CFG_1(pipe) \
_PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B)
#define _PLANE_BUF_CFG_2(pipe) \
......@@ -6837,6 +6874,7 @@ enum {
#define DE_PCH_EVENT_IVB (1<<28)
#define DE_DP_A_HOTPLUG_IVB (1<<27)
#define DE_AUX_CHANNEL_A_IVB (1<<26)
#define DE_EDP_PSR_INT_HSW (1<<19)
#define DE_SPRITEC_FLIP_DONE_IVB (1<<14)
#define DE_PLANEC_FLIP_DONE_IVB (1<<13)
#define DE_PIPEC_VBLANK_IVB (1<<10)
......@@ -6961,6 +6999,7 @@ enum {
#define GEN8_DE_MISC_IIR _MMIO(0x44468)
#define GEN8_DE_MISC_IER _MMIO(0x4446c)
#define GEN8_DE_MISC_GSE (1 << 27)
#define GEN8_DE_EDP_PSR (1 << 19)
#define GEN8_PCU_ISR _MMIO(0x444e0)
#define GEN8_PCU_IMR _MMIO(0x444e4)
......@@ -7191,18 +7230,22 @@ enum {
#define GEN7_L3CNTLREG3 _MMIO(0xB024)
#define GEN7_L3_CHICKEN_MODE_REGISTER _MMIO(0xB030)
#define GEN7_WA_L3_CHICKEN_MODE 0x20000000
#define GEN7_WA_L3_CHICKEN_MODE 0x20000000
#define GEN10_L3_CHICKEN_MODE_REGISTER _MMIO(0xB114)
#define GEN11_I2M_WRITE_DISABLE (1 << 28)
#define GEN7_L3SQCREG4 _MMIO(0xb034)
#define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27)
#define GEN8_L3SQCREG4 _MMIO(0xb118)
#define GEN8_LQSC_RO_PERF_DIS (1<<27)
#define GEN8_LQSC_FLUSH_COHERENT_LINES (1<<21)
#define GEN11_LQSC_CLEAN_EVICT_DISABLE (1 << 6)
#define GEN8_LQSC_RO_PERF_DIS (1 << 27)
#define GEN8_LQSC_FLUSH_COHERENT_LINES (1 << 21)
/* GEN8 chicken */
#define HDC_CHICKEN0 _MMIO(0x7300)
#define CNL_HDC_CHICKEN0 _MMIO(0xE5F0)
#define ICL_HDC_MODE _MMIO(0xE5F4)
#define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1<<15)
#define HDC_FENCE_DEST_SLM_DISABLE (1<<14)
#define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11)
......@@ -7216,6 +7259,9 @@ enum {
#define SLICE_ECO_CHICKEN0 _MMIO(0x7308)
#define PIXEL_MASK_CAMMING_DISABLE (1 << 14)
#define GEN9_WM_CHICKEN3 _MMIO(0x5588)
#define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9)
/* WaCatErrorRejectionIssue */
#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030)
#define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11)
......@@ -8214,8 +8260,30 @@ enum {
#define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4)
#define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6)
#define GEN8_GARBCNTL _MMIO(0xB004)
#define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7)
#define GEN8_GARBCNTL _MMIO(0xB004)
#define GEN9_GAPS_TSV_CREDIT_DISABLE (1 << 7)
#define GEN11_ARBITRATION_PRIO_ORDER_MASK (0x3f << 22)
#define GEN11_HASH_CTRL_EXCL_MASK (0x7f << 0)
#define GEN11_HASH_CTRL_EXCL_BIT0 (1 << 0)
#define GEN11_GLBLINVL _MMIO(0xB404)
#define GEN11_BANK_HASH_ADDR_EXCL_MASK (0x7f << 5)
#define GEN11_BANK_HASH_ADDR_EXCL_BIT0 (1 << 5)
#define GEN10_DFR_RATIO_EN_AND_CHICKEN _MMIO(0x9550)
#define DFR_DISABLE (1 << 9)
#define GEN11_GACB_PERF_CTRL _MMIO(0x4B80)
#define GEN11_HASH_CTRL_MASK (0x3 << 12 | 0xf << 0)
#define GEN11_HASH_CTRL_BIT0 (1 << 0)
#define GEN11_HASH_CTRL_BIT4 (1 << 12)
#define GEN11_LSN_UNSLCVC _MMIO(0xB43C)
#define GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC (1 << 9)
#define GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC (1 << 7)
#define GAMW_ECO_DEV_RW_IA_REG _MMIO(0x4080)
#define GAMW_ECO_DEV_CTX_RELOAD_DISABLE (1 << 7)
/* IVYBRIDGE DPF */
#define GEN7_L3CDERRST1(slice) _MMIO(0xB008 + (slice) * 0x200) /* L3CD Error Status 1 */
......@@ -8724,6 +8792,12 @@ enum skl_power_gate {
#define PORT_CLK_SEL_NONE (7<<29)
#define PORT_CLK_SEL_MASK (7<<29)
/* On ICL+ this is the same as PORT_CLK_SEL, but all bits change. */
#define DDI_CLK_SEL(port) PORT_CLK_SEL(port)
#define DDI_CLK_SEL_NONE (0x0 << 28)
#define DDI_CLK_SEL_MG (0x8 << 28)
#define DDI_CLK_SEL_MASK (0xF << 28)
/* Transcoder clock selection */
#define _TRANS_CLK_SEL_A 0x46140
#define _TRANS_CLK_SEL_B 0x46144
......@@ -8854,6 +8928,7 @@ enum skl_power_gate {
* CNL Clocks
*/
#define DPCLKA_CFGCR0 _MMIO(0x6C200)
#define DPCLKA_CFGCR0_ICL _MMIO(0x164280)
#define DPCLKA_CFGCR0_DDI_CLK_OFF(port) (1 << ((port) == PORT_F ? 23 : \
(port)+10))
#define DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port) == PORT_F ? 21 : \
......@@ -8870,10 +8945,141 @@ enum skl_power_gate {
#define PLL_POWER_STATE (1 << 26)
#define CNL_DPLL_ENABLE(pll) _MMIO_PLL(pll, DPLL0_ENABLE, DPLL1_ENABLE)
#define _MG_PLL1_ENABLE 0x46030
#define _MG_PLL2_ENABLE 0x46034
#define _MG_PLL3_ENABLE 0x46038
#define _MG_PLL4_ENABLE 0x4603C
/* Bits are the same as DPLL0_ENABLE */
#define MG_PLL_ENABLE(port) _MMIO_PORT((port) - PORT_C, _MG_PLL1_ENABLE, \
_MG_PLL2_ENABLE)
#define _MG_REFCLKIN_CTL_PORT1 0x16892C
#define _MG_REFCLKIN_CTL_PORT2 0x16992C
#define _MG_REFCLKIN_CTL_PORT3 0x16A92C
#define _MG_REFCLKIN_CTL_PORT4 0x16B92C
#define MG_REFCLKIN_CTL_OD_2_MUX(x) ((x) << 8)
#define MG_REFCLKIN_CTL(port) _MMIO_PORT((port) - PORT_C, \
_MG_REFCLKIN_CTL_PORT1, \
_MG_REFCLKIN_CTL_PORT2)
#define _MG_CLKTOP2_CORECLKCTL1_PORT1 0x1688D8
#define _MG_CLKTOP2_CORECLKCTL1_PORT2 0x1698D8
#define _MG_CLKTOP2_CORECLKCTL1_PORT3 0x16A8D8
#define _MG_CLKTOP2_CORECLKCTL1_PORT4 0x16B8D8
#define MG_CLKTOP2_CORECLKCTL1_B_DIVRATIO(x) ((x) << 16)
#define MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(x) ((x) << 8)
#define MG_CLKTOP2_CORECLKCTL1(port) _MMIO_PORT((port) - PORT_C, \
_MG_CLKTOP2_CORECLKCTL1_PORT1, \
_MG_CLKTOP2_CORECLKCTL1_PORT2)
#define _MG_CLKTOP2_HSCLKCTL_PORT1 0x1688D4
#define _MG_CLKTOP2_HSCLKCTL_PORT2 0x1698D4
#define _MG_CLKTOP2_HSCLKCTL_PORT3 0x16A8D4
#define _MG_CLKTOP2_HSCLKCTL_PORT4 0x16B8D4
#define MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(x) ((x) << 16)
#define MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(x) ((x) << 14)
#define MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO(x) ((x) << 12)
#define MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(x) ((x) << 8)
#define MG_CLKTOP2_HSCLKCTL(port) _MMIO_PORT((port) - PORT_C, \
_MG_CLKTOP2_HSCLKCTL_PORT1, \
_MG_CLKTOP2_HSCLKCTL_PORT2)
#define _MG_PLL_DIV0_PORT1 0x168A00
#define _MG_PLL_DIV0_PORT2 0x169A00
#define _MG_PLL_DIV0_PORT3 0x16AA00
#define _MG_PLL_DIV0_PORT4 0x16BA00
#define MG_PLL_DIV0_FRACNEN_H (1 << 30)
#define MG_PLL_DIV0_FBDIV_FRAC(x) ((x) << 8)
#define MG_PLL_DIV0_FBDIV_INT(x) ((x) << 0)
#define MG_PLL_DIV0(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV0_PORT1, \
_MG_PLL_DIV0_PORT2)
#define _MG_PLL_DIV1_PORT1 0x168A04
#define _MG_PLL_DIV1_PORT2 0x169A04
#define _MG_PLL_DIV1_PORT3 0x16AA04
#define _MG_PLL_DIV1_PORT4 0x16BA04
#define MG_PLL_DIV1_IREF_NDIVRATIO(x) ((x) << 16)
#define MG_PLL_DIV1_DITHER_DIV_1 (0 << 12)
#define MG_PLL_DIV1_DITHER_DIV_2 (1 << 12)
#define MG_PLL_DIV1_DITHER_DIV_4 (2 << 12)
#define MG_PLL_DIV1_DITHER_DIV_8 (3 << 12)
#define MG_PLL_DIV1_NDIVRATIO(x) ((x) << 4)
#define MG_PLL_DIV1_FBPREDIV(x) ((x) << 0)
#define MG_PLL_DIV1(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV1_PORT1, \
_MG_PLL_DIV1_PORT2)
#define _MG_PLL_LF_PORT1 0x168A08
#define _MG_PLL_LF_PORT2 0x169A08
#define _MG_PLL_LF_PORT3 0x16AA08
#define _MG_PLL_LF_PORT4 0x16BA08
#define MG_PLL_LF_TDCTARGETCNT(x) ((x) << 24)
#define MG_PLL_LF_AFCCNTSEL_256 (0 << 20)
#define MG_PLL_LF_AFCCNTSEL_512 (1 << 20)
#define MG_PLL_LF_GAINCTRL(x) ((x) << 16)
#define MG_PLL_LF_INT_COEFF(x) ((x) << 8)
#define MG_PLL_LF_PROP_COEFF(x) ((x) << 0)
#define MG_PLL_LF(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_LF_PORT1, \
_MG_PLL_LF_PORT2)
#define _MG_PLL_FRAC_LOCK_PORT1 0x168A0C
#define _MG_PLL_FRAC_LOCK_PORT2 0x169A0C
#define _MG_PLL_FRAC_LOCK_PORT3 0x16AA0C
#define _MG_PLL_FRAC_LOCK_PORT4 0x16BA0C
#define MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 (1 << 18)
#define MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 (1 << 16)
#define MG_PLL_FRAC_LOCK_LOCKTHRESH(x) ((x) << 11)
#define MG_PLL_FRAC_LOCK_DCODITHEREN (1 << 10)
#define MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN (1 << 8)
#define MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(x) ((x) << 0)
#define MG_PLL_FRAC_LOCK(port) _MMIO_PORT((port) - PORT_C, \
_MG_PLL_FRAC_LOCK_PORT1, \
_MG_PLL_FRAC_LOCK_PORT2)
#define _MG_PLL_SSC_PORT1 0x168A10
#define _MG_PLL_SSC_PORT2 0x169A10
#define _MG_PLL_SSC_PORT3 0x16AA10
#define _MG_PLL_SSC_PORT4 0x16BA10
#define MG_PLL_SSC_EN (1 << 28)
#define MG_PLL_SSC_TYPE(x) ((x) << 26)
#define MG_PLL_SSC_STEPLENGTH(x) ((x) << 16)
#define MG_PLL_SSC_STEPNUM(x) ((x) << 10)
#define MG_PLL_SSC_FLLEN (1 << 9)
#define MG_PLL_SSC_STEPSIZE(x) ((x) << 0)
#define MG_PLL_SSC(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_SSC_PORT1, \
_MG_PLL_SSC_PORT2)
#define _MG_PLL_BIAS_PORT1 0x168A14
#define _MG_PLL_BIAS_PORT2 0x169A14
#define _MG_PLL_BIAS_PORT3 0x16AA14
#define _MG_PLL_BIAS_PORT4 0x16BA14
#define MG_PLL_BIAS_BIAS_GB_SEL(x) ((x) << 30)
#define MG_PLL_BIAS_INIT_DCOAMP(x) ((x) << 24)
#define MG_PLL_BIAS_BIAS_BONUS(x) ((x) << 16)
#define MG_PLL_BIAS_BIASCAL_EN (1 << 15)
#define MG_PLL_BIAS_CTRIM(x) ((x) << 8)
#define MG_PLL_BIAS_VREF_RDAC(x) ((x) << 5)
#define MG_PLL_BIAS_IREFTRIM(x) ((x) << 0)
#define MG_PLL_BIAS(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_BIAS_PORT1, \
_MG_PLL_BIAS_PORT2)
#define _MG_PLL_TDC_COLDST_BIAS_PORT1 0x168A18
#define _MG_PLL_TDC_COLDST_BIAS_PORT2 0x169A18
#define _MG_PLL_TDC_COLDST_BIAS_PORT3 0x16AA18
#define _MG_PLL_TDC_COLDST_BIAS_PORT4 0x16BA18
#define MG_PLL_TDC_COLDST_IREFINT_EN (1 << 27)
#define MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(x) ((x) << 17)
#define MG_PLL_TDC_COLDST_COLDSTART (1 << 16)
#define MG_PLL_TDC_TDCOVCCORR_EN (1 << 2)
#define MG_PLL_TDC_TDCSEL(x) ((x) << 0)
#define MG_PLL_TDC_COLDST_BIAS(port) _MMIO_PORT((port) - PORT_C, \
_MG_PLL_TDC_COLDST_BIAS_PORT1, \
_MG_PLL_TDC_COLDST_BIAS_PORT2)
#define _CNL_DPLL0_CFGCR0 0x6C000
#define _CNL_DPLL1_CFGCR0 0x6C080
#define DPLL_CFGCR0_HDMI_MODE (1 << 30)
#define DPLL_CFGCR0_SSC_ENABLE (1 << 29)
#define DPLL_CFGCR0_SSC_ENABLE_ICL (1 << 25)
#define DPLL_CFGCR0_LINK_RATE_MASK (0xf << 25)
#define DPLL_CFGCR0_LINK_RATE_2700 (0 << 25)
#define DPLL_CFGCR0_LINK_RATE_1350 (1 << 25)
......@@ -8907,8 +9113,19 @@ enum skl_power_gate {
#define DPLL_CFGCR1_PDIV_5 (4 << 2)
#define DPLL_CFGCR1_PDIV_7 (8 << 2)
#define DPLL_CFGCR1_CENTRAL_FREQ (3 << 0)
#define DPLL_CFGCR1_CENTRAL_FREQ_8400 (3 << 0)
#define CNL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1)
#define _ICL_DPLL0_CFGCR0 0x164000
#define _ICL_DPLL1_CFGCR0 0x164080
#define ICL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR0, \
_ICL_DPLL1_CFGCR0)
#define _ICL_DPLL0_CFGCR1 0x164004
#define _ICL_DPLL1_CFGCR1 0x164084
#define ICL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _ICL_DPLL0_CFGCR1, \
_ICL_DPLL1_CFGCR1)
/* BXT display engine PLL */
#define BXT_DE_PLL_CTL _MMIO(0x6d000)
#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */
......@@ -9680,6 +9897,13 @@ enum skl_power_gate {
#define GEN9_MFX1_MOCS(i) _MMIO(0xca00 + (i) * 4) /* Media 1 MOCS registers */
#define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */
#define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */
/* Media decoder 2 MOCS registers */
#define GEN11_MFX2_MOCS(i) _MMIO(0x10000 + (i) * 4)
#define GEN10_SCRATCH_LNCF2 _MMIO(0xb0a0)
#define PMFLUSHDONE_LNICRSDROP (1 << 20)
#define PMFLUSH_GAPL3UNBLOCK (1 << 21)
#define PMFLUSHDONE_LNEBLK (1 << 22)
/* gamt regs */
#define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4)
......
此差异已折叠。
......@@ -28,13 +28,16 @@
#include <linux/dma-fence.h>
#include "i915_gem.h"
#include "i915_scheduler.h"
#include "i915_sw_fence.h"
#include "i915_scheduler.h"
#include <uapi/drm/i915_drm.h>
struct drm_file;
struct drm_i915_gem_object;
struct i915_request;
struct i915_timeline;
struct intel_wait {
struct rb_node node;
......@@ -48,44 +51,6 @@ struct intel_signal_node {
struct list_head link;
};
struct i915_dependency {
struct i915_priotree *signaler;
struct list_head signal_link;
struct list_head wait_link;
struct list_head dfs_link;
unsigned long flags;
#define I915_DEPENDENCY_ALLOC BIT(0)
};
/*
* "People assume that time is a strict progression of cause to effect, but
* actually, from a nonlinear, non-subjective viewpoint, it's more like a big
* ball of wibbly-wobbly, timey-wimey ... stuff." -The Doctor, 2015
*
* Requests exist in a complex web of interdependencies. Each request
* has to wait for some other request to complete before it is ready to be run
* (e.g. we have to wait until the pixels have been rendering into a texture
* before we can copy from it). We track the readiness of a request in terms
* of fences, but we also need to keep the dependency tree for the lifetime
* of the request (beyond the life of an individual fence). We use the tree
* at various points to reorder the requests whilst keeping the requests
* in order with respect to their various dependencies.
*/
struct i915_priotree {
struct list_head signalers_list; /* those before us, we depend upon */
struct list_head waiters_list; /* those after us, they depend upon us */
struct list_head link;
int priority;
};
enum {
I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1,
I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY,
I915_PRIORITY_MAX = I915_CONTEXT_MAX_USER_PRIORITY + 1,
I915_PRIORITY_INVALID = INT_MIN
};
struct i915_capture_list {
struct i915_capture_list *next;
struct i915_vma *vma;
......@@ -131,7 +96,7 @@ struct i915_request {
struct i915_gem_context *ctx;
struct intel_engine_cs *engine;
struct intel_ring *ring;
struct intel_timeline *timeline;
struct i915_timeline *timeline;
struct intel_signal_node signaling;
/*
......@@ -154,7 +119,7 @@ struct i915_request {
* to retirement), i.e. bidirectional dependency information for the
* request not tied to individual fences.
*/
struct i915_priotree priotree;
struct i915_sched_node sched;
struct i915_dependency dep;
/**
......@@ -343,10 +308,10 @@ static inline bool i915_request_started(const struct i915_request *rq)
seqno - 1);
}
static inline bool i915_priotree_signaled(const struct i915_priotree *pt)
static inline bool i915_sched_node_signaled(const struct i915_sched_node *node)
{
const struct i915_request *rq =
container_of(pt, const struct i915_request, priotree);
container_of(node, const struct i915_request, sched);
return i915_request_completed(rq);
}
......
/*
* SPDX-License-Identifier: MIT
*
* Copyright © 2018 Intel Corporation
*/
#ifndef _I915_SCHEDULER_H_
#define _I915_SCHEDULER_H_
#include <linux/bitops.h>
#include <uapi/drm/i915_drm.h>
enum {
I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1,
I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY,
I915_PRIORITY_MAX = I915_CONTEXT_MAX_USER_PRIORITY + 1,
I915_PRIORITY_INVALID = INT_MIN
};
struct i915_sched_attr {
/**
* @priority: execution and service priority
*
* All clients are equal, but some are more equal than others!
*
* Requests from a context with a greater (more positive) value of
* @priority will be executed before those with a lower @priority
* value, forming a simple QoS.
*
* The &drm_i915_private.kernel_context is assigned the lowest priority.
*/
int priority;
};
/*
* "People assume that time is a strict progression of cause to effect, but
* actually, from a nonlinear, non-subjective viewpoint, it's more like a big
* ball of wibbly-wobbly, timey-wimey ... stuff." -The Doctor, 2015
*
* Requests exist in a complex web of interdependencies. Each request
* has to wait for some other request to complete before it is ready to be run
* (e.g. we have to wait until the pixels have been rendering into a texture
* before we can copy from it). We track the readiness of a request in terms
* of fences, but we also need to keep the dependency tree for the lifetime
* of the request (beyond the life of an individual fence). We use the tree
* at various points to reorder the requests whilst keeping the requests
* in order with respect to their various dependencies.
*
* There is no active component to the "scheduler". As we know the dependency
* DAG of each request, we are able to insert it into a sorted queue when it
* is ready, and are able to reorder its portion of the graph to accommodate
* dynamic priority changes.
*/
struct i915_sched_node {
struct list_head signalers_list; /* those before us, we depend upon */
struct list_head waiters_list; /* those after us, they depend upon us */
struct list_head link;
struct i915_sched_attr attr;
};
struct i915_dependency {
struct i915_sched_node *signaler;
struct list_head signal_link;
struct list_head wait_link;
struct list_head dfs_link;
unsigned long flags;
#define I915_DEPENDENCY_ALLOC BIT(0)
};
#endif /* _I915_SCHEDULER_H_ */
/*
* SPDX-License-Identifier: MIT
*
* Copyright © 2016-2018 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_timeline.h"
#include "i915_syncmap.h"
void i915_timeline_init(struct drm_i915_private *i915,
struct i915_timeline *timeline,
const char *name)
{
lockdep_assert_held(&i915->drm.struct_mutex);
/*
* Ideally we want a set of engines on a single leaf as we expect
* to mostly be tracking synchronisation between engines. It is not
* a huge issue if this is not the case, but we may want to mitigate
* any page crossing penalties if they become an issue.
*/
BUILD_BUG_ON(KSYNCMAP < I915_NUM_ENGINES);
timeline->name = name;
list_add(&timeline->link, &i915->gt.timelines);
/* Called during early_init before we know how many engines there are */
timeline->fence_context = dma_fence_context_alloc(1);
spin_lock_init(&timeline->lock);
init_request_active(&timeline->last_request, NULL);
INIT_LIST_HEAD(&timeline->requests);
i915_syncmap_init(&timeline->sync);
}
/**
* i915_timelines_park - called when the driver idles
* @i915: the drm_i915_private device
*
* When the driver is completely idle, we know that all of our sync points
* have been signaled and our tracking is then entirely redundant. Any request
* to wait upon an older sync point will be completed instantly as we know
* the fence is signaled and therefore we will not even look them up in the
* sync point map.
*/
void i915_timelines_park(struct drm_i915_private *i915)
{
struct i915_timeline *timeline;
lockdep_assert_held(&i915->drm.struct_mutex);
list_for_each_entry(timeline, &i915->gt.timelines, link) {
/*
* All known fences are completed so we can scrap
* the current sync point tracking and start afresh,
* any attempt to wait upon a previous sync point
* will be skipped as the fence was signaled.
*/
i915_syncmap_free(&timeline->sync);
}
}
void i915_timeline_fini(struct i915_timeline *timeline)
{
GEM_BUG_ON(!list_empty(&timeline->requests));
i915_syncmap_free(&timeline->sync);
list_del(&timeline->link);
}
struct i915_timeline *
i915_timeline_create(struct drm_i915_private *i915, const char *name)
{
struct i915_timeline *timeline;
timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
if (!timeline)
return ERR_PTR(-ENOMEM);
i915_timeline_init(i915, timeline, name);
kref_init(&timeline->kref);
return timeline;
}
void __i915_timeline_free(struct kref *kref)
{
struct i915_timeline *timeline =
container_of(kref, typeof(*timeline), kref);
i915_timeline_fini(timeline);
kfree(timeline);
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_timeline.c"
#include "selftests/i915_timeline.c"
#endif
......@@ -22,27 +22,20 @@
*
*/
#ifndef I915_GEM_TIMELINE_H
#define I915_GEM_TIMELINE_H
#ifndef I915_TIMELINE_H
#define I915_TIMELINE_H
#include <linux/list.h>
#include <linux/kref.h>
#include "i915_request.h"
#include "i915_syncmap.h"
#include "i915_utils.h"
struct i915_gem_timeline;
struct intel_timeline {
struct i915_timeline {
u64 fence_context;
u32 seqno;
/**
* Count of outstanding requests, from the time they are constructed
* to the moment they are retired. Loosely coupled to hardware.
*/
u32 inflight_seqnos;
spinlock_t lock;
/**
......@@ -77,47 +70,57 @@ struct intel_timeline {
*/
u32 global_sync[I915_NUM_ENGINES];
struct i915_gem_timeline *common;
};
struct i915_gem_timeline {
struct list_head link;
struct drm_i915_private *i915;
const char *name;
struct intel_timeline engine[I915_NUM_ENGINES];
struct kref kref;
};
int i915_gem_timeline_init(struct drm_i915_private *i915,
struct i915_gem_timeline *tl,
const char *name);
int i915_gem_timeline_init__global(struct drm_i915_private *i915);
void i915_gem_timelines_park(struct drm_i915_private *i915);
void i915_gem_timeline_fini(struct i915_gem_timeline *tl);
void i915_timeline_init(struct drm_i915_private *i915,
struct i915_timeline *tl,
const char *name);
void i915_timeline_fini(struct i915_timeline *tl);
struct i915_timeline *
i915_timeline_create(struct drm_i915_private *i915, const char *name);
static inline int __intel_timeline_sync_set(struct intel_timeline *tl,
u64 context, u32 seqno)
static inline struct i915_timeline *
i915_timeline_get(struct i915_timeline *timeline)
{
kref_get(&timeline->kref);
return timeline;
}
void __i915_timeline_free(struct kref *kref);
static inline void i915_timeline_put(struct i915_timeline *timeline)
{
kref_put(&timeline->kref, __i915_timeline_free);
}
static inline int __i915_timeline_sync_set(struct i915_timeline *tl,
u64 context, u32 seqno)
{
return i915_syncmap_set(&tl->sync, context, seqno);
}
static inline int intel_timeline_sync_set(struct intel_timeline *tl,
const struct dma_fence *fence)
static inline int i915_timeline_sync_set(struct i915_timeline *tl,
const struct dma_fence *fence)
{
return __intel_timeline_sync_set(tl, fence->context, fence->seqno);
return __i915_timeline_sync_set(tl, fence->context, fence->seqno);
}
static inline bool __intel_timeline_sync_is_later(struct intel_timeline *tl,
u64 context, u32 seqno)
static inline bool __i915_timeline_sync_is_later(struct i915_timeline *tl,
u64 context, u32 seqno)
{
return i915_syncmap_is_later(&tl->sync, context, seqno);
}
static inline bool intel_timeline_sync_is_later(struct intel_timeline *tl,
const struct dma_fence *fence)
static inline bool i915_timeline_sync_is_later(struct i915_timeline *tl,
const struct dma_fence *fence)
{
return __intel_timeline_sync_is_later(tl, fence->context, fence->seqno);
return __i915_timeline_sync_is_later(tl, fence->context, fence->seqno);
}
void i915_timelines_park(struct drm_i915_private *i915);
#endif
......@@ -679,45 +679,68 @@ DEFINE_EVENT(i915_request, i915_request_execute,
TP_ARGS(rq)
);
DECLARE_EVENT_CLASS(i915_request_hw,
TP_PROTO(struct i915_request *rq, unsigned int port),
TP_ARGS(rq, port),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, hw_id)
__field(u32, ring)
__field(u32, ctx)
__field(u32, seqno)
__field(u32, global_seqno)
__field(u32, port)
),
TP_fast_assign(
__entry->dev = rq->i915->drm.primary->index;
__entry->hw_id = rq->ctx->hw_id;
__entry->ring = rq->engine->id;
__entry->ctx = rq->fence.context;
__entry->seqno = rq->fence.seqno;
__entry->global_seqno = rq->global_seqno;
__entry->port = port;
),
TP_printk("dev=%u, hw_id=%u, ring=%u, ctx=%u, seqno=%u, global=%u, port=%u",
__entry->dev, __entry->hw_id, __entry->ring,
__entry->ctx, __entry->seqno,
__entry->global_seqno, __entry->port)
);
TRACE_EVENT(i915_request_in,
TP_PROTO(struct i915_request *rq, unsigned int port),
TP_ARGS(rq, port),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, hw_id)
__field(u32, ring)
__field(u32, ctx)
__field(u32, seqno)
__field(u32, global_seqno)
__field(u32, port)
__field(u32, prio)
),
TP_fast_assign(
__entry->dev = rq->i915->drm.primary->index;
__entry->hw_id = rq->ctx->hw_id;
__entry->ring = rq->engine->id;
__entry->ctx = rq->fence.context;
__entry->seqno = rq->fence.seqno;
__entry->global_seqno = rq->global_seqno;
__entry->prio = rq->sched.attr.priority;
__entry->port = port;
),
DEFINE_EVENT(i915_request_hw, i915_request_in,
TP_PROTO(struct i915_request *rq, unsigned int port),
TP_ARGS(rq, port)
TP_printk("dev=%u, hw_id=%u, ring=%u, ctx=%u, seqno=%u, prio=%u, global=%u, port=%u",
__entry->dev, __entry->hw_id, __entry->ring, __entry->ctx,
__entry->seqno, __entry->prio, __entry->global_seqno,
__entry->port)
);
DEFINE_EVENT(i915_request, i915_request_out,
TP_PROTO(struct i915_request *rq),
TP_ARGS(rq)
TRACE_EVENT(i915_request_out,
TP_PROTO(struct i915_request *rq),
TP_ARGS(rq),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, hw_id)
__field(u32, ring)
__field(u32, ctx)
__field(u32, seqno)
__field(u32, global_seqno)
__field(u32, completed)
),
TP_fast_assign(
__entry->dev = rq->i915->drm.primary->index;
__entry->hw_id = rq->ctx->hw_id;
__entry->ring = rq->engine->id;
__entry->ctx = rq->fence.context;
__entry->seqno = rq->fence.seqno;
__entry->global_seqno = rq->global_seqno;
__entry->completed = i915_request_completed(rq);
),
TP_printk("dev=%u, hw_id=%u, ring=%u, ctx=%u, seqno=%u, global=%u, completed?=%u",
__entry->dev, __entry->hw_id, __entry->ring,
__entry->ctx, __entry->seqno,
__entry->global_seqno, __entry->completed)
);
#else
#if !defined(TRACE_HEADER_MULTI_READ)
static inline void
......@@ -811,42 +834,6 @@ DEFINE_EVENT(i915_request, i915_request_wait_end,
TP_ARGS(rq)
);
TRACE_EVENT(i915_flip_request,
TP_PROTO(int plane, struct drm_i915_gem_object *obj),
TP_ARGS(plane, obj),
TP_STRUCT__entry(
__field(int, plane)
__field(struct drm_i915_gem_object *, obj)
),
TP_fast_assign(
__entry->plane = plane;
__entry->obj = obj;
),
TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
);
TRACE_EVENT(i915_flip_complete,
TP_PROTO(int plane, struct drm_i915_gem_object *obj),
TP_ARGS(plane, obj),
TP_STRUCT__entry(
__field(int, plane)
__field(struct drm_i915_gem_object *, obj)
),
TP_fast_assign(
__entry->plane = plane;
__entry->obj = obj;
),
TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
);
TRACE_EVENT_CONDITION(i915_reg_rw,
TP_PROTO(bool write, i915_reg_t reg, u64 val, int len, bool trace),
......
......@@ -120,6 +120,12 @@ static inline u64 ptr_to_u64(const void *ptr)
#include <linux/list.h>
static inline int list_is_first(const struct list_head *list,
const struct list_head *head)
{
return head->next == list;
}
static inline void __list_del_many(struct list_head *head,
struct list_head *first)
{
......
......@@ -46,8 +46,6 @@ i915_vma_retire(struct i915_gem_active *active, struct i915_request *rq)
GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
WARN_ON(i915_vma_unbind(vma));
GEM_BUG_ON(!i915_gem_object_is_active(obj));
if (--obj->active_count)
......@@ -232,7 +230,6 @@ i915_vma_instance(struct drm_i915_gem_object *obj,
if (!vma)
vma = vma_create(obj, vm, view);
GEM_BUG_ON(!IS_ERR(vma) && i915_vma_is_closed(vma));
GEM_BUG_ON(!IS_ERR(vma) && i915_vma_compare(vma, vm, view));
GEM_BUG_ON(!IS_ERR(vma) && vma_lookup(obj, vm, view) != vma);
return vma;
......@@ -684,13 +681,43 @@ int __i915_vma_do_pin(struct i915_vma *vma,
return ret;
}
static void i915_vma_destroy(struct i915_vma *vma)
void i915_vma_close(struct i915_vma *vma)
{
lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
GEM_BUG_ON(i915_vma_is_closed(vma));
vma->flags |= I915_VMA_CLOSED;
/*
* We defer actually closing, unbinding and destroying the VMA until
* the next idle point, or if the object is freed in the meantime. By
* postponing the unbind, we allow for it to be resurrected by the
* client, avoiding the work required to rebind the VMA. This is
* advantageous for DRI, where the client/server pass objects
* between themselves, temporarily opening a local VMA to the
* object, and then closing it again. The same object is then reused
* on the next frame (or two, depending on the depth of the swap queue)
* causing us to rebind the VMA once more. This ends up being a lot
* of wasted work for the steady state.
*/
list_add_tail(&vma->closed_link, &vma->vm->i915->gt.closed_vma);
}
void i915_vma_reopen(struct i915_vma *vma)
{
lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
if (vma->flags & I915_VMA_CLOSED) {
vma->flags &= ~I915_VMA_CLOSED;
list_del(&vma->closed_link);
}
}
static void __i915_vma_destroy(struct i915_vma *vma)
{
int i;
GEM_BUG_ON(vma->node.allocated);
GEM_BUG_ON(i915_vma_is_active(vma));
GEM_BUG_ON(!i915_vma_is_closed(vma));
GEM_BUG_ON(vma->fence);
for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
......@@ -699,6 +726,7 @@ static void i915_vma_destroy(struct i915_vma *vma)
list_del(&vma->obj_link);
list_del(&vma->vm_link);
rb_erase(&vma->obj_node, &vma->obj->vma_tree);
if (!i915_vma_is_ggtt(vma))
i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
......@@ -706,15 +734,30 @@ static void i915_vma_destroy(struct i915_vma *vma)
kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
}
void i915_vma_close(struct i915_vma *vma)
void i915_vma_destroy(struct i915_vma *vma)
{
GEM_BUG_ON(i915_vma_is_closed(vma));
vma->flags |= I915_VMA_CLOSED;
lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
rb_erase(&vma->obj_node, &vma->obj->vma_tree);
GEM_BUG_ON(i915_vma_is_active(vma));
GEM_BUG_ON(i915_vma_is_pinned(vma));
if (i915_vma_is_closed(vma))
list_del(&vma->closed_link);
WARN_ON(i915_vma_unbind(vma));
__i915_vma_destroy(vma);
}
void i915_vma_parked(struct drm_i915_private *i915)
{
struct i915_vma *vma, *next;
if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
WARN_ON(i915_vma_unbind(vma));
list_for_each_entry_safe(vma, next, &i915->gt.closed_vma, closed_link) {
GEM_BUG_ON(!i915_vma_is_closed(vma));
i915_vma_destroy(vma);
}
GEM_BUG_ON(!list_empty(&i915->gt.closed_vma));
}
static void __i915_vma_iounmap(struct i915_vma *vma)
......@@ -804,7 +847,7 @@ int i915_vma_unbind(struct i915_vma *vma)
return -EBUSY;
if (!drm_mm_node_allocated(&vma->node))
goto destroy;
return 0;
GEM_BUG_ON(obj->bind_count == 0);
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
......@@ -841,10 +884,6 @@ int i915_vma_unbind(struct i915_vma *vma)
i915_vma_remove(vma);
destroy:
if (unlikely(i915_vma_is_closed(vma)))
i915_vma_destroy(vma);
return 0;
}
......
......@@ -119,6 +119,8 @@ struct i915_vma {
/** This vma's place in the eviction list */
struct list_head evict_link;
struct list_head closed_link;
/**
* Used for performing relocations during execbuffer insertion.
*/
......@@ -285,6 +287,8 @@ void i915_vma_revoke_mmap(struct i915_vma *vma);
int __must_check i915_vma_unbind(struct i915_vma *vma);
void i915_vma_unlink_ctx(struct i915_vma *vma);
void i915_vma_close(struct i915_vma *vma);
void i915_vma_reopen(struct i915_vma *vma);
void i915_vma_destroy(struct i915_vma *vma);
int __i915_vma_do_pin(struct i915_vma *vma,
u64 size, u64 alignment, u64 flags);
......@@ -408,6 +412,8 @@ i915_vma_unpin_fence(struct i915_vma *vma)
__i915_vma_unpin_fence(vma);
}
void i915_vma_parked(struct drm_i915_private *i915);
#define for_each_until(cond) if (cond) break; else
/**
......
......@@ -183,11 +183,16 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
}
/* FIXME pre-g4x don't work like this */
if (intel_state->base.visible)
if (state->visible)
crtc_state->active_planes |= BIT(intel_plane->id);
else
crtc_state->active_planes &= ~BIT(intel_plane->id);
if (state->visible && state->fb->format->format == DRM_FORMAT_NV12)
crtc_state->nv12_planes |= BIT(intel_plane->id);
else
crtc_state->nv12_planes &= ~BIT(intel_plane->id);
return intel_plane_atomic_calc_changes(old_crtc_state,
&crtc_state->base,
old_plane_state,
......
......@@ -530,6 +530,7 @@ parse_driver_features(struct drm_i915_private *dev_priv,
*/
if (!driver->drrs_enabled)
dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
dev_priv->vbt.psr.enable = driver->psr_enabled;
}
static void
......
......@@ -82,7 +82,7 @@ static unsigned long wait_timeout(void)
static noinline void missed_breadcrumb(struct intel_engine_cs *engine)
{
if (drm_debug & DRM_UT_DRIVER) {
if (GEM_SHOW_DEBUG()) {
struct drm_printer p = drm_debug_printer(__func__);
intel_engine_dump(engine, &p,
......@@ -130,11 +130,12 @@ static void intel_breadcrumbs_hangcheck(struct timer_list *t)
static void intel_breadcrumbs_fake_irq(struct timer_list *t)
{
struct intel_engine_cs *engine = from_timer(engine, t,
breadcrumbs.fake_irq);
struct intel_engine_cs *engine =
from_timer(engine, t, breadcrumbs.fake_irq);
struct intel_breadcrumbs *b = &engine->breadcrumbs;
/* The timer persists in case we cannot enable interrupts,
/*
* The timer persists in case we cannot enable interrupts,
* or if we have previously seen seqno/interrupt incoherency
* ("missed interrupt" syndrome, better known as a "missed breadcrumb").
* 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)
if (!b->irq_armed)
return;
/* If the user has disabled the fake-irq, restore the hangchecking */
if (!test_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings)) {
mod_timer(&b->hangcheck, wait_timeout());
return;
}
mod_timer(&b->fake_irq, jiffies + 1);
}
......@@ -831,8 +838,8 @@ static void cancel_fake_irq(struct intel_engine_cs *engine)
{
struct intel_breadcrumbs *b = &engine->breadcrumbs;
del_timer_sync(&b->fake_irq); /* may queue b->hangcheck */
del_timer_sync(&b->hangcheck);
del_timer_sync(&b->fake_irq);
clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings);
}
......@@ -840,15 +847,22 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine)
{
struct intel_breadcrumbs *b = &engine->breadcrumbs;
cancel_fake_irq(engine);
spin_lock_irq(&b->irq_lock);
/*
* Leave the fake_irq timer enabled (if it is running), but clear the
* bit so that it turns itself off on its next wake up and goes back
* to the long hangcheck interval if still required.
*/
clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings);
if (b->irq_enabled)
irq_enable(engine);
else
irq_disable(engine);
/* We set the IRQ_BREADCRUMB bit when we enable the irq presuming the
/*
* We set the IRQ_BREADCRUMB bit when we enable the irq presuming the
* GPU is active and may have already executed the MI_USER_INTERRUPT
* before the CPU is ready to receive. However, the engine is currently
* 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)
*/
clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
if (b->irq_armed)
enable_fake_irq(b);
spin_unlock_irq(&b->irq_lock);
}
......
......@@ -2302,9 +2302,44 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
return 0;
}
static int skl_dpll0_vco(struct intel_atomic_state *intel_state)
{
struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
struct intel_crtc *crtc;
struct intel_crtc_state *crtc_state;
int vco, i;
vco = intel_state->cdclk.logical.vco;
if (!vco)
vco = dev_priv->skl_preferred_vco_freq;
for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
if (!crtc_state->base.enable)
continue;
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
continue;
/*
* DPLL0 VCO may need to be adjusted to get the correct
* clock for eDP. This will affect cdclk as well.
*/
switch (crtc_state->port_clock / 2) {
case 108000:
case 216000:
vco = 8640000;
break;
default:
vco = 8100000;
break;
}
}
return vco;
}
static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
{
struct drm_i915_private *dev_priv = to_i915(state->dev);
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
int min_cdclk, cdclk, vco;
......@@ -2312,9 +2347,7 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
if (min_cdclk < 0)
return min_cdclk;
vco = intel_state->cdclk.logical.vco;
if (!vco)
vco = dev_priv->skl_preferred_vco_freq;
vco = skl_dpll0_vco(intel_state);
/*
* FIXME should also account for plane ratio
......
......@@ -298,7 +298,10 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
csr->version = css_header->version;
if (IS_CANNONLAKE(dev_priv)) {
if (csr->fw_path == i915_modparams.dmc_firmware_path) {
/* Bypass version check for firmware override. */
required_version = csr->version;
} else if (IS_CANNONLAKE(dev_priv)) {
required_version = CNL_CSR_VERSION_REQUIRED;
} else if (IS_GEMINILAKE(dev_priv)) {
required_version = GLK_CSR_VERSION_REQUIRED;
......@@ -453,7 +456,9 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
if (!HAS_CSR(dev_priv))
return;
if (IS_CANNONLAKE(dev_priv))
if (i915_modparams.dmc_firmware_path)
csr->fw_path = i915_modparams.dmc_firmware_path;
else if (IS_CANNONLAKE(dev_priv))
csr->fw_path = I915_CSR_CNL;
else if (IS_GEMINILAKE(dev_priv))
csr->fw_path = I915_CSR_GLK;
......
......@@ -870,6 +870,45 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
}
}
static const struct icl_combo_phy_ddi_buf_trans *
icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
int type, int *n_entries)
{
u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
switch (voltage) {
case VOLTAGE_INFO_0_85V:
*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
return icl_combo_phy_ddi_translations_edp_0_85V;
case VOLTAGE_INFO_0_95V:
*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
return icl_combo_phy_ddi_translations_edp_0_95V;
case VOLTAGE_INFO_1_05V:
*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
return icl_combo_phy_ddi_translations_edp_1_05V;
default:
MISSING_CASE(voltage);
return NULL;
}
} else {
switch (voltage) {
case VOLTAGE_INFO_0_85V:
*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
case VOLTAGE_INFO_0_95V:
*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
case VOLTAGE_INFO_1_05V:
*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
default:
MISSING_CASE(voltage);
return NULL;
}
}
}
static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
{
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)
}
}
static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
const struct intel_shared_dpll *pll)
{
const enum intel_dpll_id id = pll->info->id;
switch (id) {
default:
MISSING_CASE(id);
case DPLL_ID_ICL_DPLL0:
case DPLL_ID_ICL_DPLL1:
return DDI_CLK_SEL_NONE;
case DPLL_ID_ICL_MGPLL1:
case DPLL_ID_ICL_MGPLL2:
case DPLL_ID_ICL_MGPLL3:
case DPLL_ID_ICL_MGPLL4:
return DDI_CLK_SEL_MG;
}
}
/* Starting with Haswell, different DDI ports can work in FDI mode for
* connection to the PCH-located connectors. For this, it is necessary to train
* 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)
enum port port = encoder->port;
int n_entries;
if (IS_CANNONLAKE(dev_priv)) {
if (IS_ICELAKE(dev_priv)) {
if (port == PORT_A || port == PORT_B)
icl_get_combo_buf_trans(dev_priv, port, encoder->type,
&n_entries);
else
n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
} else if (IS_CANNONLAKE(dev_priv)) {
if (encoder->type == INTEL_OUTPUT_EDP)
cnl_get_buf_trans_edp(dev_priv, &n_entries);
else
......@@ -2182,6 +2246,146 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val);
}
static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
u32 level, enum port port, int type)
{
const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
u32 n_entries, val;
int ln;
ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
&n_entries);
if (!ddi_translations)
return;
if (level >= n_entries) {
DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);
level = n_entries - 1;
}
/* Set PORT_TX_DW5 Rterm Sel to 110b. */
val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
val &= ~RTERM_SELECT_MASK;
val |= RTERM_SELECT(0x6);
I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
/* Program PORT_TX_DW5 */
val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
/* Set DisableTap2 and DisableTap3 if MIPI DSI
* Clear DisableTap2 and DisableTap3 for all other Ports
*/
if (type == INTEL_OUTPUT_DSI) {
val |= TAP2_DISABLE;
val |= TAP3_DISABLE;
} else {
val &= ~TAP2_DISABLE;
val &= ~TAP3_DISABLE;
}
I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
/* Program PORT_TX_DW2 */
val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
RCOMP_SCALAR_MASK);
val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
/* Program Rcomp scalar for every table entry */
val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
/* Program PORT_TX_DW4 */
/* We cannot write to GRP. It would overwrite individual loadgen. */
for (ln = 0; ln <= 3; ln++) {
val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
CURSOR_COEFF_MASK);
val |= ddi_translations[level].dw4_scaling;
I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
}
}
static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
u32 level,
enum intel_output_type type)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum port port = encoder->port;
int width = 0;
int rate = 0;
u32 val;
int ln = 0;
if (type == INTEL_OUTPUT_HDMI) {
width = 4;
/* Rate is always < than 6GHz for HDMI */
} else {
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
width = intel_dp->lane_count;
rate = intel_dp->link_rate;
}
/*
* 1. If port type is eDP or DP,
* set PORT_PCS_DW1 cmnkeeper_enable to 1b,
* else clear to 0b.
*/
val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
if (type == INTEL_OUTPUT_HDMI)
val &= ~COMMON_KEEPER_EN;
else
val |= COMMON_KEEPER_EN;
I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
/* 2. Program loadgen select */
/*
* Program PORT_TX_DW4_LN depending on Bit rate and used lanes
* <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
* <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
* > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
*/
for (ln = 0; ln <= 3; ln++) {
val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
val &= ~LOADGEN_SELECT;
if ((rate <= 600000 && width == 4 && ln >= 1) ||
(rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
val |= LOADGEN_SELECT;
}
I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
}
/* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
val = I915_READ(ICL_PORT_CL_DW5(port));
val |= SUS_CLOCK_CONFIG;
I915_WRITE(ICL_PORT_CL_DW5(port), val);
/* 4. Clear training enable to change swing values */
val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
val &= ~TX_TRAINING_EN;
I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
/* 5. Program swing and de-emphasis */
icl_ddi_combo_vswing_program(dev_priv, level, port, type);
/* 6. Set training enable to trigger update */
val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
val |= TX_TRAINING_EN;
I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
}
static void icl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level,
enum intel_output_type type)
{
enum port port = encoder->port;
if (port == PORT_A || port == PORT_B)
icl_combo_phy_ddi_vswing_sequence(encoder, level, type);
else
/* Not Implemented Yet */
WARN_ON(1);
}
static uint32_t translate_signal_level(int signal_levels)
{
int i;
......@@ -2213,7 +2417,9 @@ u32 bxt_signal_levels(struct intel_dp *intel_dp)
struct intel_encoder *encoder = &dport->base;
int level = intel_ddi_dp_level(intel_dp);
if (IS_CANNONLAKE(dev_priv))
if (IS_ICELAKE(dev_priv))
icl_ddi_vswing_sequence(encoder, level, encoder->type);
else if (IS_CANNONLAKE(dev_priv))
cnl_ddi_vswing_sequence(encoder, level, encoder->type);
else
bxt_ddi_vswing_sequence(encoder, level, encoder->type);
......@@ -2234,6 +2440,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
return DDI_BUF_TRANS_SELECT(level);
}
void icl_map_plls_to_ports(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct drm_atomic_state *old_state)
{
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct drm_connector_state *conn_state;
struct drm_connector *conn;
int i;
for_each_new_connector_in_state(old_state, conn, conn_state, i) {
struct intel_encoder *encoder =
to_intel_encoder(conn_state->best_encoder);
enum port port = encoder->port;
uint32_t val;
if (conn_state->crtc != crtc)
continue;
mutex_lock(&dev_priv->dpll_lock);
val = I915_READ(DPCLKA_CFGCR0_ICL);
WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
if (port == PORT_A || port == PORT_B) {
val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
POSTING_READ(DPCLKA_CFGCR0_ICL);
}
val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
mutex_unlock(&dev_priv->dpll_lock);
}
}
void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct drm_atomic_state *old_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct drm_connector_state *old_conn_state;
struct drm_connector *conn;
int i;
for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
struct intel_encoder *encoder =
to_intel_encoder(old_conn_state->best_encoder);
enum port port = encoder->port;
if (old_conn_state->crtc != crtc)
continue;
mutex_lock(&dev_priv->dpll_lock);
I915_WRITE(DPCLKA_CFGCR0_ICL,
I915_READ(DPCLKA_CFGCR0_ICL) |
DPCLKA_CFGCR0_DDI_CLK_OFF(port));
mutex_unlock(&dev_priv->dpll_lock);
}
}
static void intel_ddi_clk_select(struct intel_encoder *encoder,
const struct intel_shared_dpll *pll)
{
......@@ -2246,7 +2515,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
mutex_lock(&dev_priv->dpll_lock);
if (IS_CANNONLAKE(dev_priv)) {
if (IS_ICELAKE(dev_priv)) {
if (port >= PORT_C)
I915_WRITE(DDI_CLK_SEL(port),
icl_pll_to_ddi_pll_sel(encoder, pll));
} else if (IS_CANNONLAKE(dev_priv)) {
/* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
val = I915_READ(DPCLKA_CFGCR0);
val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
......@@ -2284,14 +2557,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum port port = encoder->port;
if (IS_CANNONLAKE(dev_priv))
if (IS_ICELAKE(dev_priv)) {
if (port >= PORT_C)
I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
} else if (IS_CANNONLAKE(dev_priv)) {
I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
DPCLKA_CFGCR0_DDI_CLK_OFF(port));
else if (IS_GEN9_BC(dev_priv))
} else if (IS_GEN9_BC(dev_priv)) {
I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
DPLL_CTRL2_DDI_CLK_OFF(port));
else if (INTEL_GEN(dev_priv) < 9)
} else if (INTEL_GEN(dev_priv) < 9) {
I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
}
}
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,
intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
if (IS_CANNONLAKE(dev_priv))
if (IS_ICELAKE(dev_priv))
icl_ddi_vswing_sequence(encoder, level, encoder->type);
else if (IS_CANNONLAKE(dev_priv))
cnl_ddi_vswing_sequence(encoder, level, encoder->type);
else if (IS_GEN9_LP(dev_priv))
bxt_ddi_vswing_sequence(encoder, level, encoder->type);
......@@ -2347,7 +2626,9 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
if (IS_CANNONLAKE(dev_priv))
if (IS_ICELAKE(dev_priv))
icl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
else if (IS_CANNONLAKE(dev_priv))
cnl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
else if (IS_GEN9_LP(dev_priv))
bxt_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
......
......@@ -848,7 +848,7 @@ void intel_device_info_runtime_init(struct intel_device_info *info)
gen9_sseu_info_init(dev_priv);
else if (INTEL_GEN(dev_priv) == 10)
gen10_sseu_info_init(dev_priv);
else if (INTEL_INFO(dev_priv)->gen >= 11)
else if (INTEL_GEN(dev_priv) >= 11)
gen11_sseu_info_init(dev_priv);
/* Initialize command stream timestamp frequency */
......
......@@ -218,6 +218,10 @@ struct intel_link_m_n {
for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) \
for_each_if((__mask) & BIT(__p))
#define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \
for ((__t) = 0; (__t) < I915_MAX_TRANSCODERS; (__t)++) \
for_each_if ((__mask) & (1 << (__t)))
#define for_each_universal_plane(__dev_priv, __pipe, __p) \
for ((__p) = 0; \
(__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \
......
此差异已折叠。
......@@ -139,6 +139,11 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
intel_dp_compute_rate(intel_dp, intel_dp->link_rate,
&link_bw, &rate_select);
if (link_bw)
DRM_DEBUG_KMS("Using LINK_BW_SET value %02x\n", link_bw);
else
DRM_DEBUG_KMS("Using LINK_RATE_SET value %02x\n", rate_select);
/* Write the link configuration data */
link_config[0] = link_bw;
link_config[1] = intel_dp->lane_count;
......
......@@ -103,6 +103,32 @@ enum intel_dpll_id {
* @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
*/
DPLL_ID_SKL_DPLL3 = 3,
/**
* @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
*/
DPLL_ID_ICL_DPLL0 = 0,
/**
* @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
*/
DPLL_ID_ICL_DPLL1 = 1,
/**
* @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
*/
DPLL_ID_ICL_MGPLL1 = 2,
/**
* @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
*/
DPLL_ID_ICL_MGPLL2 = 3,
/**
* @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
*/
DPLL_ID_ICL_MGPLL3 = 4,
/**
* @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
*/
DPLL_ID_ICL_MGPLL4 = 5,
};
#define I915_NUM_PLLS 6
......@@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
/* bxt */
uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
pcsdw12;
/*
* ICL uses the following, already defined:
* uint32_t cfgcr0, cfgcr1;
*/
uint32_t mg_refclkin_ctl;
uint32_t mg_clktop2_coreclkctl1;
uint32_t mg_clktop2_hsclkctl;
uint32_t mg_pll_div0;
uint32_t mg_pll_div1;
uint32_t mg_pll_lf;
uint32_t mg_pll_frac_lock;
uint32_t mg_pll_ssc;
uint32_t mg_pll_bias;
uint32_t mg_pll_tdc_coldst_bias;
};
/**
......
......@@ -56,6 +56,8 @@
for (;;) { \
const bool expired__ = ktime_after(ktime_get_raw(), end__); \
OP; \
/* Guarantee COND check prior to timeout */ \
barrier(); \
if (COND) { \
ret__ = 0; \
break; \
......@@ -96,6 +98,8 @@
u64 now = local_clock(); \
if (!(ATOMIC)) \
preempt_enable(); \
/* Guarantee COND check prior to timeout */ \
barrier(); \
if (COND) { \
ret = 0; \
break; \
......@@ -140,6 +144,10 @@
#define KHz(x) (1000 * (x))
#define MHz(x) KHz(1000 * (x))
#define KBps(x) (1000 * (x))
#define MBps(x) KBps(1000 * (x))
#define GBps(x) ((u64)1000 * MBps((x)))
/*
* Display related stuff
*/
......@@ -882,6 +890,7 @@ struct intel_crtc_state {
/* bitmask of visible planes (enum plane_id) */
u8 active_planes;
u8 nv12_planes;
/* HDMI scrambling status */
bool hdmi_scrambling;
......@@ -1329,6 +1338,9 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv);
void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
/* i915_irq.c */
bool gen11_reset_one_iir(struct drm_i915_private * const i915,
const unsigned int bank,
const unsigned int bit);
void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
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);
u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
bool enable);
void icl_map_plls_to_ports(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct drm_atomic_state *old_state);
void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state,
struct drm_atomic_state *old_state);
unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
int plane, unsigned int height);
......@@ -1580,8 +1598,6 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv);
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
void gen9_enable_dc5(struct drm_i915_private *dev_priv);
unsigned int skl_cdclk_get_vco(unsigned int freq);
void skl_enable_dc6(struct drm_i915_private *dev_priv);
void skl_disable_dc6(struct drm_i915_private *dev_priv);
void intel_dp_get_m_n(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config);
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,
unsigned frontbuffer_bits);
void intel_psr_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug);
void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir);
/* intel_runtime_pm.c */
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,
enum intel_display_power_domain domain);
void intel_display_power_put(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
u8 req_slices);
static inline void
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);
bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
enum pipe pipe, enum plane_id plane_id);
bool intel_format_is_yuv(uint32_t format);
bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
enum pipe pipe, enum plane_id plane_id);
/* intel_tv.c */
void intel_tv_init(struct drm_i915_private *dev_priv);
......
......@@ -647,6 +647,11 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
/* prepare count */
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul);
if (prepare_cnt > PREPARE_CNT_MAX) {
DRM_DEBUG_KMS("prepare count too high %u\n", prepare_cnt);
prepare_cnt = PREPARE_CNT_MAX;
}
/* exit zero count */
exit_zero_cnt = DIV_ROUND_UP(
(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)
if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num)
exit_zero_cnt += 1;
if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
DRM_DEBUG_KMS("exit zero count too high %u\n", exit_zero_cnt);
exit_zero_cnt = EXIT_ZERO_CNT_MAX;
}
/* clk zero count */
clk_zero_cnt = DIV_ROUND_UP(
(tclk_prepare_clkzero - ths_prepare_ns)
* ui_den, ui_num * mul);
if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
DRM_DEBUG_KMS("clock zero count too high %u\n", clk_zero_cnt);
clk_zero_cnt = CLK_ZERO_CNT_MAX;
}
/* trail count */
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
if (prepare_cnt > PREPARE_CNT_MAX ||
exit_zero_cnt > EXIT_ZERO_CNT_MAX ||
clk_zero_cnt > CLK_ZERO_CNT_MAX ||
trail_cnt > TRAIL_CNT_MAX)
DRM_DEBUG_DRIVER("Values crossing maximum limits, restricting to max values\n");
if (prepare_cnt > PREPARE_CNT_MAX)
prepare_cnt = PREPARE_CNT_MAX;
if (exit_zero_cnt > EXIT_ZERO_CNT_MAX)
exit_zero_cnt = EXIT_ZERO_CNT_MAX;
if (clk_zero_cnt > CLK_ZERO_CNT_MAX)
clk_zero_cnt = CLK_ZERO_CNT_MAX;
if (trail_cnt > TRAIL_CNT_MAX)
if (trail_cnt > TRAIL_CNT_MAX) {
DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
trail_cnt = TRAIL_CNT_MAX;
}
/* B080 */
intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
......
此差异已折叠。
......@@ -121,7 +121,8 @@ int intel_guc_ads_create(struct intel_guc *guc)
* to find it. Note that we have to skip our header (1 page),
* because our GuC shared data is there.
*/
kernel_ctx_vma = dev_priv->kernel_context->engine[RCS].state;
kernel_ctx_vma = to_intel_context(dev_priv->kernel_context,
dev_priv->engine[RCS])->state;
blob->ads.golden_context_lrca =
intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset;
......
......@@ -23,9 +23,6 @@
#ifndef _INTEL_GUC_FWIF_H
#define _INTEL_GUC_FWIF_H
#define GUC_CORE_FAMILY_GEN9 12
#define GUC_CORE_FAMILY_UNKNOWN 0x7fffffff
#define GUC_CLIENT_PRIORITY_KMD_HIGH 0
#define GUC_CLIENT_PRIORITY_HIGH 1
#define GUC_CLIENT_PRIORITY_KMD_NORMAL 2
......@@ -82,8 +79,6 @@
#define GUC_CTL_ARAT_LOW 2
#define GUC_CTL_DEVICE_INFO 3
#define GUC_CTL_GT_TYPE_SHIFT 0
#define GUC_CTL_CORE_FAMILY_SHIFT 7
#define GUC_CTL_LOG_PARAMS 4
#define GUC_LOG_VALID (1 << 0)
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册