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: Daniel Vetter <daniel.vetter@ffwll.ch> From: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/878r78xrxd.fsf@intel.com
This commit is contained in:
commit
0b336ec076
@ -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)
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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(>->uc))
|
||||||
|
ret = intel_guc_global_policies_update(>->uc.guc);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|||||||
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,
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user