Commit 0b336ec0 authored by Daniel Vetter's avatar Daniel Vetter

Merge tag 'drm-intel-next-fixes-2023-11-08' of...

Merge tag 'drm-intel-next-fixes-2023-11-08' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

drm/i915 fixes for v6.7-rc1:
- Fix null dereference when perf interface is not available
- Fix a -Wstringop-overflow warning
- Fix a -Wformat-truncation warning in intel_tc_port_init
- Flush WC GGTT only on required platforms
- Fix MTL HBR3 rate support on C10 phy and eDP
- Fix MTL notify_guc for multi-GT
- Bump GLK CDCLK frequency when driving multiple pipes
- Fix potential spectre vulnerability
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/878r78xrxd.fsf@intel.com
parents 9ccde17d 9506fba4
...@@ -2750,6 +2750,18 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) ...@@ -2750,6 +2750,18 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
for_each_pipe(dev_priv, pipe) for_each_pipe(dev_priv, pipe)
min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk); min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
/*
* Avoid glk_force_audio_cdclk() causing excessive screen
* blinking when multiple pipes are active by making sure
* CDCLK frequency is always high enough for audio. With a
* single active pipe we can always change CDCLK frequency
* by changing the cd2x divider (see glk_cdclk_table[]) and
* thus a full modeset won't be needed then.
*/
if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes &&
!is_power_of_2(cdclk_state->active_pipes))
min_cdclk = max(2 * 96000, min_cdclk);
if (min_cdclk > dev_priv->display.cdclk.max_cdclk_freq) { if (min_cdclk > dev_priv->display.cdclk.max_cdclk_freq) {
drm_dbg_kms(&dev_priv->drm, drm_dbg_kms(&dev_priv->drm,
"required cdclk (%d kHz) exceeds max (%d kHz)\n", "required cdclk (%d kHz) exceeds max (%d kHz)\n",
......
...@@ -430,7 +430,7 @@ static int mtl_max_source_rate(struct intel_dp *intel_dp) ...@@ -430,7 +430,7 @@ static int mtl_max_source_rate(struct intel_dp *intel_dp)
enum phy phy = intel_port_to_phy(i915, dig_port->base.port); enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
if (intel_is_c10phy(i915, phy)) if (intel_is_c10phy(i915, phy))
return intel_dp_is_edp(intel_dp) ? 675000 : 810000; return 810000;
return 2000000; return 2000000;
} }
......
...@@ -58,7 +58,7 @@ struct intel_tc_port { ...@@ -58,7 +58,7 @@ struct intel_tc_port {
struct delayed_work link_reset_work; struct delayed_work link_reset_work;
int link_refcount; int link_refcount;
bool legacy_port:1; bool legacy_port:1;
char port_name[8]; const char *port_name;
enum tc_port_mode mode; enum tc_port_mode mode;
enum tc_port_mode init_mode; enum tc_port_mode init_mode;
enum phy_fia phy_fia; enum phy_fia phy_fia;
...@@ -1875,8 +1875,12 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) ...@@ -1875,8 +1875,12 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
else else
tc->phy_ops = &icl_tc_phy_ops; tc->phy_ops = &icl_tc_phy_ops;
snprintf(tc->port_name, sizeof(tc->port_name), tc->port_name = kasprintf(GFP_KERNEL, "%c/TC#%d", port_name(port),
"%c/TC#%d", port_name(port), tc_port + 1); tc_port + 1);
if (!tc->port_name) {
kfree(tc);
return -ENOMEM;
}
mutex_init(&tc->lock); mutex_init(&tc->lock);
/* TODO: Combine the two works */ /* TODO: Combine the two works */
...@@ -1897,6 +1901,7 @@ void intel_tc_port_cleanup(struct intel_digital_port *dig_port) ...@@ -1897,6 +1901,7 @@ void intel_tc_port_cleanup(struct intel_digital_port *dig_port)
{ {
intel_tc_port_suspend(dig_port); intel_tc_port_suspend(dig_port);
kfree(dig_port->tc->port_name);
kfree(dig_port->tc); kfree(dig_port->tc);
dig_port->tc = NULL; dig_port->tc = NULL;
} }
...@@ -844,6 +844,7 @@ static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv, ...@@ -844,6 +844,7 @@ static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
if (idx >= pc->num_user_engines) if (idx >= pc->num_user_engines)
return -EINVAL; return -EINVAL;
idx = array_index_nospec(idx, pc->num_user_engines);
pe = &pc->user_engines[idx]; pe = &pc->user_engines[idx];
/* Only render engine supports RPCS configuration. */ /* Only render engine supports RPCS configuration. */
......
...@@ -195,6 +195,21 @@ void gen6_ggtt_invalidate(struct i915_ggtt *ggtt) ...@@ -195,6 +195,21 @@ void gen6_ggtt_invalidate(struct i915_ggtt *ggtt)
spin_unlock_irq(&uncore->lock); spin_unlock_irq(&uncore->lock);
} }
static bool needs_wc_ggtt_mapping(struct drm_i915_private *i915)
{
/*
* On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range
* will be dropped. For WC mappings in general we have 64 byte burst
* writes when the WC buffer is flushed, so we can't use it, but have to
* resort to an uncached mapping. The WC issue is easily caught by the
* readback check when writing GTT PTE entries.
*/
if (!IS_GEN9_LP(i915) && GRAPHICS_VER(i915) < 11)
return true;
return false;
}
static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt) static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt)
{ {
struct intel_uncore *uncore = ggtt->vm.gt->uncore; struct intel_uncore *uncore = ggtt->vm.gt->uncore;
...@@ -202,8 +217,12 @@ static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt) ...@@ -202,8 +217,12 @@ static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt)
/* /*
* Note that as an uncached mmio write, this will 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. * WCB of the writes into the GGTT before it triggers the invalidate.
*
* Only perform this when GGTT is mapped as WC, see ggtt_probe_common().
*/ */
intel_uncore_write_fw(uncore, GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); if (needs_wc_ggtt_mapping(ggtt->vm.i915))
intel_uncore_write_fw(uncore, GFX_FLSH_CNTL_GEN6,
GFX_FLSH_CNTL_EN);
} }
static void guc_ggtt_ct_invalidate(struct intel_gt *gt) static void guc_ggtt_ct_invalidate(struct intel_gt *gt)
...@@ -1140,17 +1159,11 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) ...@@ -1140,17 +1159,11 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
GEM_WARN_ON(pci_resource_len(pdev, GEN4_GTTMMADR_BAR) != gen6_gttmmadr_size(i915)); GEM_WARN_ON(pci_resource_len(pdev, GEN4_GTTMMADR_BAR) != gen6_gttmmadr_size(i915));
phys_addr = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) + gen6_gttadr_offset(i915); phys_addr = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) + gen6_gttadr_offset(i915);
/* if (needs_wc_ggtt_mapping(i915))
* On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range
* will be dropped. For WC mappings in general we have 64 byte burst
* writes when the WC buffer is flushed, so we can't use it, but have to
* resort to an uncached mapping. The WC issue is easily caught by the
* readback check when writing GTT PTE entries.
*/
if (IS_GEN9_LP(i915) || GRAPHICS_VER(i915) >= 11)
ggtt->gsm = ioremap(phys_addr, size);
else
ggtt->gsm = ioremap_wc(phys_addr, size); ggtt->gsm = ioremap_wc(phys_addr, size);
else
ggtt->gsm = ioremap(phys_addr, size);
if (!ggtt->gsm) { if (!ggtt->gsm) {
drm_err(&i915->drm, "Failed to map the ggtt page table\n"); drm_err(&i915->drm, "Failed to map the ggtt page table\n");
return -ENOMEM; return -ENOMEM;
......
...@@ -581,19 +581,23 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6) ...@@ -581,19 +581,23 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
static void rc6_res_reg_init(struct intel_rc6 *rc6) static void rc6_res_reg_init(struct intel_rc6 *rc6)
{ {
memset(rc6->res_reg, INVALID_MMIO_REG.reg, sizeof(rc6->res_reg)); i915_reg_t res_reg[INTEL_RC6_RES_MAX] = {
[0 ... INTEL_RC6_RES_MAX - 1] = INVALID_MMIO_REG,
};
switch (rc6_to_gt(rc6)->type) { switch (rc6_to_gt(rc6)->type) {
case GT_MEDIA: case GT_MEDIA:
rc6->res_reg[INTEL_RC6_RES_RC6] = MTL_MEDIA_MC6; res_reg[INTEL_RC6_RES_RC6] = MTL_MEDIA_MC6;
break; break;
default: default:
rc6->res_reg[INTEL_RC6_RES_RC6_LOCKED] = GEN6_GT_GFX_RC6_LOCKED; res_reg[INTEL_RC6_RES_RC6_LOCKED] = GEN6_GT_GFX_RC6_LOCKED;
rc6->res_reg[INTEL_RC6_RES_RC6] = GEN6_GT_GFX_RC6; res_reg[INTEL_RC6_RES_RC6] = GEN6_GT_GFX_RC6;
rc6->res_reg[INTEL_RC6_RES_RC6p] = GEN6_GT_GFX_RC6p; res_reg[INTEL_RC6_RES_RC6p] = GEN6_GT_GFX_RC6p;
rc6->res_reg[INTEL_RC6_RES_RC6pp] = GEN6_GT_GFX_RC6pp; res_reg[INTEL_RC6_RES_RC6pp] = GEN6_GT_GFX_RC6pp;
break; break;
} }
memcpy(rc6->res_reg, res_reg, sizeof(res_reg));
} }
void intel_rc6_init(struct intel_rc6 *rc6) void intel_rc6_init(struct intel_rc6 *rc6)
......
...@@ -38,10 +38,13 @@ static int i915_param_int_open(struct inode *inode, struct file *file) ...@@ -38,10 +38,13 @@ static int i915_param_int_open(struct inode *inode, struct file *file)
static int notify_guc(struct drm_i915_private *i915) static int notify_guc(struct drm_i915_private *i915)
{ {
int ret = 0; struct intel_gt *gt;
int i, ret = 0;
if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) for_each_gt(gt, i915, i) {
ret = intel_guc_global_policies_update(&to_gt(i915)->uc.guc); if (intel_uc_uses_guc_submission(&gt->uc))
ret = intel_guc_global_policies_update(&gt->uc.guc);
}
return ret; return ret;
} }
......
...@@ -4227,11 +4227,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, ...@@ -4227,11 +4227,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
u32 known_open_flags; u32 known_open_flags;
int ret; int ret;
if (!perf->i915) { if (!perf->i915)
drm_dbg(&perf->i915->drm,
"i915 perf interface not available for this system\n");
return -ENOTSUPP; return -ENOTSUPP;
}
known_open_flags = I915_PERF_FLAG_FD_CLOEXEC | known_open_flags = I915_PERF_FLAG_FD_CLOEXEC |
I915_PERF_FLAG_FD_NONBLOCK | I915_PERF_FLAG_FD_NONBLOCK |
...@@ -4607,11 +4604,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, ...@@ -4607,11 +4604,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
struct i915_oa_reg *regs; struct i915_oa_reg *regs;
int err, id; int err, id;
if (!perf->i915) { if (!perf->i915)
drm_dbg(&perf->i915->drm,
"i915 perf interface not available for this system\n");
return -ENOTSUPP; return -ENOTSUPP;
}
if (!perf->metrics_kobj) { if (!perf->metrics_kobj) {
drm_dbg(&perf->i915->drm, drm_dbg(&perf->i915->drm,
...@@ -4773,11 +4767,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data, ...@@ -4773,11 +4767,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
struct i915_oa_config *oa_config; struct i915_oa_config *oa_config;
int ret; int ret;
if (!perf->i915) { if (!perf->i915)
drm_dbg(&perf->i915->drm,
"i915 perf interface not available for this system\n");
return -ENOTSUPP; return -ENOTSUPP;
}
if (i915_perf_stream_paranoid && !perfmon_capable()) { if (i915_perf_stream_paranoid && !perfmon_capable()) {
drm_dbg(&perf->i915->drm, drm_dbg(&perf->i915->drm,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment