diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
164 files changed, 3355 insertions, 1672 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 01b5a8272a27..ce397a8797f7 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -17,7 +17,7 @@ config DRM_I915 select DRM_KMS_HELPER select DRM_PANEL select DRM_MIPI_DSI - select FB_IO_HELPERS if DRM_FBDEV_EMULATION + select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION select RELAY select I2C select I2C_ALGOBIT diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index dcbda9ba32dd..79f65eff6bb2 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -132,6 +132,7 @@ gt-y += \ gt/intel_sseu.o \ gt/intel_sseu_debugfs.o \ gt/intel_timeline.o \ + gt/intel_tlb.o \ gt/intel_wopcm.o \ gt/intel_workarounds.o \ gt/shmem_utils.o \ @@ -197,7 +198,8 @@ i915-y += \ gt/uc/intel_gsc_fw.o \ gt/uc/intel_gsc_proxy.o \ gt/uc/intel_gsc_uc.o \ - gt/uc/intel_gsc_uc_heci_cmd_submit.o\ + gt/uc/intel_gsc_uc_debugfs.o \ + gt/uc/intel_gsc_uc_heci_cmd_submit.o \ gt/uc/intel_guc.o \ gt/uc/intel_guc_ads.o \ gt/uc/intel_guc_capture.o \ diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 112d91d81fdc..4c7187f7913e 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -1259,6 +1259,9 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, struct drm_encoder *encoder; struct intel_connector *intel_connector; + if (!assert_port_valid(dev_priv, port)) + return false; + devdata = intel_bios_encoder_data_lookup(dev_priv, port); /* FIXME bail? */ @@ -1270,6 +1273,8 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, if (!dig_port) return false; + dig_port->aux_ch = AUX_CH_NONE; + intel_connector = intel_connector_alloc(); if (!intel_connector) goto err_connector_alloc; @@ -1373,6 +1378,9 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv, intel_infoframe_init(dig_port); dig_port->aux_ch = intel_dp_aux_ch(intel_encoder); + if (dig_port->aux_ch == AUX_CH_NONE) + goto err_init_connector; + if (!intel_dp_init_connector(dig_port, intel_connector)) goto err_init_connector; diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 5c187e6e0472..634b14116d9d 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -659,6 +659,20 @@ int g4x_hdmi_connector_atomic_check(struct drm_connector *connector, return ret; } +static bool is_hdmi_port_valid(struct drm_i915_private *i915, enum port port) +{ + if (IS_G4X(i915) || IS_VALLEYVIEW(i915)) + return port == PORT_B || port == PORT_C; + else + return port == PORT_B || port == PORT_C || port == PORT_D; +} + +static bool assert_hdmi_port_valid(struct drm_i915_private *i915, enum port port) +{ + return !drm_WARN(&i915->drm, !is_hdmi_port_valid(i915, port), + "Platform does not support HDMI %c\n", port_name(port)); +} + void g4x_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, enum port port) { @@ -667,6 +681,12 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; + if (!assert_port_valid(dev_priv, port)) + return; + + if (!assert_hdmi_port_valid(dev_priv, port)) + return; + devdata = intel_bios_encoder_data_lookup(dev_priv, port); /* FIXME bail? */ @@ -678,6 +698,8 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, if (!dig_port) return; + dig_port->aux_ch = AUX_CH_NONE; + intel_connector = intel_connector_alloc(); if (!intel_connector) { kfree(dig_port); @@ -753,6 +775,5 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, intel_infoframe_init(dig_port); - dig_port->aux_ch = intel_dp_aux_ch(intel_encoder); intel_hdmi_init_connector(dig_port, intel_connector); } diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index c133928a0655..ad6488e9c2b2 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -444,7 +444,8 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder) intel_de_write(dev_priv, ICL_PORT_TX_DW2_GRP(phy), tmp); /* For EHL, TGL, set latency optimization for PCS_DW1 lanes */ - if (IS_JSL_EHL(dev_priv) || (DISPLAY_VER(dev_priv) >= 12)) { + if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv) || + (DISPLAY_VER(dev_priv) >= 12)) { intel_de_rmw(dev_priv, ICL_PORT_PCS_DW1_AUX(phy), LATENCY_OPTIM_MASK, LATENCY_OPTIM_VAL(0)); @@ -528,31 +529,16 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder, enum port port; enum phy phy; - /* Program T-INIT master registers */ - for_each_dsi_port(port, intel_dsi->ports) - intel_de_rmw(dev_priv, ICL_DSI_T_INIT_MASTER(port), - DSI_T_INIT_MASTER_MASK, intel_dsi->init_count); - /* Program DPHY clock lanes timings */ - for_each_dsi_port(port, intel_dsi->ports) { + for_each_dsi_port(port, intel_dsi->ports) intel_de_write(dev_priv, DPHY_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg); - /* shadow register inside display core */ - intel_de_write(dev_priv, DSI_CLK_TIMING_PARAM(port), - intel_dsi->dphy_reg); - } - /* Program DPHY data lanes timings */ - for_each_dsi_port(port, intel_dsi->ports) { + for_each_dsi_port(port, intel_dsi->ports) intel_de_write(dev_priv, DPHY_DATA_TIMING_PARAM(port), intel_dsi->dphy_data_lane_reg); - /* shadow register inside display core */ - intel_de_write(dev_priv, DSI_DATA_TIMING_PARAM(port), - intel_dsi->dphy_data_lane_reg); - } - /* * If DSI link operating at or below an 800 MHz, * TA_SURE should be override and programmed to @@ -561,26 +547,55 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder, */ if (DISPLAY_VER(dev_priv) == 11) { if (afe_clk(encoder, crtc_state) <= 800000) { - for_each_dsi_port(port, intel_dsi->ports) { + for_each_dsi_port(port, intel_dsi->ports) intel_de_rmw(dev_priv, DPHY_TA_TIMING_PARAM(port), TA_SURE_MASK, TA_SURE_OVERRIDE | TA_SURE(0)); - - /* shadow register inside display core */ - intel_de_rmw(dev_priv, DSI_TA_TIMING_PARAM(port), - TA_SURE_MASK, - TA_SURE_OVERRIDE | TA_SURE(0)); - } } } - if (IS_JSL_EHL(dev_priv)) { + if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { for_each_dsi_phy(phy, intel_dsi->phys) intel_de_rmw(dev_priv, ICL_DPHY_CHKN(phy), 0, ICL_DPHY_CHKN_AFE_OVER_PPI_STRAP); } } +static void +gen11_dsi_setup_timings(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); + enum port port; + + /* Program T-INIT master registers */ + for_each_dsi_port(port, intel_dsi->ports) + intel_de_rmw(dev_priv, ICL_DSI_T_INIT_MASTER(port), + DSI_T_INIT_MASTER_MASK, intel_dsi->init_count); + + /* shadow register inside display core */ + for_each_dsi_port(port, intel_dsi->ports) + intel_de_write(dev_priv, DSI_CLK_TIMING_PARAM(port), + intel_dsi->dphy_reg); + + /* shadow register inside display core */ + for_each_dsi_port(port, intel_dsi->ports) + intel_de_write(dev_priv, DSI_DATA_TIMING_PARAM(port), + intel_dsi->dphy_data_lane_reg); + + /* shadow register inside display core */ + if (DISPLAY_VER(dev_priv) == 11) { + if (afe_clk(encoder, crtc_state) <= 800000) { + for_each_dsi_port(port, intel_dsi->ports) { + intel_de_rmw(dev_priv, DSI_TA_TIMING_PARAM(port), + TA_SURE_MASK, + TA_SURE_OVERRIDE | TA_SURE(0)); + } + } + } +} + static void gen11_dsi_gate_clocks(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -1090,11 +1105,15 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, /* step 4c: configure voltage swing and skew */ gen11_dsi_voltage_swing_program_seq(encoder); + /* setup D-PHY timings */ + gen11_dsi_setup_dphy_timings(encoder, crtc_state); + /* enable DDI buffer */ gen11_dsi_enable_ddi_buffer(encoder); - /* setup D-PHY timings */ - gen11_dsi_setup_dphy_timings(encoder, crtc_state); + gen11_dsi_gate_clocks(encoder); + + gen11_dsi_setup_timings(encoder, crtc_state); /* Since transcoder is configured to take events from GPIO */ gen11_dsi_config_util_pin(encoder, true); @@ -1104,9 +1123,6 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, /* Step (4h, 4i, 4j, 4k): Configure transcoder */ gen11_dsi_configure_transcoder(encoder, crtc_state); - - /* Step 4l: Gate DDI clocks */ - gen11_dsi_gate_clocks(encoder); } static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) @@ -1138,12 +1154,7 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) "error setting max return pkt size%d\n", tmp); } - /* panel power on related mipi dsi vbt sequences */ - intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON); - msleep(intel_dsi->panel_on_delay); - intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP); - intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); /* ensure all panel commands dispatched before enabling transcoder */ wait_for_cmds_dispatched_to_panel(encoder); @@ -1154,6 +1165,14 @@ static void gen11_dsi_pre_pll_enable(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); + + intel_dsi_wait_panel_power_cycle(intel_dsi); + + intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON); + msleep(intel_dsi->panel_on_delay); + intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET); + /* step2: enable IO power */ gen11_dsi_enable_io_power(encoder); @@ -1225,9 +1244,7 @@ static void gen11_dsi_enable(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc); - - drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); /* Wa_1409054076:icl,jsl,ehl */ icl_apply_kvmr_pipe_a_wa(encoder, crtc->pipe, true); @@ -1238,6 +1255,8 @@ static void gen11_dsi_enable(struct intel_atomic_state *state, /* step6d: enable dsi transcoder */ gen11_dsi_enable_transcoder(encoder); + intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); + /* step7: enable backlight */ intel_backlight_enable(crtc_state, conn_state); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_ON); @@ -1271,8 +1290,6 @@ static void gen11_dsi_powerdown_panel(struct intel_encoder *encoder) struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_OFF); - intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_ASSERT_RESET); - intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_OFF); /* ensure cmds dispatched to panel */ wait_for_cmds_dispatched_to_panel(encoder); @@ -1373,11 +1390,21 @@ static void gen11_dsi_disable(struct intel_atomic_state *state, const struct drm_connector_state *old_conn_state) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - struct intel_crtc *crtc = to_intel_crtc(old_conn_state->crtc); /* step1: turn off backlight */ intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_OFF); intel_backlight_disable(old_conn_state); +} + +static void gen11_dsi_post_disable(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + + intel_crtc_vblank_off(old_crtc_state); /* step2d,e: disable transcoder and wait */ gen11_dsi_disable_transcoder(encoder); @@ -1391,6 +1418,9 @@ static void gen11_dsi_disable(struct intel_atomic_state *state, /* step2h,i,j: deconfig trancoder */ gen11_dsi_deconfigure_trancoder(encoder); + intel_dsc_disable(old_crtc_state); + skl_scaler_disable(old_crtc_state); + /* step3: disable port */ gen11_dsi_disable_port(encoder); @@ -1398,18 +1428,13 @@ static void gen11_dsi_disable(struct intel_atomic_state *state, /* step4: disable IO power */ gen11_dsi_disable_io_power(encoder); -} -static void gen11_dsi_post_disable(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) -{ - intel_crtc_vblank_off(old_crtc_state); + intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_ASSERT_RESET); - intel_dsc_disable(old_crtc_state); + msleep(intel_dsi->panel_off_delay); + intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_OFF); - skl_scaler_disable(old_crtc_state); + intel_dsi->panel_power_off_time = ktime_get_boottime(); } static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector, @@ -1909,7 +1934,8 @@ static void icl_dsi_add_properties(struct intel_connector *connector) fixed_mode->vdisplay); } -void icl_dsi_init(struct drm_i915_private *dev_priv) +void icl_dsi_init(struct drm_i915_private *dev_priv, + const struct intel_bios_encoder_data *devdata) { struct intel_dsi *intel_dsi; struct intel_encoder *encoder; @@ -1917,7 +1943,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) struct drm_connector *connector; enum port port; - if (!intel_bios_is_dsi_present(dev_priv, &port)) + port = intel_bios_encoder_port(devdata); + if (port == PORT_NONE) return; intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL); @@ -1934,6 +1961,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) intel_dsi->attached_connector = intel_connector; connector = &intel_connector->base; + encoder->devdata = devdata; + /* register DSI encoder with DRM subsystem */ drm_encoder_init(&dev_priv->drm, &encoder->base, &gen11_dsi_encoder_funcs, DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port)); @@ -1957,6 +1986,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) encoder->get_power_domains = gen11_dsi_get_power_domains; encoder->disable_clock = gen11_dsi_gate_clocks; encoder->is_clock_enabled = gen11_dsi_is_clock_enabled; + encoder->shutdown = intel_dsi_shutdown; /* register DSI connector with DRM subsystem */ drm_connector_init(&dev_priv->drm, connector, &gen11_dsi_connector_funcs, @@ -1968,7 +1998,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) /* attach connector to encoder */ intel_connector_attach_encoder(intel_connector, encoder); - encoder->devdata = intel_bios_encoder_data_lookup(dev_priv, port); + intel_dsi->panel_power_off_time = ktime_get_boottime(); + intel_bios_init_panel_late(dev_priv, &intel_connector->panel, encoder->devdata, NULL); mutex_lock(&dev_priv->drm.mode_config.mutex); diff --git a/drivers/gpu/drm/i915/display/icl_dsi.h b/drivers/gpu/drm/i915/display/icl_dsi.h index b4861b56b5b2..43fa7d72eeb1 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.h +++ b/drivers/gpu/drm/i915/display/icl_dsi.h @@ -7,9 +7,11 @@ #define __ICL_DSI_H__ struct drm_i915_private; +struct intel_bios_encoder_data; struct intel_crtc_state; -void icl_dsi_init(struct drm_i915_private *i915); +void icl_dsi_init(struct drm_i915_private *dev_priv, + const struct intel_bios_encoder_data *devdata); void icl_dsi_frame_update(struct intel_crtc_state *crtc_state); #endif /* __ICL_DSI_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 7d9578ebae55..60a492e186ab 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -212,6 +212,7 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; int width, height; + unsigned int rel_data_rate; if (plane->id == PLANE_CURSOR) return 0; @@ -241,7 +242,11 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, height /= 2; } - return width * height * fb->format->cpp[color_plane]; + rel_data_rate = width * height * fb->format->cpp[color_plane]; + + return intel_adjusted_rate(&plane_state->uapi.src, + &plane_state->uapi.dst, + rel_data_rate); } int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 34a397adbd6b..858c959f7bab 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2230,122 +2230,6 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) return 0; } -static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin) -{ - enum port port; - - if (!ddc_pin) - return PORT_NONE; - - for_each_port(port) { - const struct intel_bios_encoder_data *devdata = - i915->display.vbt.ports[port]; - - if (devdata && ddc_pin == devdata->child.ddc_pin) - return port; - } - - return PORT_NONE; -} - -static void sanitize_ddc_pin(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child; - u8 mapped_ddc_pin; - enum port p; - - if (!devdata->child.ddc_pin) - return; - - mapped_ddc_pin = map_ddc_pin(i915, devdata->child.ddc_pin); - if (!intel_gmbus_is_valid_pin(i915, mapped_ddc_pin)) { - drm_dbg_kms(&i915->drm, - "Port %c has invalid DDC pin %d, " - "sticking to defaults\n", - port_name(port), mapped_ddc_pin); - devdata->child.ddc_pin = 0; - return; - } - - p = get_port_by_ddc_pin(i915, devdata->child.ddc_pin); - if (p == PORT_NONE) - return; - - drm_dbg_kms(&i915->drm, - "port %c trying to use the same DDC pin (0x%x) as port %c, " - "disabling port %c DVI/HDMI support\n", - port_name(port), mapped_ddc_pin, - port_name(p), port_name(p)); - - /* - * If we have multiple ports supposedly sharing the pin, then dvi/hdmi - * couldn't exist on the shared port. Otherwise they share the same ddc - * pin and system couldn't communicate with them separately. - * - * Give inverse child device order the priority, last one wins. Yes, - * there are real machines (eg. Asrock B250M-HDV) where VBT has both - * port A and port E with the same AUX ch and we must pick port E :( - */ - child = &i915->display.vbt.ports[p]->child; - - child->device_type &= ~DEVICE_TYPE_TMDS_DVI_SIGNALING; - child->device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT; - - child->ddc_pin = 0; -} - -static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch) -{ - enum port port; - - if (!aux_ch) - return PORT_NONE; - - for_each_port(port) { - const struct intel_bios_encoder_data *devdata = - i915->display.vbt.ports[port]; - - if (devdata && aux_ch == devdata->child.aux_channel) - return port; - } - - return PORT_NONE; -} - -static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child; - enum port p; - - p = get_port_by_aux_ch(i915, devdata->child.aux_channel); - if (p == PORT_NONE) - return; - - drm_dbg_kms(&i915->drm, - "port %c trying to use the same AUX CH (0x%x) as port %c, " - "disabling port %c DP support\n", - port_name(port), devdata->child.aux_channel, - port_name(p), port_name(p)); - - /* - * If we have multiple ports supposedly sharing the aux channel, then DP - * couldn't exist on the shared port. Otherwise they share the same aux - * channel and system couldn't communicate with them separately. - * - * Give inverse child device order the priority, last one wins. Yes, - * there are real machines (eg. Asrock B250M-HDV) where VBT has both - * port A and port E with the same AUX ch and we must pick port E :( - */ - child = &i915->display.vbt.ports[p]->child; - - child->device_type &= ~DEVICE_TYPE_DISPLAYPORT_OUTPUT; - child->aux_channel = 0; -} - static u8 dvo_port_type(u8 dvo_port) { switch (dvo_port) { @@ -2490,6 +2374,19 @@ dsi_dvo_port_to_port(struct drm_i915_private *i915, u8 dvo_port) } } +enum port intel_bios_encoder_port(const struct intel_bios_encoder_data *devdata) +{ + struct drm_i915_private *i915 = devdata->i915; + const struct child_device_config *child = &devdata->child; + enum port port; + + port = dvo_port_to_port(i915, child->dvo_port); + if (port == PORT_NONE && DISPLAY_VER(i915) >= 11) + port = dsi_dvo_port_to_port(i915, child->dvo_port); + + return port; +} + static int parse_bdb_230_dp_max_link_rate(const int vbt_max_link_rate) { switch (vbt_max_link_rate) { @@ -2600,7 +2497,7 @@ intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata) devdata->child.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR; } -static bool +bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata) { return devdata->child.device_type & DEVICE_TYPE_MIPI_OUTPUT; @@ -2615,7 +2512,8 @@ intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata) /* This is an index in the HDMI/DVI DDI buffer translation table, or -1 */ int intel_bios_hdmi_level_shift(const struct intel_bios_encoder_data *devdata) { - if (!devdata || devdata->i915->display.vbt.version < 158) + if (!devdata || devdata->i915->display.vbt.version < 158 || + DISPLAY_VER(devdata->i915) >= 14) return -1; return devdata->child.hdmi_level_shifter_value; @@ -2658,13 +2556,17 @@ static bool is_port_valid(struct drm_i915_private *i915, enum port port) return true; } -static void print_ddi_port(const struct intel_bios_encoder_data *devdata, - enum port port) +static void print_ddi_port(const struct intel_bios_encoder_data *devdata) { struct drm_i915_private *i915 = devdata->i915; const struct child_device_config *child = &devdata->child; bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt; int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock; + enum port port; + + port = intel_bios_encoder_port(devdata); + if (port == PORT_NONE) + return; is_dvi = intel_bios_encoder_supports_dvi(devdata); is_dp = intel_bios_encoder_supports_dp(devdata); @@ -2728,12 +2630,9 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata, static void parse_ddi_port(struct intel_bios_encoder_data *devdata) { struct drm_i915_private *i915 = devdata->i915; - const struct child_device_config *child = &devdata->child; enum port port; - port = dvo_port_to_port(i915, child->dvo_port); - if (port == PORT_NONE && DISPLAY_VER(i915) >= 11) - port = dsi_dvo_port_to_port(i915, child->dvo_port); + port = intel_bios_encoder_port(devdata); if (port == PORT_NONE) return; @@ -2744,22 +2643,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata) return; } - if (i915->display.vbt.ports[port]) { - drm_dbg_kms(&i915->drm, - "More than one child device for port %c in VBT, using the first.\n", - port_name(port)); - return; - } - sanitize_device_type(devdata, port); - - if (intel_bios_encoder_supports_dvi(devdata)) - sanitize_ddc_pin(devdata, port); - - if (intel_bios_encoder_supports_dp(devdata)) - sanitize_aux_ch(devdata, port); - - i915->display.vbt.ports[port] = devdata; } static bool has_ddi_port_info(struct drm_i915_private *i915) @@ -2770,7 +2654,6 @@ static bool has_ddi_port_info(struct drm_i915_private *i915) static void parse_ddi_ports(struct drm_i915_private *i915) { struct intel_bios_encoder_data *devdata; - enum port port; if (!has_ddi_port_info(i915)) return; @@ -2778,10 +2661,8 @@ static void parse_ddi_ports(struct drm_i915_private *i915) list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) parse_ddi_port(devdata); - for_each_port(port) { - if (i915->display.vbt.ports[port]) - print_ddi_port(i915->display.vbt.ports[port], port); - } + list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) + print_ddi_port(devdata); } static void @@ -3706,5 +3587,22 @@ bool intel_bios_encoder_hpd_invert(const struct intel_bios_encoder_data *devdata const struct intel_bios_encoder_data * intel_bios_encoder_data_lookup(struct drm_i915_private *i915, enum port port) { - return i915->display.vbt.ports[port]; + struct intel_bios_encoder_data *devdata; + + list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) { + if (intel_bios_encoder_port(devdata) == port) + return devdata; + } + + return NULL; +} + +void intel_bios_for_each_encoder(struct drm_i915_private *i915, + void (*func)(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata)) +{ + struct intel_bios_encoder_data *devdata; + + list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) + func(i915, devdata); } diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 45fae97d9719..9680e3e92bb5 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -263,10 +263,12 @@ bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdat bool intel_bios_encoder_supports_edp(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devdata); +bool intel_bios_encoder_supports_dsi(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_is_lspcon(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_lane_reversal(const struct intel_bios_encoder_data *devdata); bool intel_bios_encoder_hpd_invert(const struct intel_bios_encoder_data *devdata); +enum port intel_bios_encoder_port(const struct intel_bios_encoder_data *devdata); enum aux_ch intel_bios_dp_aux_ch(const struct intel_bios_encoder_data *devdata); int intel_bios_dp_boost_level(const struct intel_bios_encoder_data *devdata); int intel_bios_dp_max_lane_count(const struct intel_bios_encoder_data *devdata); @@ -276,4 +278,8 @@ int intel_bios_hdmi_ddc_pin(const struct intel_bios_encoder_data *devdata); int intel_bios_hdmi_level_shift(const struct intel_bios_encoder_data *devdata); int intel_bios_hdmi_max_tmds_clock(const struct intel_bios_encoder_data *devdata); +void intel_bios_for_each_encoder(struct drm_i915_private *i915, + void (*func)(struct drm_i915_private *i915, + const struct intel_bios_encoder_data *devdata)); + #endif /* _INTEL_BIOS_H_ */ diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 4207863b7b2a..2fb030b1ff1d 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -37,6 +37,7 @@ #include "intel_pci_config.h" #include "intel_pcode.h" #include "intel_psr.h" +#include "intel_vdsc.h" #include "vlv_sideband.h" /** @@ -469,7 +470,7 @@ static void hsw_get_cdclk(struct drm_i915_private *dev_priv, cdclk_config->cdclk = 450000; else if (freq == LCPLL_CLK_FREQ_450) cdclk_config->cdclk = 450000; - else if (IS_HSW_ULT(dev_priv)) + else if (IS_HASWELL_ULT(dev_priv)) cdclk_config->cdclk = 337500; else cdclk_config->cdclk = 540000; @@ -2607,9 +2608,16 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) * When we decide to use only one VDSC engine, since * each VDSC operates with 1 ppc throughput, pixel clock * cannot be higher than the VDSC clock (cdclk) + * If there 2 VDSC engines, then pixel clock can't be higher than + * VDSC clock(cdclk) * 2 and so on. */ - if (crtc_state->dsc.compression_enable && !crtc_state->dsc.dsc_split) - min_cdclk = max(min_cdclk, (int)crtc_state->pixel_rate); + if (crtc_state->dsc.compression_enable) { + int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state); + + min_cdclk = max_t(int, min_cdclk, + DIV_ROUND_UP(crtc_state->pixel_rate, + num_vdsc_instances)); + } /* * HACK. Currently for TGL/DG2 platforms we calculate @@ -3147,7 +3155,7 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) */ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) { - if (IS_JSL_EHL(dev_priv)) { + if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { if (dev_priv->display.cdclk.hw.ref == 24000) dev_priv->display.cdclk.max_cdclk_freq = 552000; else @@ -3192,9 +3200,9 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) */ if (intel_de_read(dev_priv, FUSE_STRAP) & HSW_CDCLK_LIMIT) dev_priv->display.cdclk.max_cdclk_freq = 450000; - else if (IS_BDW_ULX(dev_priv)) + else if (IS_BROADWELL_ULX(dev_priv)) dev_priv->display.cdclk.max_cdclk_freq = 450000; - else if (IS_BDW_ULT(dev_priv)) + else if (IS_BROADWELL_ULT(dev_priv)) dev_priv->display.cdclk.max_cdclk_freq = 540000; else dev_priv->display.cdclk.max_cdclk_freq = 675000; @@ -3559,10 +3567,10 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) dev_priv->display.cdclk.table = dg2_cdclk_table; } else if (IS_ALDERLAKE_P(dev_priv)) { /* Wa_22011320316:adl-p[a0] */ - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { + if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { dev_priv->display.cdclk.table = adlp_a_step_cdclk_table; dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; - } else if (IS_ADLP_RPLU(dev_priv)) { + } else if (IS_RAPTORLAKE_U(dev_priv)) { dev_priv->display.cdclk.table = rplu_cdclk_table; dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs; } else { @@ -3575,7 +3583,7 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) } else if (DISPLAY_VER(dev_priv) >= 12) { dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; dev_priv->display.cdclk.table = icl_cdclk_table; - } else if (IS_JSL_EHL(dev_priv)) { + } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { dev_priv->display.funcs.cdclk = &ehl_cdclk_funcs; dev_priv->display.cdclk.table = icl_cdclk_table; } else if (DISPLAY_VER(dev_priv) >= 11) { diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 8966e6560516..454607b4a02a 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1453,6 +1453,16 @@ static int glk_degamma_lut_size(struct drm_i915_private *i915) return 35; } +/* + * change_lut_val_precision: helper function to upscale or downscale lut values. + * Parameters 'to' and 'from' needs to be less than 32. This should be sufficient + * as currently there are no lut values exceeding 32 bit. + */ +static u32 change_lut_val_precision(u32 lut_val, int to, int from) +{ + return mul_u32_u32(lut_val, (1 << to)) / (1 << from); +} + static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { @@ -1487,8 +1497,15 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ + u32 lut_val; + + if (DISPLAY_VER(i915) >= 14) + lut_val = change_lut_val_precision(lut[i].green, 24, 16); + else + lut_val = lut[i].green; + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + lut_val); } /* Clamp values > 1.0. */ @@ -3439,6 +3456,14 @@ static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc) for (i = 0; i < lut_size; i++) { u32 val = intel_de_read_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe)); + /* + * For MTL and beyond, convert back the 24 bit lut values + * read from HW to 16 bit values to maintain parity with + * userspace values + */ + if (DISPLAY_VER(dev_priv) >= 14) + val = change_lut_val_precision(val, 16, 24); + lut[i].red = val; lut[i].green = val; lut[i].blue = val; diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 922a6d87b553..e2a220cf2e57 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -141,7 +141,7 @@ static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy) if (IS_ALDERLAKE_S(i915)) return phy == PHY_A; - else if (IS_JSL_EHL(i915) || + else if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) || IS_ROCKETLAKE(i915) || IS_DG1(i915)) return phy < PHY_C; @@ -242,7 +242,7 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy), IREFGEN, IREFGEN); - if (IS_JSL_EHL(dev_priv)) { + if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { if (ehl_vbt_ddi_d_present(dev_priv)) expected_val = ICL_PHY_MISC_MUX_DDID; @@ -333,7 +333,8 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv) * "internal" child devices. */ val = intel_de_read(dev_priv, ICL_PHY_MISC(phy)); - if (IS_JSL_EHL(dev_priv) && phy == PHY_A) { + if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && + phy == PHY_A) { val &= ~ICL_PHY_MISC_MUX_DDID; if (ehl_vbt_ddi_d_present(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index ab7cd5e60a0a..809074758687 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -1064,6 +1064,8 @@ void intel_crt_init(struct drm_i915_private *dev_priv) } if (HAS_DDI(dev_priv)) { + assert_port_valid(dev_priv, PORT_E); + crt->base.port = PORT_E; crt->base.get_config = hsw_crt_get_config; crt->base.get_hw_state = intel_ddi_get_hw_state; diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 719447ce86e7..1b00ef2c6185 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -116,6 +116,7 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port, XELPDP_MSGBUS_TIMEOUT_SLOW, val)) { drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n", phy_name(phy), *val); + intel_cx0_bus_reset(i915, port, lane); return -ETIMEDOUT; } @@ -158,10 +159,8 @@ static int __intel_cx0_read_once(struct drm_i915_private *i915, enum port port, XELPDP_PORT_M2P_ADDRESS(addr)); ack = intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, &val); - if (ack < 0) { - intel_cx0_bus_reset(i915, port, lane); + if (ack < 0) return ack; - } intel_clear_response_ready_flag(i915, port, lane); @@ -202,6 +201,7 @@ static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port, int lane, u16 addr, u8 data, bool committed) { enum phy phy = intel_port_to_phy(i915, port); + int ack; u32 val; if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane), @@ -230,10 +230,9 @@ static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port, } if (committed) { - if (intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val) < 0) { - intel_cx0_bus_reset(i915, port, lane); - return -EINVAL; - } + ack = intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val); + if (ack < 0) + return ack; } else if ((intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)) & XELPDP_PORT_P2M_ERROR_SET)) { drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index f99809af257d..4c4db5cdcbd0 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -43,8 +43,5 @@ int intel_c20pll_calc_port_clock(struct intel_encoder *encoder, void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock); -void intel_cx0_phy_ddi_vswing_sequence(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - u32 level); int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); #endif /* __INTEL_CX0_PHY_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 090f242e610c..84bbf854337a 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -32,6 +32,7 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "icl_dsi.h" #include "intel_audio.h" #include "intel_audio_regs.h" #include "intel_backlight.h" @@ -3582,7 +3583,8 @@ void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, { if (DISPLAY_VER(dev_priv) >= 12 && crtc_state->port_clock > 594000) crtc_state->min_voltage_level = 2; - else if (IS_JSL_EHL(dev_priv) && crtc_state->port_clock > 594000) + else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && + crtc_state->port_clock > 594000) crtc_state->min_voltage_level = 3; else if (DISPLAY_VER(dev_priv) >= 11 && crtc_state->port_clock > 594000) crtc_state->min_voltage_level = 1; @@ -4653,13 +4655,95 @@ static void intel_ddi_tc_encoder_shutdown_complete(struct intel_encoder *encoder #define port_tc_name(port) ((port) - PORT_TC1 + '1') #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1') -void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) +static bool port_strap_detected(struct drm_i915_private *i915, enum port port) +{ + /* straps not used on skl+ */ + if (DISPLAY_VER(i915) >= 9) + return true; + + switch (port) { + case PORT_A: + return intel_de_read(i915, DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; + case PORT_B: + return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDIB_DETECTED; + case PORT_C: + return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDIC_DETECTED; + case PORT_D: + return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDID_DETECTED; + case PORT_E: + return true; /* no strap for DDI-E */ + default: + MISSING_CASE(port); + return false; + } +} + +static bool need_aux_ch(struct intel_encoder *encoder, bool init_dp) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum phy phy = intel_port_to_phy(i915, encoder->port); + + return init_dp || intel_phy_is_tc(i915, phy); +} + +static bool assert_has_icl_dsi(struct drm_i915_private *i915) +{ + return !drm_WARN(&i915->drm, !IS_ALDERLAKE_P(i915) && + !IS_TIGERLAKE(i915) && DISPLAY_VER(i915) != 11, + "Platform does not support DSI\n"); +} + +static bool port_in_use(struct drm_i915_private *i915, enum port port) +{ + struct intel_encoder *encoder; + + for_each_intel_encoder(&i915->drm, encoder) { + /* FIXME what about second port for dual link DSI? */ + if (encoder->port == port) + return true; + } + + return false; +} + +void intel_ddi_init(struct drm_i915_private *dev_priv, + const struct intel_bios_encoder_data *devdata) { struct intel_digital_port *dig_port; struct intel_encoder *encoder; - const struct intel_bios_encoder_data *devdata; bool init_hdmi, init_dp; - enum phy phy = intel_port_to_phy(dev_priv, port); + enum port port; + enum phy phy; + + port = intel_bios_encoder_port(devdata); + if (port == PORT_NONE) + return; + + if (!port_strap_detected(dev_priv, port)) { + drm_dbg_kms(&dev_priv->drm, + "Port %c strap not detected\n", port_name(port)); + return; + } + + if (!assert_port_valid(dev_priv, port)) + return; + + if (port_in_use(dev_priv, port)) { + drm_dbg_kms(&dev_priv->drm, + "Port %c already claimed\n", port_name(port)); + return; + } + + if (intel_bios_encoder_supports_dsi(devdata)) { + /* BXT/GLK handled elsewhere, for now at least */ + if (!assert_has_icl_dsi(dev_priv)) + return; + + icl_dsi_init(dev_priv, devdata); + return; + } + + phy = intel_port_to_phy(dev_priv, port); /* * On platforms with HTI (aka HDPORT), if it's enabled at boot it may @@ -4673,14 +4757,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) return; } - devdata = intel_bios_encoder_data_lookup(dev_priv, port); - if (!devdata) { - drm_dbg_kms(&dev_priv->drm, - "VBT says port %c is not present\n", - port_name(port)); - return; - } - init_hdmi = intel_bios_encoder_supports_dvi(devdata) || intel_bios_encoder_supports_hdmi(devdata); init_dp = intel_bios_encoder_supports_dp(devdata); @@ -4715,6 +4791,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) if (!dig_port) return; + dig_port->aux_ch = AUX_CH_NONE; + encoder = &dig_port->base; encoder->devdata = devdata; @@ -4801,7 +4879,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->disable_clock = dg1_ddi_disable_clock; encoder->is_clock_enabled = dg1_ddi_is_clock_enabled; encoder->get_config = dg1_ddi_get_config; - } else if (IS_JSL_EHL(dev_priv)) { + } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { if (intel_ddi_is_tc(dev_priv, port)) { encoder->enable_clock = jsl_ddi_tc_enable_clock; encoder->disable_clock = jsl_ddi_tc_disable_clock; @@ -4872,7 +4950,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->hpd_pin = rkl_hpd_pin(dev_priv, port); else if (DISPLAY_VER(dev_priv) >= 12) encoder->hpd_pin = tgl_hpd_pin(dev_priv, port); - else if (IS_JSL_EHL(dev_priv)) + else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) encoder->hpd_pin = ehl_hpd_pin(dev_priv, port); else if (DISPLAY_VER(dev_priv) == 11) encoder->hpd_pin = icl_hpd_pin(dev_priv, port); @@ -4895,7 +4973,12 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) dig_port->dp.output_reg = INVALID_MMIO_REG; dig_port->max_lanes = intel_ddi_max_lanes(dig_port); - dig_port->aux_ch = intel_dp_aux_ch(encoder); + + if (need_aux_ch(encoder, init_dp)) { + dig_port->aux_ch = intel_dp_aux_ch(encoder); + if (dig_port->aux_ch == AUX_CH_NONE) + goto err; + } if (intel_phy_is_tc(dev_priv, phy)) { bool is_legacy = diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 2bc034042a93..4999c0ee229b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -11,6 +11,7 @@ struct drm_connector_state; struct drm_i915_private; struct intel_atomic_state; +struct intel_bios_encoder_data; struct intel_connector; struct intel_crtc; struct intel_crtc_state; @@ -50,7 +51,8 @@ void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, enum port port); -void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); +void intel_ddi_init(struct drm_i915_private *dev_priv, + const struct intel_bios_encoder_data *devdata); bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index b7d20485bde5..de809e2d9cac 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1049,12 +1049,26 @@ static const union intel_ddi_buf_trans_entry _mtl_c10_trans_dp14[] = { { .snps = { 62, 0, 0 } }, /* preset 9 */ }; -static const struct intel_ddi_buf_trans mtl_cx0_trans = { +static const struct intel_ddi_buf_trans mtl_c10_trans_dp14 = { .entries = _mtl_c10_trans_dp14, .num_entries = ARRAY_SIZE(_mtl_c10_trans_dp14), .hdmi_default_entry = ARRAY_SIZE(_mtl_c10_trans_dp14) - 1, }; +/* DP1.4 */ +static const union intel_ddi_buf_trans_entry _mtl_c20_trans_dp14[] = { + { .snps = { 20, 0, 0 } }, /* preset 0 */ + { .snps = { 24, 0, 4 } }, /* preset 1 */ + { .snps = { 30, 0, 9 } }, /* preset 2 */ + { .snps = { 34, 0, 14 } }, /* preset 3 */ + { .snps = { 29, 0, 0 } }, /* preset 4 */ + { .snps = { 34, 0, 5 } }, /* preset 5 */ + { .snps = { 38, 0, 10 } }, /* preset 6 */ + { .snps = { 36, 0, 0 } }, /* preset 7 */ + { .snps = { 40, 0, 6 } }, /* preset 8 */ + { .snps = { 48, 0, 0 } }, /* preset 9 */ +}; + /* DP2.0 */ static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = { { .snps = { 48, 0, 0 } }, /* preset 0 */ @@ -1072,7 +1086,7 @@ static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = { { .snps = { 37, 4, 7 } }, /* preset 12 */ { .snps = { 33, 4, 11 } }, /* preset 13 */ { .snps = { 40, 8, 0 } }, /* preset 14 */ - { .snps = { 28, 2, 2 } }, /* preset 15 */ + { .snps = { 30, 2, 2 } }, /* preset 15 */ }; /* HDMI2.0 */ @@ -1090,6 +1104,12 @@ static const struct intel_ddi_buf_trans mtl_c20_trans_hdmi = { .hdmi_default_entry = 0, }; +static const struct intel_ddi_buf_trans mtl_c20_trans_dp14 = { + .entries = _mtl_c20_trans_dp14, + .num_entries = ARRAY_SIZE(_mtl_c20_trans_dp14), + .hdmi_default_entry = ARRAY_SIZE(_mtl_c20_trans_dp14) - 1, +}; + static const struct intel_ddi_buf_trans mtl_c20_trans_uhbr = { .entries = _mtl_c20_trans_uhbr, .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr), @@ -1390,7 +1410,7 @@ tgl_get_combo_buf_trans_dp(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); if (crtc_state->port_clock > 270000) { - if (IS_TGL_UY(dev_priv)) { + if (IS_TIGERLAKE_UY(dev_priv)) { return intel_get_buf_trans(&tgl_uy_combo_phy_trans_dp_hbr2, n_entries); } else { @@ -1678,8 +1698,10 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder, return intel_get_buf_trans(&mtl_c20_trans_uhbr, n_entries); else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !(intel_is_c10phy(i915, phy))) return intel_get_buf_trans(&mtl_c20_trans_hdmi, n_entries); + else if (!intel_is_c10phy(i915, phy)) + return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries); else - return intel_get_buf_trans(&mtl_cx0_trans, n_entries); + return intel_get_buf_trans(&mtl_c10_trans_dp14, n_entries); } void intel_ddi_buf_trans_init(struct intel_encoder *encoder) @@ -1718,15 +1740,15 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) encoder->get_buf_trans = icl_get_mg_buf_trans; } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) { encoder->get_buf_trans = bxt_get_buf_trans; - } else if (IS_CML_ULX(i915) || IS_CFL_ULX(i915) || IS_KBL_ULX(i915)) { + } else if (IS_COMETLAKE_ULX(i915) || IS_COFFEELAKE_ULX(i915) || IS_KABYLAKE_ULX(i915)) { encoder->get_buf_trans = kbl_y_get_buf_trans; - } else if (IS_CML_ULT(i915) || IS_CFL_ULT(i915) || IS_KBL_ULT(i915)) { + } else if (IS_COMETLAKE_ULT(i915) || IS_COFFEELAKE_ULT(i915) || IS_KABYLAKE_ULT(i915)) { encoder->get_buf_trans = kbl_u_get_buf_trans; } else if (IS_COMETLAKE(i915) || IS_COFFEELAKE(i915) || IS_KABYLAKE(i915)) { encoder->get_buf_trans = kbl_get_buf_trans; - } else if (IS_SKL_ULX(i915)) { + } else if (IS_SKYLAKE_ULX(i915)) { encoder->get_buf_trans = skl_y_get_buf_trans; - } else if (IS_SKL_ULT(i915)) { + } else if (IS_SKYLAKE_ULT(i915)) { encoder->get_buf_trans = skl_u_get_buf_trans; } else if (IS_SKYLAKE(i915)) { encoder->get_buf_trans = skl_get_buf_trans; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 16603d591f56..763ab569d8f3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -53,7 +53,6 @@ #include "i915_utils.h" #include "i9xx_plane.h" #include "i9xx_wm.h" -#include "icl_dsi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_audio.h" @@ -1750,7 +1749,7 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) return phy <= PHY_E; else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) return phy <= PHY_D; - else if (IS_JSL_EHL(dev_priv)) + else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) return phy <= PHY_C; else if (IS_ALDERLAKE_P(dev_priv) || IS_DISPLAY_VER(dev_priv, 11, 12)) return phy <= PHY_B; @@ -1802,7 +1801,8 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port) return PHY_B + port - PORT_TC1; else if ((IS_DG1(i915) || IS_ROCKETLAKE(i915)) && port >= PORT_TC1) return PHY_C + port - PORT_TC1; - else if (IS_JSL_EHL(i915) && port == PORT_D) + else if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) && + port == PORT_D) return PHY_A; return PHY_A + port - PORT_A; @@ -3153,6 +3153,10 @@ static void bdw_set_pipe_misc(const struct intel_crtc_state *crtc_state) if (DISPLAY_VER(dev_priv) >= 12) val |= PIPE_MISC_PIXEL_ROUNDING_TRUNC; + /* allow PSR with sprite enabled */ + if (IS_BROADWELL(dev_priv)) + val |= PIPE_MISC_PSR_MASK_SPRITE_ENABLE; + intel_de_write(dev_priv, PIPE_MISC(crtc->pipe), val); } @@ -7143,7 +7147,11 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) */ intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore); } - intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, wakeref); + /* + * Delay re-enabling DC states by 17 ms to avoid the off->on->off + * toggling overhead at and above 60 FPS. + */ + intel_display_power_put_async_delay(dev_priv, POWER_DOMAIN_DC_OFF, wakeref, 17); intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref); /* @@ -7370,7 +7378,7 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv) if (DISPLAY_VER(dev_priv) >= 9) return false; - if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) + if (IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv)) return false; if (HAS_PCH_LPT_H(dev_priv) && @@ -7387,6 +7395,12 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv) return true; } +bool assert_port_valid(struct drm_i915_private *i915, enum port port) +{ + return !drm_WARN(&i915->drm, !(DISPLAY_RUNTIME_INFO(i915)->port_mask & BIT(port)), + "Platform does not support port %c\n", port_name(port)); +} + void intel_setup_outputs(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder; @@ -7397,93 +7411,14 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - if (IS_METEORLAKE(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_TC1); - intel_ddi_init(dev_priv, PORT_TC2); - intel_ddi_init(dev_priv, PORT_TC3); - intel_ddi_init(dev_priv, PORT_TC4); - } else if (IS_DG2(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_C); - intel_ddi_init(dev_priv, PORT_D_XELPD); - intel_ddi_init(dev_priv, PORT_TC1); - } else if (IS_ALDERLAKE_P(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_TC1); - intel_ddi_init(dev_priv, PORT_TC2); - intel_ddi_init(dev_priv, PORT_TC3); - intel_ddi_init(dev_priv, PORT_TC4); - icl_dsi_init(dev_priv); - } else if (IS_ALDERLAKE_S(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_TC1); - intel_ddi_init(dev_priv, PORT_TC2); - intel_ddi_init(dev_priv, PORT_TC3); - intel_ddi_init(dev_priv, PORT_TC4); - } else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_TC1); - intel_ddi_init(dev_priv, PORT_TC2); - } else if (DISPLAY_VER(dev_priv) >= 12) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_TC1); - intel_ddi_init(dev_priv, PORT_TC2); - intel_ddi_init(dev_priv, PORT_TC3); - intel_ddi_init(dev_priv, PORT_TC4); - intel_ddi_init(dev_priv, PORT_TC5); - intel_ddi_init(dev_priv, PORT_TC6); - icl_dsi_init(dev_priv); - } else if (IS_JSL_EHL(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_C); - intel_ddi_init(dev_priv, PORT_D); - icl_dsi_init(dev_priv); - } else if (DISPLAY_VER(dev_priv) == 11) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_C); - intel_ddi_init(dev_priv, PORT_D); - intel_ddi_init(dev_priv, PORT_E); - intel_ddi_init(dev_priv, PORT_F); - icl_dsi_init(dev_priv); - } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_C); - vlv_dsi_init(dev_priv); - } else if (DISPLAY_VER(dev_priv) >= 9) { - intel_ddi_init(dev_priv, PORT_A); - intel_ddi_init(dev_priv, PORT_B); - intel_ddi_init(dev_priv, PORT_C); - intel_ddi_init(dev_priv, PORT_D); - intel_ddi_init(dev_priv, PORT_E); - } else if (HAS_DDI(dev_priv)) { - u32 found; - + if (HAS_DDI(dev_priv)) { if (intel_ddi_crt_present(dev_priv)) intel_crt_init(dev_priv); - /* Haswell uses DDI functions to detect digital outputs. */ - found = intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; - if (found) - intel_ddi_init(dev_priv, PORT_A); - - found = intel_de_read(dev_priv, SFUSE_STRAP); - if (found & SFUSE_STRAP_DDIB_DETECTED) - intel_ddi_init(dev_priv, PORT_B); - if (found & SFUSE_STRAP_DDIC_DETECTED) - intel_ddi_init(dev_priv, PORT_C); - if (found & SFUSE_STRAP_DDID_DETECTED) - intel_ddi_init(dev_priv, PORT_D); - if (found & SFUSE_STRAP_DDIF_DETECTED) - intel_ddi_init(dev_priv, PORT_F); + intel_bios_for_each_encoder(dev_priv, intel_ddi_init); + + if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) + vlv_dsi_init(dev_priv); } else if (HAS_PCH_SPLIT(dev_priv)) { int found; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index c744c021af23..49ac8473b988 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -113,7 +113,7 @@ enum i9xx_plane_id { #define for_each_dbuf_slice(__dev_priv, __slice) \ for ((__slice) = DBUF_S1; (__slice) < I915_MAX_DBUF_SLICES; (__slice)++) \ - for_each_if(INTEL_INFO(__dev_priv)->display->dbuf.slice_mask & BIT(__slice)) + for_each_if(DISPLAY_INFO(__dev_priv)->dbuf.slice_mask & BIT(__slice)) #define for_each_dbuf_slice_in_mask(__dev_priv, __slice, __mask) \ for_each_dbuf_slice((__dev_priv), (__slice)) \ @@ -539,6 +539,8 @@ void assert_transcoder(struct drm_i915_private *dev_priv, #define assert_transcoder_enabled(d, t) assert_transcoder(d, t, true) #define assert_transcoder_disabled(d, t) assert_transcoder(d, t, false) +bool assert_port_valid(struct drm_i915_private *i915, enum port port); + /* * Use I915_STATE_WARN(x) (rather than WARN() and WARN_ON()) for hw state sanity * checks to check for unexpected conditions which may not necessarily be a user diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 8d2243c71dd8..53e5c33e08c3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -17,6 +17,7 @@ #include <drm/drm_modeset_lock.h> #include "intel_cdclk.h" +#include "intel_display_device.h" #include "intel_display_limits.h" #include "intel_display_power.h" #include "intel_dpll_mgr.h" @@ -33,7 +34,6 @@ struct i915_audio_component; struct i915_hdcp_arbiter; struct intel_atomic_state; struct intel_audio_funcs; -struct intel_bios_encoder_data; struct intel_cdclk_funcs; struct intel_cdclk_vals; struct intel_color_funcs; @@ -218,7 +218,6 @@ struct intel_vbt_data { struct list_head display_devices; struct list_head bdb_blocks; - struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */ struct sdvo_device_mapping { u8 initialized; u8 dvo_port; @@ -430,6 +429,14 @@ struct intel_display { } hti; struct { + /* Access with DISPLAY_INFO() */ + const struct intel_display_device_info *__device_info; + + /* Access with DISPLAY_RUNTIME_INFO() */ + struct intel_display_runtime_info __runtime_info; + } info; + + struct { bool false_color; } ips; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 165e2c7e3126..63c1fb9e479f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -819,8 +819,7 @@ static ssize_t i915_displayport_test_active_write(struct file *file, if (IS_ERR(input_buffer)) return PTR_ERR(input_buffer); - drm_dbg(&to_i915(dev)->drm, - "Copied %d bytes from user\n", (unsigned int)len); + drm_dbg(dev, "Copied %d bytes from user\n", (unsigned int)len); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { @@ -839,8 +838,7 @@ static ssize_t i915_displayport_test_active_write(struct file *file, status = kstrtoint(input_buffer, 10, &val); if (status < 0) break; - drm_dbg(&to_i915(dev)->drm, - "Got %d for test active\n", val); + drm_dbg(dev, "Got %d for test active\n", val); /* To prevent erroneous activation of the compliance * testing code, only accept an actual value of 1 here */ diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index f0ee9bcf661d..c39f8a15d8aa 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -184,10 +184,6 @@ static const struct intel_display_device_info no_display = {}; .__runtime_defaults.cpu_transcoder_mask = \ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) -static const struct intel_display_device_info i830_display = { - I830_DISPLAY, -}; - #define I845_DISPLAY \ .has_overlay = 1, \ .overlay_needs_physical = 1, \ @@ -200,19 +196,29 @@ static const struct intel_display_device_info i830_display = { .__runtime_defaults.pipe_mask = BIT(PIPE_A), \ .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) +static const struct intel_display_device_info i830_display = { + I830_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C), /* DVO A/B/C */ +}; + static const struct intel_display_device_info i845_display = { I845_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ }; static const struct intel_display_device_info i85x_display = { I830_DISPLAY, + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; static const struct intel_display_device_info i865g_display = { I845_DISPLAY, + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* DVO B/C */ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -225,7 +231,8 @@ static const struct intel_display_device_info i865g_display = { .__runtime_defaults.ip.ver = 3, \ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ .__runtime_defaults.cpu_transcoder_mask = \ - BIT(TRANSCODER_A) | BIT(TRANSCODER_B) + BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) /* SDVO B/C */ static const struct intel_display_device_info i915g_display = { GEN3_DISPLAY, @@ -290,6 +297,8 @@ static const struct intel_display_device_info pnv_display = { static const struct intel_display_device_info i965g_display = { GEN4_DISPLAY, .has_overlay = 1, + + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* SDVO B/C */ }; static const struct intel_display_device_info i965gm_display = { @@ -297,17 +306,21 @@ static const struct intel_display_device_info i965gm_display = { .has_overlay = 1, .supports_tv = 1, + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* SDVO B/C */ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; static const struct intel_display_device_info g45_display = { GEN4_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* SDVO/HDMI/DP B/C, DP D */ }; static const struct intel_display_device_info gm45_display = { GEN4_DISPLAY, .supports_tv = 1, + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* SDVO/HDMI/DP B/C, DP D */ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -320,7 +333,8 @@ static const struct intel_display_device_info gm45_display = { .__runtime_defaults.ip.ver = 5, \ .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), \ .__runtime_defaults.cpu_transcoder_mask = \ - BIT(TRANSCODER_A) | BIT(TRANSCODER_B) + BIT(TRANSCODER_A) | BIT(TRANSCODER_B), \ + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ static const struct intel_display_device_info ilk_d_display = { ILK_DISPLAY, @@ -342,6 +356,7 @@ static const struct intel_display_device_info snb_display = { .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -355,6 +370,7 @@ static const struct intel_display_device_info ivb_display = { .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -370,6 +386,7 @@ static const struct intel_display_device_info vlv_display = { .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B), .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B), + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C), /* HDMI/DP B/C */ }; static const struct intel_display_device_info hsw_display = { @@ -377,6 +394,8 @@ static const struct intel_display_device_info hsw_display = { .has_dp_mst = 1, .has_fpga_dbg = 1, .has_hotplug = 1, + .has_psr = 1, + .has_psr_hw_tracking = 1, HSW_PIPE_OFFSETS, IVB_CURSOR_OFFSETS, IVB_COLORS, @@ -386,6 +405,7 @@ static const struct intel_display_device_info hsw_display = { .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -394,6 +414,8 @@ static const struct intel_display_device_info bdw_display = { .has_dp_mst = 1, .has_fpga_dbg = 1, .has_hotplug = 1, + .has_psr = 1, + .has_psr_hw_tracking = 1, HSW_PIPE_OFFSETS, IVB_CURSOR_OFFSETS, IVB_COLORS, @@ -403,6 +425,7 @@ static const struct intel_display_device_info bdw_display = { .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -418,6 +441,7 @@ static const struct intel_display_device_info chv_display = { .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), + .__runtime_defaults.port_mask = BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* HDMI/DP B/C/D */ }; static const struct intel_display_device_info skl_display = { @@ -441,6 +465,7 @@ static const struct intel_display_device_info skl_display = { .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), }; @@ -464,7 +489,8 @@ static const struct intel_display_device_info skl_display = { .__runtime_defaults.cpu_transcoder_mask = \ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \ - BIT(TRANSCODER_DSI_A) | BIT(TRANSCODER_DSI_C) + BIT(TRANSCODER_DSI_A) | BIT(TRANSCODER_DSI_C), \ + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) static const struct intel_display_device_info bxt_display = { GEN9_LP_DISPLAY, @@ -481,46 +507,57 @@ static const struct intel_display_device_info glk_display = { .__runtime_defaults.ip.ver = 10, }; -static const struct intel_display_device_info gen11_display = { - .abox_mask = BIT(0), - .dbuf.size = 2048, - .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), - .has_ddi = 1, - .has_dp_mst = 1, - .has_fpga_dbg = 1, - .has_hotplug = 1, - .has_ipc = 1, - .has_psr = 1, - .has_psr_hw_tracking = 1, - .pipe_offsets = { - [TRANSCODER_A] = PIPE_A_OFFSET, - [TRANSCODER_B] = PIPE_B_OFFSET, - [TRANSCODER_C] = PIPE_C_OFFSET, - [TRANSCODER_EDP] = PIPE_EDP_OFFSET, - [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, - [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, - }, - .trans_offsets = { - [TRANSCODER_A] = TRANSCODER_A_OFFSET, - [TRANSCODER_B] = TRANSCODER_B_OFFSET, - [TRANSCODER_C] = TRANSCODER_C_OFFSET, - [TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, - [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, - [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, - }, - IVB_CURSOR_OFFSETS, - ICL_COLORS, +#define ICL_DISPLAY \ + .abox_mask = BIT(0), \ + .dbuf.size = 2048, \ + .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2), \ + .has_ddi = 1, \ + .has_dp_mst = 1, \ + .has_fpga_dbg = 1, \ + .has_hotplug = 1, \ + .has_ipc = 1, \ + .has_psr = 1, \ + .has_psr_hw_tracking = 1, \ + .pipe_offsets = { \ + [TRANSCODER_A] = PIPE_A_OFFSET, \ + [TRANSCODER_B] = PIPE_B_OFFSET, \ + [TRANSCODER_C] = PIPE_C_OFFSET, \ + [TRANSCODER_EDP] = PIPE_EDP_OFFSET, \ + [TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \ + [TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \ + }, \ + .trans_offsets = { \ + [TRANSCODER_A] = TRANSCODER_A_OFFSET, \ + [TRANSCODER_B] = TRANSCODER_B_OFFSET, \ + [TRANSCODER_C] = TRANSCODER_C_OFFSET, \ + [TRANSCODER_EDP] = TRANSCODER_EDP_OFFSET, \ + [TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \ + [TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \ + }, \ + IVB_CURSOR_OFFSETS, \ + ICL_COLORS, \ + \ + .__runtime_defaults.ip.ver = 11, \ + .__runtime_defaults.has_dmc = 1, \ + .__runtime_defaults.has_dsc = 1, \ + .__runtime_defaults.has_hdcp = 1, \ + .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), \ + .__runtime_defaults.cpu_transcoder_mask = \ + BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \ + BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | \ + BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \ + .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) - .__runtime_defaults.ip.ver = 11, - .__runtime_defaults.has_dmc = 1, - .__runtime_defaults.has_dsc = 1, - .__runtime_defaults.has_hdcp = 1, - .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), - .__runtime_defaults.cpu_transcoder_mask = - BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | - BIT(TRANSCODER_C) | BIT(TRANSCODER_EDP) | - BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), - .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A), +static const struct intel_display_device_info icl_display = { + ICL_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D) | BIT(PORT_E), +}; + +static const struct intel_display_device_info jsl_ehl_display = { + ICL_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), }; #define XE_D_DISPLAY \ @@ -568,6 +605,20 @@ static const struct intel_display_device_info gen11_display = { static const struct intel_display_device_info tgl_display = { XE_D_DISPLAY, + + /* + * FIXME DDI C/combo PHY C missing due to combo PHY + * code making a mess on SKUs where the PHY is missing. + */ + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4) | BIT(PORT_TC5) | BIT(PORT_TC6), +}; + +static const struct intel_display_device_info dg1_display = { + XE_D_DISPLAY, + + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + BIT(PORT_TC1) | BIT(PORT_TC2), }; static const struct intel_display_device_info rkl_display = { @@ -579,12 +630,17 @@ static const struct intel_display_device_info rkl_display = { .__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + BIT(PORT_TC1) | BIT(PORT_TC2), }; static const struct intel_display_device_info adl_s_display = { XE_D_DISPLAY, .has_hti = 1, .has_psr_hw_tracking = 0, + + .__runtime_defaults.port_mask = BIT(PORT_A) | + BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), }; #define XE_LPD_FEATURES \ @@ -639,6 +695,8 @@ static const struct intel_display_device_info xe_lpd_display = { BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), }; static const struct intel_display_device_info xe_hpd_display = { @@ -648,6 +706,8 @@ static const struct intel_display_device_info xe_hpd_display = { .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D_XELPD) | + BIT(PORT_TC1), }; static const struct intel_display_device_info xe_lpdp_display = { @@ -660,12 +720,28 @@ static const struct intel_display_device_info xe_lpdp_display = { .__runtime_defaults.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D), + .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | + BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4), }; +/* + * Separate detection for no display cases to keep the display id array simple. + * + * IVB Q requires subvendor and subdevice matching to differentiate from IVB D + * GT2 server. + */ +static bool has_no_display(struct pci_dev *pdev) +{ + static const struct pci_device_id ids[] = { + INTEL_IVB_Q_IDS(0), + {} + }; + + return pci_match_id(ids, pdev); +} + #undef INTEL_VGA_DEVICE -#undef INTEL_QUANTA_VGA_DEVICE #define INTEL_VGA_DEVICE(id, info) { id, info } -#define INTEL_QUANTA_VGA_DEVICE(info) { 0x16a, info } static const struct { u32 devid; @@ -690,7 +766,6 @@ static const struct { INTEL_IRONLAKE_M_IDS(&ilk_m_display), INTEL_SNB_D_IDS(&snb_display), INTEL_SNB_M_IDS(&snb_display), - INTEL_IVB_Q_IDS(NULL), /* must be first IVB in list */ INTEL_IVB_M_IDS(&ivb_display), INTEL_IVB_D_IDS(&ivb_display), INTEL_HSW_IDS(&hsw_display), @@ -702,11 +777,11 @@ static const struct { INTEL_GLK_IDS(&glk_display), INTEL_KBL_IDS(&skl_display), INTEL_CFL_IDS(&skl_display), - INTEL_ICL_11_IDS(&gen11_display), - INTEL_EHL_IDS(&gen11_display), - INTEL_JSL_IDS(&gen11_display), + INTEL_ICL_11_IDS(&icl_display), + INTEL_EHL_IDS(&jsl_ehl_display), + INTEL_JSL_IDS(&jsl_ehl_display), INTEL_TGL_12_IDS(&tgl_display), - INTEL_DG1_IDS(&tgl_display), + INTEL_DG1_IDS(&dg1_display), INTEL_RKL_IDS(&rkl_display), INTEL_ADLS_IDS(&adl_s_display), INTEL_RPLS_IDS(&adl_s_display), @@ -738,6 +813,15 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step u32 val; int i; + /* The caller expects to ver, rel and step to be initialized + * here, and there's no good way to check when there was a + * failure and no_display was returned. So initialize all these + * values here zero, to be sure. + */ + *ver = 0; + *rel = 0; + *step = 0; + addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32)); if (!addr) { drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n"); @@ -747,9 +831,10 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step val = ioread32(addr); pci_iounmap(pdev, addr); - if (val == 0) - /* Platform doesn't have display */ + if (val == 0) { + drm_dbg_kms(&i915->drm, "Device doesn't have display\n"); return &no_display; + } *ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val); *rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); @@ -775,6 +860,11 @@ intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid, if (has_gmdid) return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step); + if (has_no_display(pdev)) { + drm_dbg_kms(&i915->drm, "Device doesn't have display\n"); + return &no_display; + } + for (i = 0; i < ARRAY_SIZE(intel_display_ids); i++) { if (intel_display_ids[i].devid == pdev->device) return intel_display_ids[i].info; @@ -791,8 +881,12 @@ void intel_display_device_info_runtime_init(struct drm_i915_private *i915) struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915); enum pipe pipe; + BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->pipe_mask) < I915_MAX_PIPES); + BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->cpu_transcoder_mask) < I915_MAX_TRANSCODERS); + BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->port_mask) < I915_MAX_PORTS); + /* Wa_14011765242: adl-s A0,A1 */ - if (IS_ADLS_DISPLAY_STEP(i915, STEP_A0, STEP_A2)) + if (IS_ALDERLAKE_S(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_A2)) for_each_pipe(i915, pipe) display_runtime->num_scalers[pipe] = 0; else if (DISPLAY_VER(i915) >= 11) { @@ -910,3 +1004,24 @@ void intel_display_device_info_runtime_init(struct drm_i915_private *i915) display_fused_off: memset(display_runtime, 0, sizeof(*display_runtime)); } + +void intel_display_device_info_print(const struct intel_display_device_info *info, + const struct intel_display_runtime_info *runtime, + struct drm_printer *p) +{ + if (runtime->ip.rel) + drm_printf(p, "display version: %u.%02u\n", + runtime->ip.ver, + runtime->ip.rel); + else + drm_printf(p, "display version: %u\n", + runtime->ip.ver); + +#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->name)) + DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); +#undef PRINT_FLAG + + drm_printf(p, "has_hdcp: %s\n", str_yes_no(runtime->has_hdcp)); + drm_printf(p, "has_dmc: %s\n", str_yes_no(runtime->has_dmc)); + drm_printf(p, "has_dsc: %s\n", str_yes_no(runtime->has_dsc)); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 706ff2aa1f55..215e682bd8b7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -11,6 +11,7 @@ #include "intel_display_limits.h" struct drm_i915_private; +struct drm_printer; #define DEV_INFO_DISPLAY_FOR_EACH_FLAG(func) \ /* Keep in alphabetical order */ \ @@ -53,7 +54,7 @@ struct drm_i915_private; #define HAS_GMCH(i915) (DISPLAY_INFO(i915)->has_gmch) #define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) #define HAS_IPC(i915) (DISPLAY_INFO(i915)->has_ipc) -#define HAS_IPS(i915) (IS_HSW_ULT(i915) || IS_BROADWELL(i915)) +#define HAS_IPS(i915) (IS_HASWELL_ULT(i915) || IS_BROADWELL(i915)) #define HAS_LSPCON(i915) (IS_DISPLAY_VER(i915, 9, 10)) #define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) #define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12) @@ -79,6 +80,7 @@ struct intel_display_runtime_info { u8 pipe_mask; u8 cpu_transcoder_mask; + u16 port_mask; u8 num_sprites[I915_MAX_PIPES]; u8 num_scalers[I915_MAX_PIPES]; @@ -126,4 +128,8 @@ intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid, u16 *ver, u16 *rel, u16 *step); void intel_display_device_info_runtime_init(struct drm_i915_private *i915); +void intel_display_device_info_print(const struct intel_display_device_info *info, + const struct intel_display_runtime_info *runtime, + struct drm_printer *p); + #endif diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index b909814ae02b..8f144d4d3c39 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -28,6 +28,7 @@ #include "intel_crtc.h" #include "intel_display_debugfs.h" #include "intel_display_driver.h" +#include "intel_display_irq.h" #include "intel_display_power.h" #include "intel_display_types.h" #include "intel_dkl_phy.h" @@ -177,6 +178,7 @@ void intel_display_driver_early_probe(struct drm_i915_private *i915) if (!HAS_DISPLAY(i915)) return; + intel_display_irq_init(i915); intel_dkl_phy_init(i915); intel_color_init_hooks(i915); intel_init_cdclk_hooks(i915); diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index ae2578741dfe..62ce55475554 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -749,6 +749,20 @@ void ivb_display_irq_handler(struct drm_i915_private *dev_priv, u32 de_iir) if (de_iir & DE_ERR_INT_IVB) ivb_err_int_handler(dev_priv); + if (de_iir & DE_EDP_PSR_INT_HSW) { + struct intel_encoder *encoder; + + for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + u32 psr_iir; + + psr_iir = intel_uncore_rmw(&dev_priv->uncore, + EDP_PSR_IIR, 0, 0); + intel_psr_irq_handler(intel_dp, psr_iir); + break; + } + } + if (de_iir & DE_AUX_CHANNEL_A_IVB) intel_dp_aux_irq_handler(dev_priv); @@ -1135,7 +1149,7 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl) { - void __iomem * const regs = i915->uncore.regs; + void __iomem * const regs = intel_uncore_regs(&i915->uncore); u32 iir; if (!(master_ctl & GEN11_GU_MISC_IRQ)) @@ -1156,7 +1170,7 @@ void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir) void gen11_display_irq_handler(struct drm_i915_private *i915) { - void __iomem * const regs = i915->uncore.regs; + void __iomem * const regs = intel_uncore_regs(&i915->uncore); const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); disable_rpm_wakeref_asserts(&i915->runtime_pm); @@ -1523,7 +1537,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, * to avoid races with the irq handler, assuming we have MSI. Shared legacy * interrupts could still race. */ -void ibx_irq_postinstall(struct drm_i915_private *dev_priv) +static void ibx_irq_postinstall(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; u32 mask; @@ -1569,6 +1583,50 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) vlv_display_irq_reset(dev_priv); } +void ilk_de_irq_postinstall(struct drm_i915_private *i915) +{ + struct intel_uncore *uncore = &i915->uncore; + u32 display_mask, extra_mask; + + if (GRAPHICS_VER(i915) >= 7) { + display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | + DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); + extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | + DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | + DE_PLANE_FLIP_DONE_IVB(PLANE_C) | + DE_PLANE_FLIP_DONE_IVB(PLANE_B) | + DE_PLANE_FLIP_DONE_IVB(PLANE_A) | + DE_DP_A_HOTPLUG_IVB); + } else { + display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | + DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | + DE_PIPEA_CRC_DONE | DE_POISON); + extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | + DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | + DE_PLANE_FLIP_DONE(PLANE_A) | + DE_PLANE_FLIP_DONE(PLANE_B) | + DE_DP_A_HOTPLUG); + } + + if (IS_HASWELL(i915)) { + gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); + display_mask |= DE_EDP_PSR_INT_HSW; + } + + if (IS_IRONLAKE_M(i915)) + extra_mask |= DE_PCU_EVENT; + + i915->irq_mask = ~display_mask; + + ibx_irq_postinstall(i915); + + GEN3_IRQ_INIT(uncore, DE, i915->irq_mask, + display_mask | extra_mask); +} + +static void mtp_irq_postinstall(struct drm_i915_private *i915); +static void icp_irq_postinstall(struct drm_i915_private *i915); + void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; @@ -1586,6 +1644,13 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; + if (DISPLAY_VER(dev_priv) >= 14) + mtp_irq_postinstall(dev_priv); + else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) + icp_irq_postinstall(dev_priv); + else if (HAS_PCH_SPLIT(dev_priv)) + ibx_irq_postinstall(dev_priv); + if (DISPLAY_VER(dev_priv) <= 10) de_misc_masked |= GEN8_DE_MISC_GSE; @@ -1652,7 +1717,7 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) } } -void mtp_irq_postinstall(struct drm_i915_private *i915) +static void mtp_irq_postinstall(struct drm_i915_private *i915) { struct intel_uncore *uncore = &i915->uncore; u32 sde_mask = SDE_GMBUS_ICP | SDE_PICAINTERRUPT; @@ -1666,7 +1731,7 @@ void mtp_irq_postinstall(struct drm_i915_private *i915) GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff); } -void icp_irq_postinstall(struct drm_i915_private *dev_priv) +static void icp_irq_postinstall(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; u32 mask = SDE_GMBUS_ICP; @@ -1685,3 +1750,30 @@ void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv) GEN11_DISPLAY_IRQ_ENABLE); } +void dg1_de_irq_postinstall(struct drm_i915_private *i915) +{ + if (!HAS_DISPLAY(i915)) + return; + + gen8_de_irq_postinstall(i915); + intel_uncore_write(&i915->uncore, GEN11_DISPLAY_INT_CTL, + GEN11_DISPLAY_IRQ_ENABLE); +} + +void intel_display_irq_init(struct drm_i915_private *i915) +{ + i915->drm.vblank_disable_immediate = true; + + /* + * Most platforms treat the display irq block as an always-on power + * domain. vlv/chv can disable it at runtime and need special care to + * avoid writing any of the display block registers outside of the power + * domain. We defer setting up the display irqs in this case to the + * runtime pm. + */ + i915->display_irqs_enabled = true; + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + i915->display_irqs_enabled = false; + + intel_hotplug_irq_init(i915); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.h b/drivers/gpu/drm/i915/display/intel_display_irq.h index 874893f4f16d..2a090dd6abd7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.h +++ b/drivers/gpu/drm/i915/display/intel_display_irq.h @@ -58,12 +58,11 @@ void vlv_display_irq_reset(struct drm_i915_private *i915); void gen8_display_irq_reset(struct drm_i915_private *i915); void gen11_display_irq_reset(struct drm_i915_private *i915); -void ibx_irq_postinstall(struct drm_i915_private *i915); void vlv_display_irq_postinstall(struct drm_i915_private *i915); -void icp_irq_postinstall(struct drm_i915_private *i915); +void ilk_de_irq_postinstall(struct drm_i915_private *i915); void gen8_de_irq_postinstall(struct drm_i915_private *i915); -void mtp_irq_postinstall(struct drm_i915_private *i915); void gen11_de_irq_postinstall(struct drm_i915_private *i915); +void dg1_de_irq_postinstall(struct drm_i915_private *i915); u32 i915_pipestat_enable_mask(struct drm_i915_private *i915, enum pipe pipe); void i915_enable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask); @@ -78,4 +77,6 @@ void i965_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_ void valleyview_pipestat_irq_handler(struct drm_i915_private *i915, u32 pipe_stats[I915_MAX_PIPES]); void i8xx_pipestat_irq_handler(struct drm_i915_private *i915, u16 iir, u32 pipe_stats[I915_MAX_PIPES]); +void intel_display_irq_init(struct drm_i915_private *i915); + #endif /* __INTEL_DISPLAY_IRQ_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index db5437043904..9e01054c2430 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -10,6 +10,7 @@ #include "i915_reg.h" #include "intel_backlight_regs.h" #include "intel_cdclk.h" +#include "intel_clock_gating.h" #include "intel_combo_phy.h" #include "intel_de.h" #include "intel_display_power.h" @@ -457,6 +458,17 @@ async_put_domains_clear_domain(struct i915_power_domains *power_domains, clear_bit(domain, power_domains->async_put_domains[1].bits); } +static void +cancel_async_put_work(struct i915_power_domains *power_domains, bool sync) +{ + if (sync) + cancel_delayed_work_sync(&power_domains->async_put_work); + else + cancel_delayed_work(&power_domains->async_put_work); + + power_domains->async_put_next_delay = 0; +} + static bool intel_display_power_grab_async_put_ref(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain) @@ -477,7 +489,7 @@ intel_display_power_grab_async_put_ref(struct drm_i915_private *dev_priv, if (!bitmap_empty(async_put_mask.bits, POWER_DOMAIN_NUM)) goto out_verify; - cancel_delayed_work(&power_domains->async_put_work); + cancel_async_put_work(power_domains, false); intel_runtime_pm_put_raw(&dev_priv->runtime_pm, fetch_and_zero(&power_domains->async_put_wakeref)); out_verify: @@ -608,7 +620,8 @@ static void __intel_display_power_put(struct drm_i915_private *dev_priv, static void queue_async_put_domains_work(struct i915_power_domains *power_domains, - intel_wakeref_t wakeref) + intel_wakeref_t wakeref, + int delay_ms) { struct drm_i915_private *i915 = container_of(power_domains, struct drm_i915_private, @@ -617,7 +630,7 @@ queue_async_put_domains_work(struct i915_power_domains *power_domains, power_domains->async_put_wakeref = wakeref; drm_WARN_ON(&i915->drm, !queue_delayed_work(system_unbound_wq, &power_domains->async_put_work, - msecs_to_jiffies(100))); + msecs_to_jiffies(delay_ms))); } static void @@ -680,13 +693,15 @@ intel_display_power_put_async_work(struct work_struct *work) bitmap_zero(power_domains->async_put_domains[1].bits, POWER_DOMAIN_NUM); queue_async_put_domains_work(power_domains, - fetch_and_zero(&new_work_wakeref)); + fetch_and_zero(&new_work_wakeref), + power_domains->async_put_next_delay); + power_domains->async_put_next_delay = 0; } else { /* * Cancel the work that got queued after this one got dequeued, * since here we released the corresponding async-put reference. */ - cancel_delayed_work(&power_domains->async_put_work); + cancel_async_put_work(power_domains, false); } out_verify: @@ -705,19 +720,25 @@ out_verify: * @i915: i915 device instance * @domain: power domain to reference * @wakeref: wakeref acquired for the reference that is being released + * @delay_ms: delay of powering down the power domain * * This function drops the power domain reference obtained by * intel_display_power_get*() and schedules a work to power down the * corresponding hardware block if this is the last reference. + * The power down is delayed by @delay_ms if this is >= 0, or by a default + * 100 ms otherwise. */ void __intel_display_power_put_async(struct drm_i915_private *i915, enum intel_display_power_domain domain, - intel_wakeref_t wakeref) + intel_wakeref_t wakeref, + int delay_ms) { struct i915_power_domains *power_domains = &i915->display.power.domains; struct intel_runtime_pm *rpm = &i915->runtime_pm; intel_wakeref_t work_wakeref = intel_runtime_pm_get_raw(rpm); + delay_ms = delay_ms >= 0 ? delay_ms : 100; + mutex_lock(&power_domains->lock); if (power_domains->domain_use_count[domain] > 1) { @@ -731,10 +752,13 @@ void __intel_display_power_put_async(struct drm_i915_private *i915, /* Let a pending work requeue itself or queue a new one. */ if (power_domains->async_put_wakeref) { set_bit(domain, power_domains->async_put_domains[1].bits); + power_domains->async_put_next_delay = max(power_domains->async_put_next_delay, + delay_ms); } else { set_bit(domain, power_domains->async_put_domains[0].bits); queue_async_put_domains_work(power_domains, - fetch_and_zero(&work_wakeref)); + fetch_and_zero(&work_wakeref), + delay_ms); } out_verify: @@ -774,7 +798,7 @@ void intel_display_power_flush_work(struct drm_i915_private *i915) async_put_domains_mask(power_domains, &async_put_mask); release_async_put_domains(power_domains, &async_put_mask); - cancel_delayed_work(&power_domains->async_put_work); + cancel_async_put_work(power_domains, false); out_verify: verify_async_put_domains_state(power_domains); @@ -798,7 +822,7 @@ intel_display_power_flush_work_sync(struct drm_i915_private *i915) struct i915_power_domains *power_domains = &i915->display.power.domains; intel_display_power_flush_work(i915); - cancel_delayed_work_sync(&power_domains->async_put_work); + cancel_async_put_work(power_domains, true); verify_async_put_domains_state(power_domains); @@ -1385,9 +1409,8 @@ static void hsw_disable_pc8(struct drm_i915_private *dev_priv) hsw_restore_lcpll(dev_priv); intel_init_pch_refclk(dev_priv); - if (HAS_PCH_LPT_LP(dev_priv)) - intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, - 0, PCH_LP_PARTITION_LEVEL_DISABLE); + /* Many display registers don't survive PC8+ */ + intel_clock_gating_init(dev_priv); } static void intel_pch_reset_handshake(struct drm_i915_private *dev_priv, @@ -1586,7 +1609,7 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv) return; if (IS_ALDERLAKE_S(dev_priv) || - IS_RKL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + (IS_ROCKETLAKE(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))) /* Wa_1409767108 */ table = wa_1409767108_buddy_page_masks; else diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index df38632c6237..d3b5d04b7b07 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -12,9 +12,6 @@ #include "intel_wakeref.h" enum aux_ch; -enum dpio_channel; -enum dpio_phy; -enum i915_drm_suspend_mode; enum port; struct drm_i915_private; struct i915_power_well; @@ -154,6 +151,7 @@ struct i915_power_domains { struct delayed_work async_put_work; intel_wakeref_t async_put_wakeref; struct intel_power_domain_mask async_put_domains[2]; + int async_put_next_delay; struct i915_power_well *power_wells; }; @@ -200,7 +198,8 @@ intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); void __intel_display_power_put_async(struct drm_i915_private *i915, enum intel_display_power_domain domain, - intel_wakeref_t wakeref); + intel_wakeref_t wakeref, + int delay_ms); void intel_display_power_flush_work(struct drm_i915_private *i915); #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) void intel_display_power_put(struct drm_i915_private *dev_priv, @@ -211,7 +210,16 @@ intel_display_power_put_async(struct drm_i915_private *i915, enum intel_display_power_domain domain, intel_wakeref_t wakeref) { - __intel_display_power_put_async(i915, domain, wakeref); + __intel_display_power_put_async(i915, domain, wakeref, -1); +} + +static inline void +intel_display_power_put_async_delay(struct drm_i915_private *i915, + enum intel_display_power_domain domain, + intel_wakeref_t wakeref, + int delay_ms) +{ + __intel_display_power_put_async(i915, domain, wakeref, delay_ms); } #else void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv, @@ -230,7 +238,16 @@ intel_display_power_put_async(struct drm_i915_private *i915, enum intel_display_power_domain domain, intel_wakeref_t wakeref) { - __intel_display_power_put_async(i915, domain, -1); + __intel_display_power_put_async(i915, domain, -1, -1); +} + +static inline void +intel_display_power_put_async_delay(struct drm_i915_private *i915, + enum intel_display_power_domain domain, + intel_wakeref_t wakeref, + int delay_ms) +{ + __intel_display_power_put_async(i915, domain, -1, delay_ms); } #endif diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index 1015bba4af01..a8736588314d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -11,7 +11,6 @@ #include "intel_dpio_phy.h" struct drm_i915_private; -struct i915_power_well; struct i915_power_well_ops; struct intel_encoder; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9f40da20e88d..12bd2f322e62 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -500,7 +500,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) max_rate = 810000; - else if (IS_JSL_EHL(dev_priv)) + else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) max_rate = ehl_max_source_rate(intel_dp); else max_rate = icl_max_source_rate(intel_dp); @@ -510,7 +510,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) } else if (DISPLAY_VER(dev_priv) == 9) { source_rates = skl_rates; size = ARRAY_SIZE(skl_rates); - } else if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) || + } else if ((IS_HASWELL(dev_priv) && !IS_HASWELL_ULX(dev_priv)) || IS_BROADWELL(dev_priv)) { source_rates = hsw_rates; size = ARRAY_SIZE(hsw_rates); @@ -713,9 +713,18 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p /* * According to BSpec, 27 is the max DSC output bpp, - * 8 is the min DSC output bpp + * 8 is the min DSC output bpp. + * While we can still clamp higher bpp values to 27, saving bandwidth, + * if it is required to oompress up to bpp < 8, means we can't do + * that and probably means we can't fit the required mode, even with + * DSC enabled. */ - bits_per_pixel = clamp_t(u32, bits_per_pixel, 8, 27); + if (bits_per_pixel < 8) { + drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min 8\n", + bits_per_pixel); + return 0; + } + bits_per_pixel = min_t(u32, bits_per_pixel, 27); } else { /* Find the nearest match in the array of known BPPs from VESA */ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 197c6e81db14..2d173bd495a3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -14,7 +14,7 @@ #include "intel_pps.h" #include "intel_tc.h" -static u32 intel_dp_aux_pack(const u8 *src, int src_bytes) +u32 intel_dp_aux_pack(const u8 *src, int src_bytes) { int i; u32 v = 0; @@ -792,25 +792,60 @@ static enum aux_ch default_aux_ch(struct intel_encoder *encoder) return (enum aux_ch)encoder->port; } +static struct intel_encoder * +get_encoder_by_aux_ch(struct intel_encoder *encoder, + enum aux_ch aux_ch) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_encoder *other; + + for_each_intel_encoder(&i915->drm, other) { + if (other == encoder) + continue; + + if (!intel_encoder_is_dig_port(other)) + continue; + + if (enc_to_dig_port(other)->aux_ch == aux_ch) + return other; + } + + return NULL; +} + enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_encoder *other; + const char *source; enum aux_ch aux_ch; aux_ch = intel_bios_dp_aux_ch(encoder->devdata); - if (aux_ch != AUX_CH_NONE) { - drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] using AUX %c (VBT)\n", - encoder->base.base.id, encoder->base.name, - aux_ch_name(aux_ch)); - return aux_ch; + source = "VBT"; + + if (aux_ch == AUX_CH_NONE) { + aux_ch = default_aux_ch(encoder); + source = "platform default"; } - aux_ch = default_aux_ch(encoder); + if (aux_ch == AUX_CH_NONE) + return AUX_CH_NONE; + + /* FIXME validate aux_ch against platform caps */ + + other = get_encoder_by_aux_ch(encoder, aux_ch); + if (other) { + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] AUX CH %c already claimed by [ENCODER:%d:%s]\n", + encoder->base.base.id, encoder->base.name, aux_ch_name(aux_ch), + other->base.base.id, other->base.name); + return AUX_CH_NONE; + } drm_dbg_kms(&i915->drm, - "[ENCODER:%d:%s] using AUX %c (platform default)\n", + "[ENCODER:%d:%s] Using AUX CH %c (%s)\n", encoder->base.base.id, encoder->base.name, - aux_ch_name(aux_ch)); + aux_ch_name(aux_ch), source); return aux_ch; } diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.h b/drivers/gpu/drm/i915/display/intel_dp_aux.h index 5b608f9d3499..8447f3e601fe 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.h +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h @@ -6,6 +6,8 @@ #ifndef __INTEL_DP_AUX_H__ #define __INTEL_DP_AUX_H__ +#include <linux/types.h> + enum aux_ch; struct drm_i915_private; struct intel_dp; @@ -17,5 +19,6 @@ void intel_dp_aux_init(struct intel_dp *intel_dp); enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder); void intel_dp_aux_irq_handler(struct drm_i915_private *i915); +u32 intel_dp_aux_pack(const u8 *src, int src_bytes); #endif /* __INTEL_DP_AUX_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6b2d8a1e2aa9..6d68b36292d3 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <linux/math.h> #include <linux/string_helpers.h> #include "i915_reg.h" @@ -191,7 +192,8 @@ intel_combo_pll_enable_reg(struct drm_i915_private *i915, { if (IS_DG1(i915)) return DG1_DPLL_ENABLE(pll->info->id); - else if (IS_JSL_EHL(i915) && (pll->info->id == DPLL_ID_EHL_DPLL4)) + else if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) && + (pll->info->id == DPLL_ID_EHL_DPLL4)) return MG_PLL_ENABLE(0); return ICL_DPLL_ENABLE(pll->info->id); @@ -927,7 +929,7 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, switch (wrpll & WRPLL_REF_MASK) { case WRPLL_REF_SPECIAL_HSW: /* Muxed-SSC for BDW, non-SSC for non-ULT HSW. */ - if (IS_HASWELL(dev_priv) && !IS_HSW_ULT(dev_priv)) { + if (IS_HASWELL(dev_priv) && !IS_HASWELL_ULT(dev_priv)) { refclk = dev_priv->display.dpll.ref_clks.nssc; break; } @@ -2460,8 +2462,8 @@ static void icl_wrpll_params_populate(struct skl_wrpll_params *params, static bool ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915) { - return ((IS_PLATFORM(i915, INTEL_ELKHARTLAKE) && - IS_JSL_EHL_DISPLAY_STEP(i915, STEP_B0, STEP_FOREVER)) || + return (((IS_ELKHARTLAKE(i915) || IS_JASPERLAKE(i915)) && + IS_DISPLAY_STEP(i915, STEP_B0, STEP_FOREVER)) || IS_TIGERLAKE(i915) || IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) && i915->display.dpll.ref_clks.nssc == 38400; } @@ -3226,7 +3228,8 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, BIT(DPLL_ID_EHL_DPLL4) | BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); - } else if (IS_JSL_EHL(dev_priv) && port != PORT_A) { + } else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && + port != PORT_A) { dpll_mask = BIT(DPLL_ID_EHL_DPLL4) | BIT(DPLL_ID_ICL_DPLL1) | @@ -3567,7 +3570,8 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->div0 &= TGL_DPLL0_DIV0_AFC_STARTUP_MASK; } } else { - if (IS_JSL_EHL(dev_priv) && id == DPLL_ID_EHL_DPLL4) { + if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && + id == DPLL_ID_EHL_DPLL4) { hw_state->cfgcr0 = intel_de_read(dev_priv, ICL_DPLL_CFGCR0(4)); hw_state->cfgcr1 = intel_de_read(dev_priv, @@ -3623,7 +3627,8 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv, cfgcr1_reg = TGL_DPLL_CFGCR1(id); div0_reg = TGL_DPLL0_DIV0(id); } else { - if (IS_JSL_EHL(dev_priv) && id == DPLL_ID_EHL_DPLL4) { + if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && + id == DPLL_ID_EHL_DPLL4) { cfgcr0_reg = ICL_DPLL_CFGCR0(4); cfgcr1_reg = ICL_DPLL_CFGCR1(4); } else { @@ -3781,7 +3786,7 @@ static void adlp_cmtg_clock_gating_wa(struct drm_i915_private *i915, struct inte { u32 val; - if (!IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0) || + if (!(IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) || pll->info->id != DPLL_ID_ICL_DPLL0) return; /* @@ -3806,7 +3811,7 @@ static void combo_pll_enable(struct drm_i915_private *dev_priv, { i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); - if (IS_JSL_EHL(dev_priv) && + if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && pll->info->id == DPLL_ID_EHL_DPLL4) { /* @@ -3914,7 +3919,7 @@ static void combo_pll_disable(struct drm_i915_private *dev_priv, icl_pll_disable(dev_priv, pll, enable_reg); - if (IS_JSL_EHL(dev_priv) && + if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && pll->info->id == DPLL_ID_EHL_DPLL4) intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, pll->wakeref); @@ -4150,7 +4155,7 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv) dpll_mgr = &rkl_pll_mgr; else if (DISPLAY_VER(dev_priv) >= 12) dpll_mgr = &tgl_pll_mgr; - else if (IS_JSL_EHL(dev_priv)) + else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) dpll_mgr = &ehl_pll_mgr; else if (DISPLAY_VER(dev_priv) >= 11) dpll_mgr = &icl_pll_mgr; @@ -4335,7 +4340,8 @@ static void readout_dpll_hw_state(struct drm_i915_private *i915, pll->on = intel_dpll_get_hw_state(i915, pll, &pll->state.hw_state); - if (IS_JSL_EHL(i915) && pll->on && + if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) && + pll->on && pll->info->id == DPLL_ID_EHL_DPLL4) { pll->wakeref = intel_display_power_get(i915, POWER_DOMAIN_DC_OFF); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index ba62eb5d7c51..04e6810954b2 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -29,13 +29,6 @@ #include "intel_wakeref.h" -/*FIXME: Move this to a more appropriate place. */ -#define abs_diff(a, b) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - (void) (&__a == &__b); \ - __a > __b ? (__a - __b) : (__b - __a); }) - enum tc_port; struct drm_i915_private; struct intel_atomic_state; diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 7c5fddb203ba..fbfd8f959f17 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -166,6 +166,8 @@ struct i915_vma *intel_dpt_pin(struct i915_address_space *vm) i915_vma_get(vma); } + dpt->obj->mm.dirty = true; + atomic_dec(&i915->gpu_error.pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); @@ -261,7 +263,7 @@ intel_dpt_create(struct intel_framebuffer *fb) dpt_obj = i915_gem_object_create_stolen(i915, size); if (IS_ERR(dpt_obj) && !HAS_LMEM(i915)) { drm_dbg_kms(&i915->drm, "Allocating dpt from smem\n"); - dpt_obj = i915_gem_object_create_internal(i915, size); + dpt_obj = i915_gem_object_create_shmem(i915, size); } if (IS_ERR(dpt_obj)) return ERR_CAST(dpt_obj); diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index 5efdd471ac2b..d3cf6a652221 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -9,6 +9,26 @@ #include "intel_dsi.h" #include "intel_panel.h" +void intel_dsi_wait_panel_power_cycle(struct intel_dsi *intel_dsi) +{ + ktime_t panel_power_on_time; + s64 panel_power_off_duration; + + panel_power_on_time = ktime_get_boottime(); + panel_power_off_duration = ktime_ms_delta(panel_power_on_time, + intel_dsi->panel_power_off_time); + + if (panel_power_off_duration < (s64)intel_dsi->panel_pwr_cycle_delay) + msleep(intel_dsi->panel_pwr_cycle_delay - panel_power_off_duration); +} + +void intel_dsi_shutdown(struct intel_encoder *encoder) +{ + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); + + intel_dsi_wait_panel_power_cycle(intel_dsi); +} + int intel_dsi_bitrate(const struct intel_dsi *intel_dsi) { int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h b/drivers/gpu/drm/i915/display/intel_dsi.h index ce80bd8be519..083390e5e442 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.h +++ b/drivers/gpu/drm/i915/display/intel_dsi.h @@ -173,5 +173,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, const struct mipi_dsi_host_ops *funcs, enum port port); +void intel_dsi_wait_panel_power_cycle(struct intel_dsi *intel_dsi); +void intel_dsi_shutdown(struct intel_encoder *encoder); #endif /* _INTEL_DSI_H */ diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index c7935ea498c4..e56ec3f2d84a 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -235,7 +235,7 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev); u32 delay = *((const u32 *) data); - drm_dbg_kms(&i915->drm, "\n"); + drm_dbg_kms(&i915->drm, "%d usecs\n", delay); usleep_range(delay, delay + 10); data += 4; diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 9884678743b6..b386894c3a6d 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -509,6 +509,8 @@ void intel_dvo_init(struct drm_i915_private *i915) return; } + assert_port_valid(i915, intel_dvo->dev.port); + encoder->type = INTEL_OUTPUT_DVO; encoder->power_domain = POWER_DOMAIN_PORT_OTHER; encoder->port = intel_dvo->dev.port; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 7f8b2d7713c7..25382022cd27 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -47,6 +47,7 @@ #include "i915_reg.h" #include "i915_utils.h" #include "i915_vgpu.h" +#include "i915_vma.h" #include "intel_cdclk.h" #include "intel_de.h" #include "intel_display_trace.h" @@ -94,8 +95,7 @@ struct intel_fbc { struct mutex lock; unsigned int busy_bits; - struct drm_mm_node compressed_fb; - struct drm_mm_node compressed_llb; + struct i915_stolen_fb compressed_fb, compressed_llb; enum intel_fbc_id id; @@ -332,15 +332,16 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, - fbc->compressed_fb.start, U32_MAX)); - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, - fbc->compressed_llb.start, U32_MAX)); - + GEM_BUG_ON(range_overflows_end_t(u64, i915_gem_stolen_area_address(i915), + i915_gem_stolen_node_offset(&fbc->compressed_fb), + U32_MAX)); + GEM_BUG_ON(range_overflows_end_t(u64, i915_gem_stolen_area_address(i915), + i915_gem_stolen_node_offset(&fbc->compressed_llb), + U32_MAX)); intel_de_write(i915, FBC_CFB_BASE, - i915->dsm.stolen.start + fbc->compressed_fb.start); + i915_gem_stolen_node_address(i915, &fbc->compressed_fb)); intel_de_write(i915, FBC_LL_BASE, - i915->dsm.stolen.start + fbc->compressed_llb.start); + i915_gem_stolen_node_address(i915, &fbc->compressed_llb)); } static const struct intel_fbc_funcs i8xx_fbc_funcs = { @@ -447,7 +448,8 @@ static void g4x_fbc_program_cfb(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; - intel_de_write(i915, DPFC_CB_BASE, fbc->compressed_fb.start); + intel_de_write(i915, DPFC_CB_BASE, + i915_gem_stolen_node_offset(&fbc->compressed_fb)); } static const struct intel_fbc_funcs g4x_fbc_funcs = { @@ -498,7 +500,8 @@ static void ilk_fbc_program_cfb(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; - intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), fbc->compressed_fb.start); + intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), + i915_gem_stolen_node_offset(&fbc->compressed_fb)); } static const struct intel_fbc_funcs ilk_fbc_funcs = { @@ -605,7 +608,7 @@ static void ivb_fbc_activate(struct intel_fbc *fbc) else if (DISPLAY_VER(i915) == 9) skl_fbc_program_cfb_stride(fbc); - if (to_gt(i915)->ggtt->num_fences) + if (intel_gt_support_legacy_fencing(to_gt(i915))) snb_fbc_program_fence(fbc); intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id), @@ -713,7 +716,7 @@ static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(i915) || (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) - end = resource_size(&i915->dsm.stolen) - 8 * 1024 * 1024; + end = i915_gem_stolen_area_size(i915) - 8 * 1024 * 1024; else end = U64_MAX; @@ -770,9 +773,9 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc, int ret; drm_WARN_ON(&i915->drm, - drm_mm_node_allocated(&fbc->compressed_fb)); + i915_gem_stolen_node_allocated(&fbc->compressed_fb)); drm_WARN_ON(&i915->drm, - drm_mm_node_allocated(&fbc->compressed_llb)); + i915_gem_stolen_node_allocated(&fbc->compressed_llb)); if (DISPLAY_VER(i915) < 5 && !IS_G4X(i915)) { ret = i915_gem_stolen_insert_node(i915, &fbc->compressed_llb, @@ -792,15 +795,14 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc, drm_dbg_kms(&i915->drm, "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n", - fbc->compressed_fb.size, fbc->limit); - + i915_gem_stolen_node_size(&fbc->compressed_fb), fbc->limit); return 0; err_llb: - if (drm_mm_node_allocated(&fbc->compressed_llb)) + if (i915_gem_stolen_node_allocated(&fbc->compressed_llb)) i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); err: - if (drm_mm_initialized(&i915->mm.stolen)) + if (i915_gem_stolen_initialized(i915)) drm_info_once(&i915->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); return -ENOSPC; } @@ -825,9 +827,9 @@ static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) if (WARN_ON(intel_fbc_hw_is_active(fbc))) return; - if (drm_mm_node_allocated(&fbc->compressed_llb)) + if (i915_gem_stolen_node_allocated(&fbc->compressed_llb)) i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); - if (drm_mm_node_allocated(&fbc->compressed_fb)) + if (i915_gem_stolen_node_allocated(&fbc->compressed_fb)) i915_gem_stolen_remove_node(i915, &fbc->compressed_fb); } @@ -990,11 +992,10 @@ static void intel_fbc_update_state(struct intel_atomic_state *state, fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state); drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE && - !plane_state->ggtt_vma->fence); + !intel_gt_support_legacy_fencing(to_gt(i915))); - if (plane_state->flags & PLANE_HAS_FENCE && - plane_state->ggtt_vma->fence) - fbc_state->fence_id = plane_state->ggtt_vma->fence->id; + if (plane_state->flags & PLANE_HAS_FENCE) + fbc_state->fence_id = i915_vma_fence_id(plane_state->ggtt_vma); else fbc_state->fence_id = -1; @@ -1021,7 +1022,7 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) */ return DISPLAY_VER(i915) >= 9 || (plane_state->flags & PLANE_HAS_FENCE && - plane_state->ggtt_vma->fence); + i915_vma_fence_id(plane_state->ggtt_vma) != -1); } static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state) @@ -1030,7 +1031,8 @@ static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state) struct intel_fbc *fbc = plane->fbc; return intel_fbc_min_limit(plane_state) <= fbc->limit && - intel_fbc_cfb_size(plane_state) <= fbc->compressed_fb.size * fbc->limit; + intel_fbc_cfb_size(plane_state) <= fbc->limit * + i915_gem_stolen_node_size(&fbc->compressed_fb); } static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state) @@ -1054,6 +1056,11 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, if (!fbc) return 0; + if (!i915_gem_stolen_initialized(i915)) { + plane_state->no_fbc_reason = "stolen memory not initialised"; + return 0; + } + if (intel_vgpu_active(i915)) { plane_state->no_fbc_reason = "VGPU active"; return 0; @@ -1707,9 +1714,6 @@ void intel_fbc_init(struct drm_i915_private *i915) { enum intel_fbc_id fbc_id; - if (!drm_mm_initialized(&i915->mm.stolen)) - DISPLAY_RUNTIME_INFO(i915)->fbc_mask = 0; - if (need_fbc_vtd_wa(i915)) DISPLAY_RUNTIME_INFO(i915)->fbc_mask = 0; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 80c3f88310db..31d0d695d567 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -85,9 +85,9 @@ static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU); } -FB_GEN_DEFAULT_DEFERRED_IO_OPS(intel_fbdev, - drm_fb_helper_damage_range, - drm_fb_helper_damage_area) +FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(intel_fbdev, + drm_fb_helper_damage_range, + drm_fb_helper_damage_area) static int intel_fbdev_set_par(struct fb_info *info) { @@ -182,8 +182,10 @@ static int intelfb_alloc(struct drm_fb_helper *helper, * If the FB is too big, just don't use it since fbdev is not very * important and we should probably use that space with FBC or other * features. + * + * Also skip stolen on MTL as Wa_22018444074 mitigation. */ - if (size * 2 < dev_priv->dsm.usable_size) + if (!(IS_METEORLAKE(dev_priv)) && size * 2 < dev_priv->dsm.usable_size) obj = i915_gem_object_create_stolen(dev_priv, size); if (IS_ERR(obj)) obj = i915_gem_object_create_shmem(dev_priv, size); diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 17a7aa8b28c2..22392f94b626 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -167,7 +167,7 @@ void __intel_fb_invalidate(struct intel_frontbuffer *front, enum fb_op_origin origin, unsigned int frontbuffer_bits) { - struct drm_i915_private *i915 = to_i915(front->obj->base.dev); + struct drm_i915_private *i915 = intel_bo_to_i915(front->obj); if (origin == ORIGIN_CS) { spin_lock(&i915->display.fb_tracking.lock); @@ -188,7 +188,7 @@ void __intel_fb_flush(struct intel_frontbuffer *front, enum fb_op_origin origin, unsigned int frontbuffer_bits) { - struct drm_i915_private *i915 = to_i915(front->obj->base.dev); + struct drm_i915_private *i915 = intel_bo_to_i915(front->obj); if (origin == ORIGIN_CS) { spin_lock(&i915->display.fb_tracking.lock); @@ -221,24 +221,18 @@ static void frontbuffer_retire(struct i915_active *ref) } static void frontbuffer_release(struct kref *ref) - __releases(&to_i915(front->obj->base.dev)->display.fb_tracking.lock) + __releases(&intel_bo_to_i915(front->obj)->display.fb_tracking.lock) { struct intel_frontbuffer *front = container_of(ref, typeof(*front), ref); struct drm_i915_gem_object *obj = front->obj; - struct i915_vma *vma; - drm_WARN_ON(obj->base.dev, atomic_read(&front->bits)); + drm_WARN_ON(&intel_bo_to_i915(obj)->drm, atomic_read(&front->bits)); - spin_lock(&obj->vma.lock); - for_each_ggtt_vma(vma, obj) { - i915_vma_clear_scanout(vma); - vma->display_alignment = I915_GTT_MIN_ALIGNMENT; - } - spin_unlock(&obj->vma.lock); + i915_ggtt_clear_scanout(obj); - RCU_INIT_POINTER(obj->frontbuffer, NULL); - spin_unlock(&to_i915(obj->base.dev)->display.fb_tracking.lock); + i915_gem_object_set_frontbuffer(obj, NULL); + spin_unlock(&intel_bo_to_i915(obj)->display.fb_tracking.lock); i915_active_fini(&front->write); @@ -249,10 +243,10 @@ static void frontbuffer_release(struct kref *ref) struct intel_frontbuffer * intel_frontbuffer_get(struct drm_i915_gem_object *obj) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_frontbuffer *front; + struct drm_i915_private *i915 = intel_bo_to_i915(obj); + struct intel_frontbuffer *front, *cur; - front = __intel_frontbuffer_get(obj); + front = i915_gem_object_get_frontbuffer(obj); if (front) return front; @@ -269,24 +263,18 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj) I915_ACTIVE_RETIRE_SLEEPS); spin_lock(&i915->display.fb_tracking.lock); - if (rcu_access_pointer(obj->frontbuffer)) { - kfree(front); - front = rcu_dereference_protected(obj->frontbuffer, true); - kref_get(&front->ref); - } else { - i915_gem_object_get(obj); - rcu_assign_pointer(obj->frontbuffer, front); - } + cur = i915_gem_object_set_frontbuffer(obj, front); spin_unlock(&i915->display.fb_tracking.lock); - - return front; + if (cur != front) + kfree(front); + return cur; } void intel_frontbuffer_put(struct intel_frontbuffer *front) { kref_put_lock(&front->ref, frontbuffer_release, - &to_i915(front->obj->base.dev)->display.fb_tracking.lock); + &intel_bo_to_i915(front->obj)->display.fb_tracking.lock); } /** @@ -315,13 +303,13 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old, BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); if (old) { - drm_WARN_ON(old->obj->base.dev, + drm_WARN_ON(&intel_bo_to_i915(old->obj)->drm, !(atomic_read(&old->bits) & frontbuffer_bits)); atomic_andnot(frontbuffer_bits, &old->bits); } if (new) { - drm_WARN_ON(new->obj->base.dev, + drm_WARN_ON(&intel_bo_to_i915(new->obj)->drm, atomic_read(&new->bits) & frontbuffer_bits); atomic_or(frontbuffer_bits, &new->bits); } diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h index 3c474ed937fb..72d89be3284b 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h @@ -28,7 +28,6 @@ #include <linux/bits.h> #include <linux/kref.h> -#include "gem/i915_gem_object_types.h" #include "i915_active_types.h" struct drm_i915_private; @@ -75,33 +74,6 @@ void intel_frontbuffer_flip(struct drm_i915_private *i915, void intel_frontbuffer_put(struct intel_frontbuffer *front); -static inline struct intel_frontbuffer * -__intel_frontbuffer_get(const struct drm_i915_gem_object *obj) -{ - struct intel_frontbuffer *front; - - if (likely(!rcu_access_pointer(obj->frontbuffer))) - return NULL; - - rcu_read_lock(); - do { - front = rcu_dereference(obj->frontbuffer); - if (!front) - break; - - if (unlikely(!kref_get_unless_zero(&front->ref))) - continue; - - if (likely(front == rcu_access_pointer(obj->frontbuffer))) - break; - - intel_frontbuffer_put(front); - } while (1); - rcu_read_unlock(); - - return front; -} - struct intel_frontbuffer * intel_frontbuffer_get(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 34fabadefaf6..a42549fa9691 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,8 +177,11 @@ bool intel_hdcp2_capable(struct intel_connector *connector) struct intel_gt *gt = i915->media_gt; struct intel_gsc_uc *gsc = gt ? >->uc.gsc : NULL; - if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) + if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) { + drm_dbg_kms(&i915->drm, + "GSC components required for HDCP2.2 are not ready\n"); return false; + } } /* MEI/GSC interface is solid depending on which is used */ diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c index 72573ce1d0e9..d753db3eef15 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c @@ -6,6 +6,7 @@ #include <drm/i915_hdcp_interface.h> #include "gem/i915_gem_region.h" +#include "gt/intel_gt.h" #include "gt/uc/intel_gsc_uc_heci_cmd_submit.h" #include "i915_drv.h" #include "i915_utils.h" @@ -621,24 +622,26 @@ static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915, struct intel_gt *gt = i915->media_gt; struct drm_i915_gem_object *obj = NULL; struct i915_vma *vma = NULL; - void *cmd; + void *cmd_in, *cmd_out; int err; - /* allocate object of one page for HDCP command memory and store it */ - obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); + /* allocate object of two page for HDCP command memory and store it */ + obj = i915_gem_object_create_shmem(i915, 2 * PAGE_SIZE); if (IS_ERR(obj)) { drm_err(&i915->drm, "Failed to allocate HDCP streaming command!\n"); return PTR_ERR(obj); } - cmd = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(i915, obj, true)); - if (IS_ERR(cmd)) { + cmd_in = i915_gem_object_pin_map_unlocked(obj, intel_gt_coherent_map_type(gt, obj, true)); + if (IS_ERR(cmd_in)) { drm_err(&i915->drm, "Failed to map gsc message page!\n"); - err = PTR_ERR(cmd); + err = PTR_ERR(cmd_in); goto out_unpin; } + cmd_out = cmd_in + PAGE_SIZE; + vma = i915_vma_instance(obj, >->ggtt->vm, NULL); if (IS_ERR(vma)) { err = PTR_ERR(vma); @@ -649,9 +652,10 @@ static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915, if (err) goto out_unmap; - memset(cmd, 0, obj->base.size); + memset(cmd_in, 0, obj->base.size); - hdcp_message->hdcp_cmd = cmd; + hdcp_message->hdcp_cmd_in = cmd_in; + hdcp_message->hdcp_cmd_out = cmd_out; hdcp_message->vma = vma; return 0; @@ -691,6 +695,8 @@ static void intel_hdcp_gsc_free_message(struct drm_i915_private *i915) struct intel_hdcp_gsc_message *hdcp_message = i915->display.hdcp.hdcp_message; + hdcp_message->hdcp_cmd_in = NULL; + hdcp_message->hdcp_cmd_out = NULL; i915_vma_unpin_and_release(&hdcp_message->vma, I915_VMA_RELEASE_MAP); kfree(hdcp_message); } @@ -721,38 +727,42 @@ void intel_hdcp_gsc_fini(struct drm_i915_private *i915) } static int intel_gsc_send_sync(struct drm_i915_private *i915, - struct intel_gsc_mtl_header *header, u64 addr, + struct intel_gsc_mtl_header *header_in, + struct intel_gsc_mtl_header *header_out, + u64 addr_in, u64 addr_out, size_t msg_out_len) { struct intel_gt *gt = i915->media_gt; int ret; - header->flags = 0; - ret = intel_gsc_uc_heci_cmd_submit_packet(>->uc.gsc, addr, - header->message_size, - addr, - msg_out_len + sizeof(*header)); + ret = intel_gsc_uc_heci_cmd_submit_packet(>->uc.gsc, addr_in, + header_in->message_size, + addr_out, + msg_out_len + sizeof(*header_out)); if (ret) { drm_err(&i915->drm, "failed to send gsc HDCP msg (%d)\n", ret); return ret; } /* - * Checking validity marker for memory sanity + * Checking validity marker and header status to see if some error has + * blocked us from sending message to gsc cs */ - if (header->validity_marker != GSC_HECI_VALIDITY_MARKER) { + if (header_out->validity_marker != GSC_HECI_VALIDITY_MARKER) { drm_err(&i915->drm, "invalid validity marker\n"); return -EINVAL; } - if (header->status != 0) { + if (header_out->status != 0) { drm_err(&i915->drm, "header status indicates error %d\n", - header->status); + header_out->status); return -EINVAL; } - if (header->flags & GSC_OUTFLAG_MSG_PENDING) + if (header_out->flags & GSC_OUTFLAG_MSG_PENDING) { + header_in->gsc_message_handle = header_out->gsc_message_handle; return -EAGAIN; + } return 0; } @@ -769,11 +779,11 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, size_t msg_out_len) { struct intel_gt *gt = i915->media_gt; - struct intel_gsc_mtl_header *header; - const size_t max_msg_size = PAGE_SIZE - sizeof(*header); + struct intel_gsc_mtl_header *header_in, *header_out; + const size_t max_msg_size = PAGE_SIZE - sizeof(*header_in); struct intel_hdcp_gsc_message *hdcp_message; - u64 addr, host_session_id; - u32 reply_size, msg_size; + u64 addr_in, addr_out, host_session_id; + u32 reply_size, msg_size_in, msg_size_out; int ret, tries = 0; if (!intel_uc_uses_gsc_uc(>->uc)) @@ -782,16 +792,20 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, if (msg_in_len > max_msg_size || msg_out_len > max_msg_size) return -ENOSPC; + msg_size_in = msg_in_len + sizeof(*header_in); + msg_size_out = msg_out_len + sizeof(*header_out); hdcp_message = i915->display.hdcp.hdcp_message; - header = hdcp_message->hdcp_cmd; - addr = i915_ggtt_offset(hdcp_message->vma); + header_in = hdcp_message->hdcp_cmd_in; + header_out = hdcp_message->hdcp_cmd_out; + addr_in = i915_ggtt_offset(hdcp_message->vma); + addr_out = addr_in + PAGE_SIZE; - msg_size = msg_in_len + sizeof(*header); - memset(header, 0, msg_size); + memset(header_in, 0, msg_size_in); + memset(header_out, 0, msg_size_out); get_random_bytes(&host_session_id, sizeof(u64)); - intel_gsc_uc_heci_cmd_emit_mtl_header(header, HECI_MEADDRESS_HDCP, - msg_size, host_session_id); - memcpy(hdcp_message->hdcp_cmd + sizeof(*header), msg_in, msg_in_len); + intel_gsc_uc_heci_cmd_emit_mtl_header(header_in, HECI_MEADDRESS_HDCP, + msg_size_in, host_session_id); + memcpy(hdcp_message->hdcp_cmd_in + sizeof(*header_in), msg_in, msg_in_len); /* * Keep sending request in case the pending bit is set no need to add @@ -800,7 +814,8 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, * 20 times each message 50 ms apart */ do { - ret = intel_gsc_send_sync(i915, header, addr, msg_out_len); + ret = intel_gsc_send_sync(i915, header_in, header_out, addr_in, + addr_out, msg_out_len); /* Only try again if gsc says so */ if (ret != -EAGAIN) @@ -814,7 +829,7 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, goto err; /* we use the same mem for the reply, so header is in the same loc */ - reply_size = header->message_size - sizeof(*header); + reply_size = header_out->message_size - sizeof(*header_out); if (reply_size > msg_out_len) { drm_warn(&i915->drm, "caller with insufficient HDCP reply size %u (%d)\n", reply_size, (u32)msg_out_len); @@ -824,7 +839,7 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, reply_size, (u32)msg_out_len); } - memcpy(msg_out, hdcp_message->hdcp_cmd + sizeof(*header), msg_out_len); + memcpy(msg_out, hdcp_message->hdcp_cmd_out + sizeof(*header_out), msg_out_len); err: return ret; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h index 5cc9fd2e88f6..cbf96551e534 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h @@ -13,7 +13,8 @@ struct drm_i915_private; struct intel_hdcp_gsc_message { struct i915_vma *vma; - void *hdcp_cmd; + void *hdcp_cmd_in; + void *hdcp_cmd_out; }; bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 7ac5e6c5e00d..94a7e1537f42 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2880,21 +2880,12 @@ static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv, return ddc_pin; } -static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) +static u8 intel_hdmi_default_ddc_pin(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = encoder->port; u8 ddc_pin; - ddc_pin = intel_bios_hdmi_ddc_pin(encoder->devdata); - if (ddc_pin) { - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] Using DDC pin 0x%x (VBT)\n", - encoder->base.base.id, encoder->base.name, - ddc_pin); - return ddc_pin; - } - if (IS_ALDERLAKE_S(dev_priv)) ddc_pin = adls_port_to_ddc_pin(dev_priv, port); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) @@ -2903,7 +2894,8 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) ddc_pin = rkl_port_to_ddc_pin(dev_priv, port); else if (DISPLAY_VER(dev_priv) == 9 && HAS_PCH_TGP(dev_priv)) ddc_pin = gen9bc_tgp_port_to_ddc_pin(dev_priv, port); - else if (IS_JSL_EHL(dev_priv) && HAS_PCH_TGP(dev_priv)) + else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && + HAS_PCH_TGP(dev_priv)) ddc_pin = mcc_port_to_ddc_pin(dev_priv, port); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) ddc_pin = icl_port_to_ddc_pin(dev_priv, port); @@ -2916,10 +2908,62 @@ static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) else ddc_pin = g4x_port_to_ddc_pin(dev_priv, port); - drm_dbg_kms(&dev_priv->drm, - "[ENCODER:%d:%s] Using DDC pin 0x%x (platform default)\n", + return ddc_pin; +} + +static struct intel_encoder * +get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_encoder *other; + + for_each_intel_encoder(&i915->drm, other) { + if (other == encoder) + continue; + + if (!intel_encoder_is_dig_port(other)) + continue; + + if (enc_to_dig_port(other)->hdmi.ddc_bus == ddc_pin) + return other; + } + + return NULL; +} + +static u8 intel_hdmi_ddc_pin(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_encoder *other; + const char *source; + u8 ddc_pin; + + ddc_pin = intel_bios_hdmi_ddc_pin(encoder->devdata); + source = "VBT"; + + if (!ddc_pin) { + ddc_pin = intel_hdmi_default_ddc_pin(encoder); + source = "platform default"; + } + + if (!intel_gmbus_is_valid_pin(i915, ddc_pin)) { + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Invalid DDC pin %d\n", + encoder->base.base.id, encoder->base.name, ddc_pin); + return 0; + } + + other = get_encoder_by_ddc_pin(encoder, ddc_pin); + if (other) { + drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] DDC pin %d already claimed by [ENCODER:%d:%s]\n", + encoder->base.base.id, encoder->base.name, ddc_pin, + other->base.base.id, other->base.name); + return 0; + } + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] Using DDC pin 0x%x (%s)\n", encoder->base.base.id, encoder->base.name, - ddc_pin); + ddc_pin, source); return ddc_pin; } @@ -2990,6 +3034,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, return; intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder); + if (!intel_hdmi->ddc_bus) + return; + ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); drm_connector_init_with_ddc(dev, connector, diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 1160fa20433b..69a83dcc1996 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -211,7 +211,7 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) /* Enable polling and queue hotplug re-enabling. */ if (hpd_disabled) { - drm_kms_helper_poll_enable(&dev_priv->drm); + drm_kms_helper_poll_reschedule(&dev_priv->drm); mod_delayed_work(dev_priv->unordered_wq, &dev_priv->display.hotplug.reenable_work, msecs_to_jiffies(HPD_STORM_REENABLE_DELAY)); @@ -376,6 +376,8 @@ static void i915_hotplug_work_func(struct work_struct *work) u32 changed = 0, retry = 0; u32 hpd_event_bits; u32 hpd_retry_bits; + struct drm_connector *first_changed_connector = NULL; + int changed_connectors = 0; mutex_lock(&dev_priv->drm.mode_config.mutex); drm_dbg_kms(&dev_priv->drm, "running encoder hotplug functions\n"); @@ -428,6 +430,11 @@ static void i915_hotplug_work_func(struct work_struct *work) break; case INTEL_HOTPLUG_CHANGED: changed |= hpd_bit; + changed_connectors++; + if (!first_changed_connector) { + drm_connector_get(&connector->base); + first_changed_connector = &connector->base; + } break; case INTEL_HOTPLUG_RETRY: retry |= hpd_bit; @@ -438,9 +445,14 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_connector_list_iter_end(&conn_iter); mutex_unlock(&dev_priv->drm.mode_config.mutex); - if (changed) + if (changed_connectors == 1) + drm_kms_helper_connector_hotplug_event(first_changed_connector); + else if (changed_connectors > 0) drm_kms_helper_hotplug_event(&dev_priv->drm); + if (first_changed_connector) + drm_connector_put(first_changed_connector); + /* Remove shared HPD pins that have changed */ retry &= ~changed; if (retry) { @@ -649,7 +661,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work) drm_connector_list_iter_end(&conn_iter); if (enabled) - drm_kms_helper_poll_enable(&dev_priv->drm); + drm_kms_helper_poll_reschedule(&dev_priv->drm); mutex_unlock(&dev_priv->drm.mode_config.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c index f95fa793fabb..95a7ea94f417 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c @@ -842,6 +842,8 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); + else + intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250); ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); @@ -1049,7 +1051,7 @@ static void mtp_hpd_irq_setup(struct drm_i915_private *i915) enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd); hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd); - intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); + intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250); mtp_hpd_invert(i915); ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs); diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index d6fe2bbabe55..09c1aa1427ad 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -1348,11 +1348,12 @@ out_unlock: static int get_registers(struct intel_overlay *overlay, bool use_phys) { struct drm_i915_private *i915 = overlay->i915; - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj = ERR_PTR(-ENODEV); struct i915_vma *vma; int err; - obj = i915_gem_object_create_stolen(i915, PAGE_SIZE); + if (!IS_METEORLAKE(i915)) /* Wa_22018444074 */ + obj = i915_gem_object_create_stolen(i915, PAGE_SIZE); if (IS_ERR(obj)) obj = i915_gem_object_create_internal(i915, PAGE_SIZE); if (IS_ERR(obj)) diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index f4c09cc37a5e..9583e86b602a 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -423,7 +423,7 @@ static bool wrpll_uses_pch_ssc(struct drm_i915_private *dev_priv, if ((ctl & WRPLL_REF_MASK) == WRPLL_REF_PCH_SSC) return true; - if ((IS_BROADWELL(dev_priv) || IS_HSW_ULT(dev_priv)) && + if ((IS_BROADWELL(dev_priv) || IS_HASWELL_ULT(dev_priv)) && (ctl & WRPLL_REF_MASK) == WRPLL_REF_MUXED_SSC_BDW && (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) return true; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 56c17283ba2d..97d5eef10130 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -234,23 +234,91 @@ static u32 psr_irq_mask_get(struct intel_dp *intel_dp) EDP_PSR_MASK(intel_dp->psr.transcoder); } -static void psr_irq_control(struct intel_dp *intel_dp) +static i915_reg_t psr_ctl_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - i915_reg_t imr_reg; - u32 mask; + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_CTL(cpu_transcoder); + else + return HSW_SRD_CTL; +} + +static i915_reg_t psr_debug_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_DEBUG(cpu_transcoder); + else + return HSW_SRD_DEBUG; +} + +static i915_reg_t psr_perf_cnt_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_PERF_CNT(cpu_transcoder); + else + return HSW_SRD_PERF_CNT; +} + +static i915_reg_t psr_status_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_STATUS(cpu_transcoder); + else + return HSW_SRD_STATUS; +} + +static i915_reg_t psr_imr_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + if (DISPLAY_VER(dev_priv) >= 12) + return TRANS_PSR_IMR(cpu_transcoder); + else + return EDP_PSR_IMR; +} +static i915_reg_t psr_iir_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ if (DISPLAY_VER(dev_priv) >= 12) - imr_reg = TRANS_PSR_IMR(intel_dp->psr.transcoder); + return TRANS_PSR_IIR(cpu_transcoder); + else + return EDP_PSR_IIR; +} + +static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_AUX_CTL(cpu_transcoder); + else + return HSW_SRD_AUX_CTL; +} + +static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder, int i) +{ + if (DISPLAY_VER(dev_priv) >= 8) + return EDP_PSR_AUX_DATA(cpu_transcoder, i); else - imr_reg = EDP_PSR_IMR; + return HSW_SRD_AUX_DATA(i); +} + +static void psr_irq_control(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + enum transcoder cpu_transcoder = intel_dp->psr.transcoder; + u32 mask; mask = psr_irq_psr_error_bit_get(intel_dp); if (intel_dp->psr.debug & I915_PSR_DEBUG_IRQ) mask |= psr_irq_post_exit_bit_get(intel_dp) | psr_irq_pre_entry_bit_get(intel_dp); - intel_de_rmw(dev_priv, imr_reg, psr_irq_mask_get(intel_dp), ~mask); + intel_de_rmw(dev_priv, psr_imr_reg(dev_priv, cpu_transcoder), + psr_irq_mask_get(intel_dp), ~mask); } static void psr_event_print(struct drm_i915_private *i915, @@ -296,12 +364,6 @@ void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir) struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum transcoder cpu_transcoder = intel_dp->psr.transcoder; ktime_t time_ns = ktime_get(); - i915_reg_t imr_reg; - - if (DISPLAY_VER(dev_priv) >= 12) - imr_reg = TRANS_PSR_IMR(cpu_transcoder); - else - imr_reg = EDP_PSR_IMR; if (psr_iir & psr_irq_pre_entry_bit_get(intel_dp)) { intel_dp->psr.last_entry_attempt = time_ns; @@ -339,7 +401,8 @@ void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir) * again so we don't care about unmask the interruption * or unset irq_aux_error. */ - intel_de_rmw(dev_priv, imr_reg, 0, psr_irq_psr_error_bit_get(intel_dp)); + intel_de_rmw(dev_priv, psr_imr_reg(dev_priv, cpu_transcoder), + 0, psr_irq_psr_error_bit_get(intel_dp)); queue_work(dev_priv->unordered_wq, &intel_dp->psr.work); } @@ -467,6 +530,43 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) } } +static void hsw_psr_setup_aux(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + enum transcoder cpu_transcoder = intel_dp->psr.transcoder; + u32 aux_clock_divider, aux_ctl; + /* write DP_SET_POWER=D0 */ + static const u8 aux_msg[] = { + [0] = (DP_AUX_NATIVE_WRITE << 4) | ((DP_SET_POWER >> 16) & 0xf), + [1] = (DP_SET_POWER >> 8) & 0xff, + [2] = DP_SET_POWER & 0xff, + [3] = 1 - 1, + [4] = DP_SET_POWER_D0, + }; + int i; + + BUILD_BUG_ON(sizeof(aux_msg) > 20); + for (i = 0; i < sizeof(aux_msg); i += 4) + intel_de_write(dev_priv, + psr_aux_data_reg(dev_priv, cpu_transcoder, i >> 2), + intel_dp_aux_pack(&aux_msg[i], sizeof(aux_msg) - i)); + + aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); + + /* Start with bits set for DDI_AUX_CTL register */ + aux_ctl = intel_dp->get_aux_send_ctl(intel_dp, sizeof(aux_msg), + aux_clock_divider); + + /* Select only valid bits for SRD_AUX_CTL */ + aux_ctl &= EDP_PSR_AUX_CTL_TIME_OUT_MASK | + EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK | + EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK | + EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK; + + intel_de_write(dev_priv, psr_aux_ctl_reg(dev_priv, cpu_transcoder), + aux_ctl); +} + static void intel_psr_enable_sink(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -528,6 +628,15 @@ static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) else val |= EDP_PSR_TP2_TP3_TIME_2500us; + /* + * WA 0479: hsw,bdw + * "Do not skip both TP1 and TP2/TP3" + */ + if (DISPLAY_VER(dev_priv) < 9 && + connector->panel.vbt.psr.tp1_wakeup_time_us == 0 && + connector->panel.vbt.psr.tp2_tp3_wakeup_time_us == 0) + val |= EDP_PSR_TP2_TP3_TIME_100us; + check_tp3_sel: if (intel_dp_source_supports_tps3(dev_priv) && drm_dp_tps3_supported(intel_dp->dpcd)) @@ -577,7 +686,7 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp) if (DISPLAY_VER(dev_priv) >= 8) val |= EDP_PSR_CRC_ENABLE; - intel_de_rmw(dev_priv, EDP_PSR_CTL(cpu_transcoder), + intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val); } @@ -639,7 +748,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) } /* Wa_22012278275:adl-p */ - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_E0)) { + if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_E0)) { static const u8 map[] = { 2, /* 5 lines */ 1, /* 6 lines */ @@ -685,7 +794,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is * recommending keep this bit unset while PSR2 is enabled. */ - intel_de_write(dev_priv, EDP_PSR_CTL(cpu_transcoder), 0); + intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), 0); intel_de_write(dev_priv, EDP_PSR2_CTL(cpu_transcoder), val); } @@ -697,8 +806,10 @@ transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder cpu_trans return cpu_transcoder == TRANSCODER_A || cpu_transcoder == TRANSCODER_B; else if (DISPLAY_VER(dev_priv) >= 12) return cpu_transcoder == TRANSCODER_A; - else + else if (DISPLAY_VER(dev_priv) >= 9) return cpu_transcoder == TRANSCODER_EDP; + else + return false; } static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate) @@ -807,7 +918,7 @@ tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp, return; /* Wa_16011303918:adl-p */ - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) + if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) return; /* @@ -963,7 +1074,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; /* JSL and EHL only supports eDP 1.3 */ - if (IS_JSL_EHL(dev_priv)) { + if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not supported by phy\n"); return false; } @@ -975,7 +1086,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { + if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not completely functional in this stepping\n"); return false; } @@ -1033,7 +1144,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, /* Wa_16011303918:adl-p */ if (crtc_state->vrr.enable && - IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { + IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, not compatible with HW stepping + VRR\n"); return false; @@ -1201,13 +1312,15 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum transcoder cpu_transcoder = intel_dp->psr.transcoder; - if (transcoder_has_psr2(dev_priv, cpu_transcoder)) - drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)) & EDP_PSR2_ENABLE); + drm_WARN_ON(&dev_priv->drm, + transcoder_has_psr2(dev_priv, cpu_transcoder) && + intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)) & EDP_PSR2_ENABLE); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, EDP_PSR_CTL(cpu_transcoder)) & EDP_PSR_ENABLE); + intel_de_read(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder)) & EDP_PSR_ENABLE); + drm_WARN_ON(&dev_priv->drm, intel_dp->psr.active); + lockdep_assert_held(&intel_dp->psr.lock); /* psr1 and psr2 are mutually exclusive.*/ @@ -1272,6 +1385,13 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, u32 mask; /* + * Only HSW and BDW have PSR AUX registers that need to be setup. + * SKL+ use hardcoded values PSR AUX transactions + */ + if (DISPLAY_VER(dev_priv) < 9) + hsw_psr_setup_aux(intel_dp); + + /* * Per Spec: Avoid continuous PSR exit by masking MEMUP and HPD also * mask LPSP to avoid dependency on other drivers that might block * runtime_pm besides preventing other hw tracking issues now we @@ -1282,11 +1402,18 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, EDP_PSR_DEBUG_MASK_LPSP | EDP_PSR_DEBUG_MASK_MAX_SLEEP; - if (DISPLAY_VER(dev_priv) < 11) + /* + * No separate pipe reg write mask on hsw/bdw, so have to unmask all + * registers in order to keep the CURSURFLIVE tricks working :( + */ + if (IS_DISPLAY_VER(dev_priv, 9, 10)) mask |= EDP_PSR_DEBUG_MASK_DISP_REG_WRITE; - intel_de_write(dev_priv, EDP_PSR_DEBUG(cpu_transcoder), - mask); + /* allow PSR with sprite enabled */ + if (IS_HASWELL(dev_priv)) + mask |= EDP_PSR_DEBUG_MASK_SPRITE_ENABLE; + + intel_de_write(dev_priv, psr_debug_reg(dev_priv, cpu_transcoder), mask); psr_irq_control(intel_dp); @@ -1352,10 +1479,7 @@ static bool psr_interrupt_error_check(struct intel_dp *intel_dp) * first time that PSR HW tries to activate so lets keep PSR disabled * to avoid any rendering problems. */ - if (DISPLAY_VER(dev_priv) >= 12) - val = intel_de_read(dev_priv, TRANS_PSR_IIR(cpu_transcoder)); - else - val = intel_de_read(dev_priv, EDP_PSR_IIR); + val = intel_de_read(dev_priv, psr_iir_reg(dev_priv, cpu_transcoder)); val &= psr_irq_psr_error_bit_get(intel_dp); if (val) { intel_dp->psr.sink_not_reliable = true; @@ -1418,7 +1542,7 @@ static void intel_psr_exit(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, val & EDP_PSR2_ENABLE); } - val = intel_de_read(dev_priv, EDP_PSR_CTL(cpu_transcoder)); + val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder)); drm_WARN_ON(&dev_priv->drm, val & EDP_PSR_ENABLE); return; @@ -1432,7 +1556,7 @@ static void intel_psr_exit(struct intel_dp *intel_dp) drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR2_ENABLE)); } else { - val = intel_de_rmw(dev_priv, EDP_PSR_CTL(cpu_transcoder), + val = intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), EDP_PSR_ENABLE, 0); drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR_ENABLE)); @@ -1451,7 +1575,7 @@ static void intel_psr_wait_exit_locked(struct intel_dp *intel_dp) psr_status = EDP_PSR2_STATUS(cpu_transcoder); psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; } else { - psr_status = EDP_PSR_STATUS(cpu_transcoder); + psr_status = psr_status_reg(dev_priv, cpu_transcoder); psr_status_mask = EDP_PSR_STATUS_STATE_MASK; } @@ -2151,7 +2275,7 @@ static int _psr1_ready_for_pipe_update_locked(struct intel_dp *intel_dp) * defensive enough to cover everything. */ return intel_de_wait_for_clear(dev_priv, - EDP_PSR_STATUS(cpu_transcoder), + psr_status_reg(dev_priv, cpu_transcoder), EDP_PSR_STATUS_STATE_MASK, 50); } @@ -2205,7 +2329,7 @@ static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp) reg = EDP_PSR2_STATUS(cpu_transcoder); mask = EDP_PSR2_STATUS_STATE_MASK; } else { - reg = EDP_PSR_STATUS(cpu_transcoder); + reg = psr_status_reg(dev_priv, cpu_transcoder); mask = EDP_PSR_STATUS_STATE_MASK; } @@ -2825,7 +2949,7 @@ psr_source_status(struct intel_dp *intel_dp, struct seq_file *m) "SRDOFFACK", "SRDENT_ON", }; - val = intel_de_read(dev_priv, EDP_PSR_STATUS(cpu_transcoder)); + val = intel_de_read(dev_priv, psr_status_reg(dev_priv, cpu_transcoder)); status_val = REG_FIELD_GET(EDP_PSR_STATUS_STATE_MASK, val); if (status_val < ARRAY_SIZE(live_status)) status = live_status[status_val]; @@ -2872,7 +2996,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)); enabled = val & EDP_PSR2_ENABLE; } else { - val = intel_de_read(dev_priv, EDP_PSR_CTL(cpu_transcoder)); + val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder)); enabled = val & EDP_PSR_ENABLE; } seq_printf(m, "Source PSR ctl: %s [0x%08x]\n", @@ -2884,7 +3008,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) /* * SKL+ Perf counter is reset to 0 everytime DC state is entered */ - val = intel_de_read(dev_priv, EDP_PSR_PERF_CNT(cpu_transcoder)); + val = intel_de_read(dev_priv, psr_perf_cnt_reg(dev_priv, cpu_transcoder)); seq_printf(m, "Performance counter: %u\n", REG_FIELD_GET(EDP_PSR_PERF_CNT_MASK, val)); diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 8750cb0d8d9d..d39951383c92 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -7,6 +7,7 @@ #define __INTEL_PSR_REGS_H__ #include "intel_display_reg_defs.h" +#include "intel_dp_aux_regs.h" #define TRANS_EXITLINE(trans) _MMIO_TRANS2((trans), _TRANS_EXITLINE_A) #define EXITLINE_ENABLE REG_BIT(31) @@ -19,6 +20,7 @@ * HSW PSR registers are relative to DDIA(_DDI_BUF_CTL_A + 0x800) with just one * instance of it */ +#define HSW_SRD_CTL _MMIO(0x64800) #define _SRD_CTL_A 0x60800 #define _SRD_CTL_EDP 0x6f800 #define EDP_PSR_CTL(tran) _MMIO_TRANS2(tran, _SRD_CTL_A) @@ -79,10 +81,22 @@ #define EDP_PSR_PRE_ENTRY(trans) (TGL_PSR_PRE_ENTRY << \ _EDP_PSR_TRANS_SHIFT(trans)) +#define HSW_SRD_AUX_CTL _MMIO(0x64810) +#define _SRD_AUX_CTL_A 0x60810 +#define _SRD_AUX_CTL_EDP 0x6f810 +#define EDP_PSR_AUX_CTL(tran) _MMIO_TRANS2(tran, _SRD_AUX_CTL_A) +#define EDP_PSR_AUX_CTL_TIME_OUT_MASK DP_AUX_CH_CTL_TIME_OUT_MASK +#define EDP_PSR_AUX_CTL_MESSAGE_SIZE_MASK DP_AUX_CH_CTL_MESSAGE_SIZE_MASK +#define EDP_PSR_AUX_CTL_PRECHARGE_2US_MASK DP_AUX_CH_CTL_PRECHARGE_2US_MASK +#define EDP_PSR_AUX_CTL_ERROR_INTERRUPT REG_BIT(11) +#define EDP_PSR_AUX_CTL_BIT_CLOCK_2X_MASK DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK + +#define HSW_SRD_AUX_DATA(i) _MMIO(0x64814 + (i) * 4) /* 5 registers */ #define _SRD_AUX_DATA_A 0x60814 #define _SRD_AUX_DATA_EDP 0x6f814 #define EDP_PSR_AUX_DATA(tran, i) _MMIO_TRANS2(tran, _SRD_AUX_DATA_A + (i) * 4) /* 5 registers */ +#define HSW_SRD_STATUS _MMIO(0x64840) #define _SRD_STATUS_A 0x60840 #define _SRD_STATUS_EDP 0x6f840 #define EDP_PSR_STATUS(tran) _MMIO_TRANS2(tran, _SRD_STATUS_A) @@ -107,12 +121,14 @@ #define EDP_PSR_STATUS_SENDING_TP1 REG_BIT(4) #define EDP_PSR_STATUS_IDLE_MASK REG_GENMASK(3, 0) +#define HSW_SRD_PERF_CNT _MMIO(0x64844) #define _SRD_PERF_CNT_A 0x60844 #define _SRD_PERF_CNT_EDP 0x6f844 #define EDP_PSR_PERF_CNT(tran) _MMIO_TRANS2(tran, _SRD_PERF_CNT_A) #define EDP_PSR_PERF_CNT_MASK REG_GENMASK(23, 0) /* PSR_MASK on SKL+ */ +#define HSW_SRD_DEBUG _MMIO(0x64860) #define _SRD_DEBUG_A 0x60860 #define _SRD_DEBUG_EDP 0x6f860 #define EDP_PSR_DEBUG(tran) _MMIO_TRANS2(tran, _SRD_DEBUG_A) diff --git a/drivers/gpu/drm/i915/display/intel_qp_tables.c b/drivers/gpu/drm/i915/display/intel_qp_tables.c index 6e86c0971d24..543cdc46aa1d 100644 --- a/drivers/gpu/drm/i915/display/intel_qp_tables.c +++ b/drivers/gpu/drm/i915/display/intel_qp_tables.c @@ -17,13 +17,17 @@ /* from BPP 6 to 36 in steps of 0.5 */ #define RC_RANGE_QP444_12BPC_MAX_NUM_BPP 61 -/* from BPP 6 to 24 in steps of 0.5 */ +/* For YCbCr420 the bits_per_pixel sent in PPS params + * is double the target bpp. The below values represent + * the target bpp. + */ +/* from BPP 4 to 12 in steps of 0.5 */ #define RC_RANGE_QP420_8BPC_MAX_NUM_BPP 17 -/* from BPP 6 to 30 in steps of 0.5 */ +/* from BPP 4 to 15 in steps of 0.5 */ #define RC_RANGE_QP420_10BPC_MAX_NUM_BPP 23 -/* from BPP 6 to 36 in steps of 0.5 */ +/* from BPP 4 to 18 in steps of 0.5 */ #define RC_RANGE_QP420_12BPC_MAX_NUM_BPP 29 /* diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 21f92123c844..7d25a64698e2 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2097,7 +2097,7 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) const struct edid *edid = drm_edid_raw(drm_edid); /* DDC bus is shared, match EDID to connector type */ - if (edid->input & DRM_EDID_INPUT_DIGITAL) + if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) status = connector_status_connected; else status = connector_status_disconnected; @@ -2752,7 +2752,7 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) __drm_atomic_helper_connector_reset(&sdvo_connector->base.base, &conn_state->base.base); - INIT_LIST_HEAD(&sdvo_connector->base.panel.fixed_modes); + intel_panel_init_alloc(&sdvo_connector->base); return sdvo_connector; } @@ -3313,13 +3313,19 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, return i2c_add_adapter(&sdvo->ddc) == 0; } -static void assert_sdvo_port_valid(const struct drm_i915_private *dev_priv, - enum port port) +static bool is_sdvo_port_valid(struct drm_i915_private *dev_priv, enum port port) { if (HAS_PCH_SPLIT(dev_priv)) - drm_WARN_ON(&dev_priv->drm, port != PORT_B); + return port == PORT_B; else - drm_WARN_ON(&dev_priv->drm, port != PORT_B && port != PORT_C); + return port == PORT_B || port == PORT_C; +} + +static bool assert_sdvo_port_valid(struct drm_i915_private *dev_priv, + enum port port) +{ + return !drm_WARN(&dev_priv->drm, !is_sdvo_port_valid(dev_priv, port), + "Platform does not support SDVO %c\n", port_name(port)); } bool intel_sdvo_init(struct drm_i915_private *dev_priv, @@ -3329,7 +3335,11 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, struct intel_sdvo *intel_sdvo; int i; - assert_sdvo_port_valid(dev_priv, port); + if (!assert_port_valid(dev_priv, port)) + return false; + + if (!assert_sdvo_port_valid(dev_priv, port)) + return false; intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL); if (!intel_sdvo) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index bd9116d2cd76..9d76c2756784 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -53,22 +53,32 @@ static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder) } static void +intel_vdsc_set_min_max_qp(struct drm_dsc_config *vdsc_cfg, int buf, + int bpp) +{ + int bpc = vdsc_cfg->bits_per_component; + + /* Read range_minqp and range_max_qp from qp tables */ + vdsc_cfg->rc_range_params[buf].range_min_qp = + intel_lookup_range_min_qp(bpc, buf, bpp, vdsc_cfg->native_420); + vdsc_cfg->rc_range_params[buf].range_max_qp = + intel_lookup_range_max_qp(bpc, buf, bpp, vdsc_cfg->native_420); +} + +/* + * We are using the method provided in DSC 1.2a C-Model in codec_main.c + * Above method use a common formula to derive values for any combination of DSC + * variables. The formula approach may yield slight differences in the derived PPS + * parameters from the original parameter sets. These differences are not consequential + * to the coding performance because all parameter sets have been shown to produce + * visually lossless quality (provides the same PPS values as + * DSCParameterValuesVESA V1-2 spreadsheet). + */ +static void calculate_rc_params(struct drm_dsc_config *vdsc_cfg) { int bpc = vdsc_cfg->bits_per_component; int bpp = vdsc_cfg->bits_per_pixel >> 4; - static const s8 ofs_und6[] = { - 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 - }; - static const s8 ofs_und8[] = { - 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 - }; - static const s8 ofs_und12[] = { - 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 - }; - static const s8 ofs_und15[] = { - 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 - }; int qp_bpc_modifier = (bpc - 8) * 2; u32 res, buf_i, bpp_i; @@ -78,6 +88,28 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) else vdsc_cfg->first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1); + /* + * According to DSC 1.2 spec in Section 4.1 if native_420 is set: + * -second_line_bpg_offset is 12 in general and equal to 2*(slice_height-1) if slice + * height < 8. + * -second_line_offset_adj is 512 as shown by emperical values to yield best chroma + * preservation in second line. + * -nsl_bpg_offset is calculated as second_line_offset/slice_height -1 then rounded + * up to 16 fractional bits, we left shift second line offset by 11 to preserve 11 + * fractional bits. + */ + if (vdsc_cfg->native_420) { + if (vdsc_cfg->slice_height >= 8) + vdsc_cfg->second_line_bpg_offset = 12; + else + vdsc_cfg->second_line_bpg_offset = + 2 * (vdsc_cfg->slice_height - 1); + + vdsc_cfg->second_line_offset_adj = 512; + vdsc_cfg->nsl_bpg_offset = DIV_ROUND_UP(vdsc_cfg->second_line_bpg_offset << 11, + vdsc_cfg->slice_height - 1); + } + /* Our hw supports only 444 modes as of today */ if (bpp >= 12) vdsc_cfg->initial_offset = 2048; @@ -97,33 +129,88 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg) vdsc_cfg->rc_quant_incr_limit0 = 11 + qp_bpc_modifier; vdsc_cfg->rc_quant_incr_limit1 = 11 + qp_bpc_modifier; - bpp_i = (2 * (bpp - 6)); - for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) { - u8 range_bpg_offset; - - /* Read range_minqp and range_max_qp from qp tables */ - vdsc_cfg->rc_range_params[buf_i].range_min_qp = - intel_lookup_range_min_qp(bpc, buf_i, bpp_i, vdsc_cfg->native_420); - vdsc_cfg->rc_range_params[buf_i].range_max_qp = - intel_lookup_range_max_qp(bpc, buf_i, bpp_i, vdsc_cfg->native_420); - - /* Calculate range_bpg_offset */ - if (bpp <= 6) { - range_bpg_offset = ofs_und6[buf_i]; - } else if (bpp <= 8) { - res = DIV_ROUND_UP(((bpp - 6) * (ofs_und8[buf_i] - ofs_und6[buf_i])), 2); - range_bpg_offset = ofs_und6[buf_i] + res; - } else if (bpp <= 12) { - range_bpg_offset = ofs_und8[buf_i]; - } else if (bpp <= 15) { - res = DIV_ROUND_UP(((bpp - 12) * (ofs_und15[buf_i] - ofs_und12[buf_i])), 3); - range_bpg_offset = ofs_und12[buf_i] + res; - } else { - range_bpg_offset = ofs_und15[buf_i]; + if (vdsc_cfg->native_420) { + static const s8 ofs_und4[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 + }; + static const s8 ofs_und5[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und6[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und8[] = { + 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 + }; + + bpp_i = bpp - 8; + for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) { + u8 range_bpg_offset; + + intel_vdsc_set_min_max_qp(vdsc_cfg, buf_i, bpp_i); + + /* Calculate range_bpg_offset */ + if (bpp <= 8) { + range_bpg_offset = ofs_und4[buf_i]; + } else if (bpp <= 10) { + res = DIV_ROUND_UP(((bpp - 8) * + (ofs_und5[buf_i] - ofs_und4[buf_i])), 2); + range_bpg_offset = ofs_und4[buf_i] + res; + } else if (bpp <= 12) { + res = DIV_ROUND_UP(((bpp - 10) * + (ofs_und6[buf_i] - ofs_und5[buf_i])), 2); + range_bpg_offset = ofs_und5[buf_i] + res; + } else if (bpp <= 16) { + res = DIV_ROUND_UP(((bpp - 12) * + (ofs_und8[buf_i] - ofs_und6[buf_i])), 4); + range_bpg_offset = ofs_und6[buf_i] + res; + } else { + range_bpg_offset = ofs_und8[buf_i]; + } + + vdsc_cfg->rc_range_params[buf_i].range_bpg_offset = + range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK; + } + } else { + static const s8 ofs_und6[] = { + 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 + }; + static const s8 ofs_und8[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und12[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und15[] = { + 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 + }; + + bpp_i = (2 * (bpp - 6)); + for (buf_i = 0; buf_i < DSC_NUM_BUF_RANGES; buf_i++) { + u8 range_bpg_offset; + + intel_vdsc_set_min_max_qp(vdsc_cfg, buf_i, bpp_i); + + /* Calculate range_bpg_offset */ + if (bpp <= 6) { + range_bpg_offset = ofs_und6[buf_i]; + } else if (bpp <= 8) { + res = DIV_ROUND_UP(((bpp - 6) * + (ofs_und8[buf_i] - ofs_und6[buf_i])), 2); + range_bpg_offset = ofs_und6[buf_i] + res; + } else if (bpp <= 12) { + range_bpg_offset = ofs_und8[buf_i]; + } else if (bpp <= 15) { + res = DIV_ROUND_UP(((bpp - 12) * + (ofs_und15[buf_i] - ofs_und12[buf_i])), 3); + range_bpg_offset = ofs_und12[buf_i] + res; + } else { + range_bpg_offset = ofs_und15[buf_i]; + } + + vdsc_cfg->rc_range_params[buf_i].range_bpg_offset = + range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK; } - - vdsc_cfg->rc_range_params[buf_i].range_bpg_offset = - range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK; } } @@ -190,30 +277,12 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config) vdsc_cfg->bits_per_pixel = compressed_bpp << 4; /* - * According to DSC 1.2 specs in Section 4.1 if native_420 is set: - * -We need to double the current bpp. - * -second_line_bpg_offset is 12 in general and equal to 2*(slice_height-1) if slice - * height < 8. - * -second_line_offset_adj is 512 as shown by emperical values to yeild best chroma - * preservation in second line. - * -nsl_bpg_offset is calculated as second_line_offset/slice_height -1 then rounded - * up to 16 fractional bits, we left shift second line offset by 11 to preserve 11 - * fractional bits. + * According to DSC 1.2 specs in Section 4.1 if native_420 is set + * we need to double the current bpp. */ - if (vdsc_cfg->native_420) { + if (vdsc_cfg->native_420) vdsc_cfg->bits_per_pixel <<= 1; - if (vdsc_cfg->slice_height >= 8) - vdsc_cfg->second_line_bpg_offset = 12; - else - vdsc_cfg->second_line_bpg_offset = - 2 * (vdsc_cfg->slice_height - 1); - - vdsc_cfg->second_line_offset_adj = 512; - vdsc_cfg->nsl_bpg_offset = DIV_ROUND_UP(vdsc_cfg->second_line_bpg_offset << 11, - vdsc_cfg->slice_height - 1); - } - vdsc_cfg->bits_per_component = pipe_config->pipe_bpp / 3; drm_dsc_set_rc_buf_thresh(vdsc_cfg); @@ -237,18 +306,6 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config) if (ret) return ret; - - /* - * FIXME: verify that the hardware actually needs these - * modifications rather than them being simple typos. - */ - if (compressed_bpp == 6 && - vdsc_cfg->bits_per_component == 8) - vdsc_cfg->rc_quant_incr_limit1 = 23; - - if (compressed_bpp == 8 && - vdsc_cfg->bits_per_component == 14) - vdsc_cfg->rc_range_params[0].range_bpg_offset = 0; } /* @@ -293,6 +350,16 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder) return POWER_DOMAIN_TRANSCODER_VDSC_PW2; } +int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state) +{ + int num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1; + + if (crtc_state->bigjoiner_pipes) + num_vdsc_instances *= 2; + + return num_vdsc_instances; +} + static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -303,11 +370,8 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) u32 pps_val = 0; u32 rc_buf_thresh_dword[4]; u32 rc_range_params_dword[8]; - u8 num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1; int i = 0; - - if (crtc_state->bigjoiner_pipes) - num_vdsc_instances *= 2; + int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state); /* Populate PICTURE_PARAMETER_SET_0 registers */ pps_val = DSC_VER_MAJ | vdsc_cfg->dsc_version_minor << diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index 8763f00fa7e2..2cc41ff08909 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -22,6 +22,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state); enum intel_display_power_domain intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder); struct intel_crtc *intel_dsc_get_bigjoiner_secondary(const struct intel_crtc *primary_crtc); +int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state); void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_dsc_dp_pps_write(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 6b01a0b68b97..ffc15d278a39 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2174,7 +2174,7 @@ static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915, return false; /* Wa_22011186057 */ - if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) + if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) return false; if (DISPLAY_VER(i915) >= 11) @@ -2196,11 +2196,11 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915, /* Wa_14010477008 */ if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || - IS_TGL_DISPLAY_STEP(i915, STEP_A0, STEP_D0)) + (IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0))) return false; /* Wa_22011186057 */ - if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) + if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) return false; /* Wa_14013215631 */ diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index ae2f3ab3e73d..a96e7d028c5c 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -671,20 +671,6 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) intel_de_posting_read(dev_priv, port_ctrl); } } - -static void intel_dsi_wait_panel_power_cycle(struct intel_dsi *intel_dsi) -{ - ktime_t panel_power_on_time; - s64 panel_power_off_duration; - - panel_power_on_time = ktime_get_boottime(); - panel_power_off_duration = ktime_ms_delta(panel_power_on_time, - intel_dsi->panel_power_off_time); - - if (panel_power_off_duration < (s64)intel_dsi->panel_pwr_cycle_delay) - msleep(intel_dsi->panel_pwr_cycle_delay - panel_power_off_duration); -} - static void intel_dsi_prepare(struct intel_encoder *intel_encoder, const struct intel_crtc_state *pipe_config); static void intel_dsi_unprepare(struct intel_encoder *encoder); @@ -831,8 +817,6 @@ static void bxt_dsi_enable(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder); - intel_crtc_vblank_on(crtc_state); } @@ -943,13 +927,6 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, intel_dsi->panel_power_off_time = ktime_get_boottime(); } -static void intel_dsi_shutdown(struct intel_encoder *encoder) -{ - struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - - intel_dsi_wait_panel_power_cycle(intel_dsi); -} - static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index fd556a076d05..1df74f7aa3dc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -97,8 +97,6 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct * struct drm_i915_private *i915 = to_i915(obj->base.dev); int ret; - dma_resv_assert_held(dma_buf->resv); - if (obj->base.size < vma->vm_end - vma->vm_start) return -EINVAL; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index dfaaa8b66ac3..ffddec1d2a76 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -68,10 +68,8 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) switch (obj->write_domain) { case I915_GEM_DOMAIN_GTT: spin_lock(&obj->vma.lock); - for_each_ggtt_vma(vma, obj) { - if (i915_vma_unset_ggtt_write(vma)) - intel_gt_flush_ggtt_writes(vma->vm->gt); - } + for_each_ggtt_vma(vma, obj) + i915_vma_flush_writes(vma); spin_unlock(&obj->vma.lock); i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index cfd7929587d8..5a687a3686bd 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2229,8 +2229,8 @@ static int i915_reset_gen7_sol_offsets(struct i915_request *rq) u32 *cs; int i; - if (GRAPHICS_VER(rq->engine->i915) != 7 || rq->engine->id != RCS0) { - drm_dbg(&rq->engine->i915->drm, "sol reset is gen7/rcs only\n"); + if (GRAPHICS_VER(rq->i915) != 7 || rq->engine->id != RCS0) { + drm_dbg(&rq->i915->drm, "sol reset is gen7/rcs only\n"); return -EINVAL; } @@ -2691,6 +2691,7 @@ static int eb_select_engine(struct i915_execbuffer *eb) { struct intel_context *ce, *child; + struct intel_gt *gt; unsigned int idx; int err; @@ -2714,10 +2715,17 @@ eb_select_engine(struct i915_execbuffer *eb) } } eb->num_batches = ce->parallel.number_children + 1; + gt = ce->engine->gt; for_each_child(ce, child) intel_context_get(child); - intel_gt_pm_get(ce->engine->gt); + intel_gt_pm_get(gt); + /* + * Keep GT0 active on MTL so that i915_vma_parked() doesn't + * free VMAs while execbuf ioctl is validating VMAs. + */ + if (gt->info.id) + intel_gt_pm_get(to_gt(gt->i915)); if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { err = intel_context_alloc_state(ce); @@ -2756,7 +2764,10 @@ eb_select_engine(struct i915_execbuffer *eb) return err; err: - intel_gt_pm_put(ce->engine->gt); + if (gt->info.id) + intel_gt_pm_put(to_gt(gt->i915)); + + intel_gt_pm_put(gt); for_each_child(ce, child) intel_context_put(child); intel_context_put(ce); @@ -2769,6 +2780,12 @@ eb_put_engine(struct i915_execbuffer *eb) struct intel_context *child; i915_vm_put(eb->context->vm); + /* + * This works in conjunction with eb_select_engine() to prevent + * i915_vma_parked() from interfering while execbuf validates vmas. + */ + if (eb->gt->info.id) + intel_gt_pm_put(to_gt(eb->gt->i915)); intel_gt_pm_put(eb->gt); for_each_child(eb->context, child) intel_context_put(child); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 97ac6fb37958..ef9346ed6d0f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -226,7 +226,7 @@ bool i915_gem_object_can_bypass_llc(struct drm_i915_gem_object *obj) * it, but since i915 takes the stance of always zeroing memory before * handing it to userspace, we need to prevent this. */ - return IS_JSL_EHL(i915); + return (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)); } static void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file) @@ -469,7 +469,7 @@ void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, { struct intel_frontbuffer *front; - front = __intel_frontbuffer_get(obj); + front = i915_gem_object_get_frontbuffer(obj); if (front) { intel_frontbuffer_flush(front, origin); intel_frontbuffer_put(front); @@ -481,7 +481,7 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, { struct intel_frontbuffer *front; - front = __intel_frontbuffer_get(obj); + front = i915_gem_object_get_frontbuffer(obj); if (front) { intel_frontbuffer_invalidate(front, origin); intel_frontbuffer_put(front); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 884a17275b3a..f607b87890dd 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -716,10 +716,6 @@ void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj, void *__must_check i915_gem_object_pin_map_unlocked(struct drm_i915_gem_object *obj, enum i915_map_type type); -enum i915_map_type i915_coherent_map_type(struct drm_i915_private *i915, - struct drm_i915_gem_object *obj, - bool always_coherent); - void __i915_gem_object_flush_map(struct drm_i915_gem_object *obj, unsigned long offset, unsigned long size); @@ -891,4 +887,71 @@ static inline int i915_gem_object_userptr_validate(struct drm_i915_gem_object *o #endif +/** + * i915_gem_object_get_frontbuffer - Get the object's frontbuffer + * @obj: The object whose frontbuffer to get. + * + * Get pointer to object's frontbuffer if such exists. Please note that RCU + * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. + * + * Return: pointer to object's frontbuffer is such exists or NULL + */ +static inline struct intel_frontbuffer * +i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj) +{ + struct intel_frontbuffer *front; + + if (likely(!rcu_access_pointer(obj->frontbuffer))) + return NULL; + + rcu_read_lock(); + do { + front = rcu_dereference(obj->frontbuffer); + if (!front) + break; + + if (unlikely(!kref_get_unless_zero(&front->ref))) + continue; + + if (likely(front == rcu_access_pointer(obj->frontbuffer))) + break; + + intel_frontbuffer_put(front); + } while (1); + rcu_read_unlock(); + + return front; +} + +/** + * i915_gem_object_set_frontbuffer - Set the object's frontbuffer + * @obj: The object whose frontbuffer to set. + * @front: The frontbuffer to set + * + * Set object's frontbuffer pointer. If frontbuffer is already set for the + * object keep it and return it's pointer to the caller. Please note that RCU + * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. This + * function is protected by i915->display.fb_tracking.lock + * + * Return: pointer to frontbuffer which was set. + */ +static inline struct intel_frontbuffer * +i915_gem_object_set_frontbuffer(struct drm_i915_gem_object *obj, + struct intel_frontbuffer *front) +{ + struct intel_frontbuffer *cur = front; + + if (!front) { + RCU_INIT_POINTER(obj->frontbuffer, NULL); + } else if (rcu_access_pointer(obj->frontbuffer)) { + cur = rcu_dereference_protected(obj->frontbuffer, true); + kref_get(&cur->ref); + } else { + drm_gem_object_get(intel_bo_to_drm_bo(obj)); + rcu_assign_pointer(obj->frontbuffer, front); + } + + return cur; +} + #endif diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index e72c57716bee..2292404007c8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -17,6 +17,8 @@ #include "i915_selftest.h" #include "i915_vma_resource.h" +#include "gt/intel_gt_defines.h" + struct drm_i915_gem_object; struct intel_fronbuffer; struct intel_memory_region; @@ -675,7 +677,7 @@ struct drm_i915_gem_object { */ bool dirty:1; - u32 tlb; + u32 tlb[I915_MAX_GT]; } mm; struct { @@ -718,6 +720,9 @@ struct drm_i915_gem_object { }; }; +#define intel_bo_to_drm_bo(bo) (&(bo)->base) +#define intel_bo_to_i915(bo) to_i915(intel_bo_to_drm_bo(bo)->dev) + static inline struct drm_i915_gem_object * to_intel_bo(struct drm_gem_object *gem) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 89fc8ea6bcfc..6b6d22c19411 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -7,7 +7,7 @@ #include <drm/drm_cache.h> #include "gt/intel_gt.h" -#include "gt/intel_gt_pm.h" +#include "gt/intel_tlb.h" #include "i915_drv.h" #include "i915_gem_object.h" @@ -193,13 +193,16 @@ static void unmap_object(struct drm_i915_gem_object *obj, void *ptr) static void flush_tlb_invalidate(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_gt *gt = to_gt(i915); + struct intel_gt *gt; + int id; - if (!obj->mm.tlb) - return; + for_each_gt(gt, i915, id) { + if (!obj->mm.tlb[id]) + return; - intel_gt_invalidate_tlb(gt, obj->mm.tlb); - obj->mm.tlb = 0; + intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]); + obj->mm.tlb[id] = 0; + } } struct sg_table * @@ -465,21 +468,6 @@ void *i915_gem_object_pin_map_unlocked(struct drm_i915_gem_object *obj, return ret; } -enum i915_map_type i915_coherent_map_type(struct drm_i915_private *i915, - struct drm_i915_gem_object *obj, - bool always_coherent) -{ - /* - * Wa_22016122933: always return I915_MAP_WC for MTL - */ - if (i915_gem_object_is_lmem(obj) || IS_METEORLAKE(i915)) - return I915_MAP_WC; - if (HAS_LLC(i915) || always_coherent) - return I915_MAP_WB; - else - return I915_MAP_WC; -} - void __i915_gem_object_flush_map(struct drm_i915_gem_object *obj, unsigned long offset, unsigned long size) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 3b094d36a0b0..1a766d8e7cce 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -892,7 +892,7 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, } else { resource_size_t lmem_range; - lmem_range = intel_gt_mcr_read_any(&i915->gt0, XEHP_TILE0_ADDR_RANGE) & 0xFFFF; + lmem_range = intel_gt_mcr_read_any(to_gt(i915), XEHP_TILE0_ADDR_RANGE) & 0xFFFF; lmem_size = lmem_range >> XEHP_TILE_LMEM_RANGE_SHIFT; lmem_size *= SZ_1G; } @@ -974,3 +974,39 @@ bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj) { return obj->ops == &i915_gem_object_stolen_ops; } + +bool i915_gem_stolen_initialized(const struct drm_i915_private *i915) +{ + return drm_mm_initialized(&i915->mm.stolen); +} + +u64 i915_gem_stolen_area_address(const struct drm_i915_private *i915) +{ + return i915->dsm.stolen.start; +} + +u64 i915_gem_stolen_area_size(const struct drm_i915_private *i915) +{ + return resource_size(&i915->dsm.stolen); +} + +u64 i915_gem_stolen_node_address(const struct drm_i915_private *i915, + const struct drm_mm_node *node) +{ + return i915->dsm.stolen.start + i915_gem_stolen_node_offset(node); +} + +bool i915_gem_stolen_node_allocated(const struct drm_mm_node *node) +{ + return drm_mm_node_allocated(node); +} + +u64 i915_gem_stolen_node_offset(const struct drm_mm_node *node) +{ + return node->start; +} + +u64 i915_gem_stolen_node_size(const struct drm_mm_node *node) +{ + return node->size; +} diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h index d5005a39d130..258381d1c054 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h @@ -12,6 +12,8 @@ struct drm_i915_private; struct drm_mm_node; struct drm_i915_gem_object; +#define i915_stolen_fb drm_mm_node + int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node, u64 size, unsigned alignment); @@ -36,4 +38,15 @@ bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj); #define I915_GEM_STOLEN_BIAS SZ_128K +bool i915_gem_stolen_initialized(const struct drm_i915_private *i915); +u64 i915_gem_stolen_area_address(const struct drm_i915_private *i915); +u64 i915_gem_stolen_area_size(const struct drm_i915_private *i915); + +u64 i915_gem_stolen_node_address(const struct drm_i915_private *i915, + const struct drm_mm_node *node); + +bool i915_gem_stolen_node_allocated(const struct drm_mm_node *node); +u64 i915_gem_stolen_node_offset(const struct drm_mm_node *node); +u64 i915_gem_stolen_node_size(const struct drm_mm_node *node); + #endif /* __I915_GEM_STOLEN_H__ */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index 4a33ad2d122b..d4b918fb11ce 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -186,7 +186,7 @@ i915_gem_object_wait(struct drm_i915_gem_object *obj, static inline unsigned long nsecs_to_jiffies_timeout(const u64 n) { /* nsecs_to_jiffies64() does not guard against overflow */ - if (NSEC_PER_SEC % HZ && + if ((NSEC_PER_SEC % HZ) != 0 && div_u64(n, NSEC_PER_SEC) >= MAX_JIFFY_OFFSET / HZ) return MAX_JIFFY_OFFSET; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index df6c9a84252c..6b9f6cf50bf6 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1246,8 +1246,10 @@ static int igt_write_huge(struct drm_i915_private *i915, * times in succession a possibility by enlarging the permutation array. */ order = i915_random_order(count * count, &prng); - if (!order) - return -ENOMEM; + if (!order) { + err = -ENOMEM; + goto out; + } max_page_size = rounddown_pow_of_two(obj->mm.page_sizes.sg); max = div_u64(max - size, max_page_size); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c index a93a90b15907..d8f4a10d71de 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c @@ -13,12 +13,12 @@ #include "selftests/igt_spinner.h" static int igt_fill_check_buffer(struct drm_i915_gem_object *obj, + struct intel_gt *gt, bool fill) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); unsigned int i, count = obj->base.size / sizeof(u32); enum i915_map_type map_type = - i915_coherent_map_type(i915, obj, false); + intel_gt_coherent_map_type(gt, obj, false); u32 *cur; int err = 0; @@ -66,7 +66,7 @@ static int igt_create_migrate(struct intel_gt *gt, enum intel_region_id src, if (err) continue; - err = igt_fill_check_buffer(obj, true); + err = igt_fill_check_buffer(obj, gt, true); if (err) continue; @@ -86,7 +86,7 @@ static int igt_create_migrate(struct intel_gt *gt, enum intel_region_id src, if (err) continue; - err = igt_fill_check_buffer(obj, false); + err = igt_fill_check_buffer(obj, gt, false); } i915_gem_object_put(obj); @@ -233,7 +233,7 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt, continue; if (!vma) { - err = igt_fill_check_buffer(obj, true); + err = igt_fill_check_buffer(obj, gt, true); if (err) continue; } @@ -276,7 +276,7 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt, if (err) goto out_unlock; } else { - err = igt_fill_check_buffer(obj, false); + err = igt_fill_check_buffer(obj, gt, false); } out_unlock: diff --git a/drivers/gpu/drm/i915/gt/gen2_engine_cs.c b/drivers/gpu/drm/i915/gt/gen2_engine_cs.c index 1c82caf525c3..8fe0499308ff 100644 --- a/drivers/gpu/drm/i915/gt/gen2_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen2_engine_cs.c @@ -76,7 +76,7 @@ int gen4_emit_flush_rcs(struct i915_request *rq, u32 mode) cmd = MI_FLUSH; if (mode & EMIT_INVALIDATE) { cmd |= MI_EXE_FLUSH; - if (IS_G4X(rq->engine->i915) || GRAPHICS_VER(rq->engine->i915) == 5) + if (IS_G4X(rq->i915) || GRAPHICS_VER(rq->i915) == 5) cmd |= MI_INVALIDATE_ISP; } diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 23857cc08eca..a4ff55aa5e55 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -39,11 +39,11 @@ int gen8_emit_flush_rcs(struct i915_request *rq, u32 mode) * On GEN9: before VF_CACHE_INVALIDATE we need to emit a NULL * pipe control. */ - if (GRAPHICS_VER(rq->engine->i915) == 9) + if (GRAPHICS_VER(rq->i915) == 9) vf_flush_wa = true; /* WaForGAMHang:kbl */ - if (IS_KBL_GRAPHICS_STEP(rq->engine->i915, 0, STEP_C0)) + if (IS_KABYLAKE(rq->i915) && IS_GRAPHICS_STEP(rq->i915, 0, STEP_C0)) dc_flush_wa = true; } @@ -165,14 +165,60 @@ static u32 preparser_disable(bool state) return MI_ARB_CHECK | 1 << 8 | state; } -u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg) +static i915_reg_t gen12_get_aux_inv_reg(struct intel_engine_cs *engine) { - u32 gsi_offset = gt->uncore->gsi_offset; + switch (engine->id) { + case RCS0: + return GEN12_CCS_AUX_INV; + case BCS0: + return GEN12_BCS0_AUX_INV; + case VCS0: + return GEN12_VD0_AUX_INV; + case VCS2: + return GEN12_VD2_AUX_INV; + case VECS0: + return GEN12_VE0_AUX_INV; + case CCS0: + return GEN12_CCS0_AUX_INV; + default: + return INVALID_MMIO_REG; + } +} + +static bool gen12_needs_ccs_aux_inv(struct intel_engine_cs *engine) +{ + i915_reg_t reg = gen12_get_aux_inv_reg(engine); + + if (IS_PONTEVECCHIO(engine->i915)) + return false; + + /* + * So far platforms supported by i915 having flat ccs do not require + * AUX invalidation. Check also whether the engine requires it. + */ + return i915_mmio_reg_valid(reg) && !HAS_FLAT_CCS(engine->i915); +} + +u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs) +{ + i915_reg_t inv_reg = gen12_get_aux_inv_reg(engine); + u32 gsi_offset = engine->gt->uncore->gsi_offset; + + if (!gen12_needs_ccs_aux_inv(engine)) + return cs; *cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN; *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset; *cs++ = AUX_INV; - *cs++ = MI_NOOP; + + *cs++ = MI_SEMAPHORE_WAIT_TOKEN | + MI_SEMAPHORE_REGISTER_POLL | + MI_SEMAPHORE_POLL | + MI_SEMAPHORE_SAD_EQ_SDD; + *cs++ = 0; + *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset; + *cs++ = 0; + *cs++ = 0; return cs; } @@ -180,8 +226,8 @@ u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv static int mtl_dummy_pipe_control(struct i915_request *rq) { /* Wa_14016712196 */ - if (IS_MTL_GRAPHICS_STEP(rq->engine->i915, M, STEP_A0, STEP_B0) || - IS_MTL_GRAPHICS_STEP(rq->engine->i915, P, STEP_A0, STEP_B0)) { + if (IS_MTL_GRAPHICS_STEP(rq->i915, M, STEP_A0, STEP_B0) || + IS_MTL_GRAPHICS_STEP(rq->i915, P, STEP_A0, STEP_B0)) { u32 *cs; /* dummy PIPE_CONTROL + depth flush */ @@ -202,8 +248,13 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) { struct intel_engine_cs *engine = rq->engine; - if (mode & EMIT_FLUSH) { - u32 flags = 0; + /* + * On Aux CCS platforms the invalidation of the Aux + * table requires quiescing memory traffic beforehand + */ + if (mode & EMIT_FLUSH || gen12_needs_ccs_aux_inv(engine)) { + u32 bit_group_0 = 0; + u32 bit_group_1 = 0; int err; u32 *cs; @@ -211,32 +262,40 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) if (err) return err; - flags |= PIPE_CONTROL_TILE_CACHE_FLUSH; - flags |= PIPE_CONTROL_FLUSH_L3; - flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; + bit_group_0 |= PIPE_CONTROL0_HDC_PIPELINE_FLUSH; + + /* + * When required, in MTL and beyond platforms we + * need to set the CCS_FLUSH bit in the pipe control + */ + if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70)) + bit_group_0 |= PIPE_CONTROL_CCS_FLUSH; + + bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; + bit_group_1 |= PIPE_CONTROL_FLUSH_L3; + bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; + bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; /* Wa_1409600907:tgl,adl-p */ - flags |= PIPE_CONTROL_DEPTH_STALL; - flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; - flags |= PIPE_CONTROL_FLUSH_ENABLE; + bit_group_1 |= PIPE_CONTROL_DEPTH_STALL; + bit_group_1 |= PIPE_CONTROL_DC_FLUSH_ENABLE; + bit_group_1 |= PIPE_CONTROL_FLUSH_ENABLE; - flags |= PIPE_CONTROL_STORE_DATA_INDEX; - flags |= PIPE_CONTROL_QW_WRITE; + bit_group_1 |= PIPE_CONTROL_STORE_DATA_INDEX; + bit_group_1 |= PIPE_CONTROL_QW_WRITE; - flags |= PIPE_CONTROL_CS_STALL; + bit_group_1 |= PIPE_CONTROL_CS_STALL; if (!HAS_3D_PIPELINE(engine->i915)) - flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS; + bit_group_1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS; else if (engine->class == COMPUTE_CLASS) - flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; + bit_group_1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; cs = intel_ring_begin(rq, 6); if (IS_ERR(cs)) return PTR_ERR(cs); - cs = gen12_emit_pipe_control(cs, - PIPE_CONTROL0_HDC_PIPELINE_FLUSH, - flags, LRC_PPHWSP_SCRATCH_ADDR); + cs = gen12_emit_pipe_control(cs, bit_group_0, bit_group_1, + LRC_PPHWSP_SCRATCH_ADDR); intel_ring_advance(rq, cs); } @@ -267,10 +326,9 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) else if (engine->class == COMPUTE_CLASS) flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; - if (!HAS_FLAT_CCS(rq->engine->i915)) - count = 8 + 4; - else - count = 8; + count = 8; + if (gen12_needs_ccs_aux_inv(rq->engine)) + count += 8; cs = intel_ring_begin(rq, count); if (IS_ERR(cs)) @@ -285,11 +343,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR); - if (!HAS_FLAT_CCS(rq->engine->i915)) { - /* hsdes: 1809175790 */ - cs = gen12_emit_aux_table_inv(rq->engine->gt, - cs, GEN12_GFX_CCS_AUX_NV); - } + cs = gen12_emit_aux_table_inv(engine, cs); *cs++ = preparser_disable(false); intel_ring_advance(rq, cs); @@ -300,21 +354,14 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) { - intel_engine_mask_t aux_inv = 0; - u32 cmd, *cs; + u32 cmd = 4; + u32 *cs; - cmd = 4; if (mode & EMIT_INVALIDATE) { cmd += 2; - if (!HAS_FLAT_CCS(rq->engine->i915) && - (rq->engine->class == VIDEO_DECODE_CLASS || - rq->engine->class == VIDEO_ENHANCEMENT_CLASS)) { - aux_inv = rq->engine->mask & - ~GENMASK(_BCS(I915_MAX_BCS - 1), BCS0); - if (aux_inv) - cmd += 4; - } + if (gen12_needs_ccs_aux_inv(rq->engine)) + cmd += 8; } cs = intel_ring_begin(rq, cmd); @@ -338,6 +385,10 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) cmd |= MI_INVALIDATE_TLB; if (rq->engine->class == VIDEO_DECODE_CLASS) cmd |= MI_INVALIDATE_BSD; + + if (gen12_needs_ccs_aux_inv(rq->engine) && + rq->engine->class == COPY_ENGINE_CLASS) + cmd |= MI_FLUSH_DW_CCS; } *cs++ = cmd; @@ -345,14 +396,7 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) *cs++ = 0; /* upper addr */ *cs++ = 0; /* value */ - if (aux_inv) { /* hsdes: 1809175790 */ - if (rq->engine->class == VIDEO_DECODE_CLASS) - cs = gen12_emit_aux_table_inv(rq->engine->gt, - cs, GEN12_VD0_AUX_NV); - else - cs = gen12_emit_aux_table_inv(rq->engine->gt, - cs, GEN12_VE0_AUX_NV); - } + cs = gen12_emit_aux_table_inv(rq->engine, cs); if (mode & EMIT_INVALIDATE) *cs++ = preparser_disable(false); @@ -754,7 +798,7 @@ u32 *gen12_emit_fini_breadcrumb_xcs(struct i915_request *rq, u32 *cs) u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs) { - struct drm_i915_private *i915 = rq->engine->i915; + struct drm_i915_private *i915 = rq->i915; u32 flags = (PIPE_CONTROL_CS_STALL | PIPE_CONTROL_TLB_INVALIDATE | PIPE_CONTROL_TILE_CACHE_FLUSH | @@ -775,7 +819,7 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs) /* Wa_1409600907 */ flags |= PIPE_CONTROL_DEPTH_STALL; - if (!HAS_3D_PIPELINE(rq->engine->i915)) + if (!HAS_3D_PIPELINE(rq->i915)) flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS; else if (rq->engine->class == COMPUTE_CLASS) flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h index 655e5c00ddc2..867ba697aceb 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h @@ -13,6 +13,7 @@ #include "intel_gt_regs.h" #include "intel_gpu_commands.h" +struct intel_engine_cs; struct intel_gt; struct i915_request; @@ -46,28 +47,32 @@ u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); -u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg); +u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs); static inline u32 * -__gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) +__gen8_emit_pipe_control(u32 *batch, u32 bit_group_0, + u32 bit_group_1, u32 offset) { memset(batch, 0, 6 * sizeof(u32)); - batch[0] = GFX_OP_PIPE_CONTROL(6) | flags0; - batch[1] = flags1; + batch[0] = GFX_OP_PIPE_CONTROL(6) | bit_group_0; + batch[1] = bit_group_1; batch[2] = offset; return batch + 6; } -static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset) +static inline u32 *gen8_emit_pipe_control(u32 *batch, + u32 bit_group_1, u32 offset) { - return __gen8_emit_pipe_control(batch, 0, flags, offset); + return __gen8_emit_pipe_control(batch, 0, bit_group_1, offset); } -static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) +static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 bit_group_0, + u32 bit_group_1, u32 offset) { - return __gen8_emit_pipe_control(batch, flags0, flags1, offset); + return __gen8_emit_pipe_control(batch, bit_group_0, + bit_group_1, offset); } static inline u32 * diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 0aff5bb13c53..ee15486fed0d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1333,6 +1333,7 @@ static int measure_breadcrumb_dw(struct intel_context *ce) if (!frame) return -ENOMEM; + frame->rq.i915 = engine->i915; frame->rq.engine = engine; frame->rq.context = ce; rcu_assign_pointer(frame->rq.timeline, ce->timeline); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 21af0ec52223..b538b5c04948 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -39,7 +39,7 @@ static void dbg_poison_ce(struct intel_context *ce) if (ce->state) { struct drm_i915_gem_object *obj = ce->state->obj; - int type = i915_coherent_map_type(ce->engine->i915, obj, true); + int type = intel_gt_coherent_map_type(ce->engine->gt, obj, true); void *map; if (!i915_gem_object_trylock(obj, NULL)) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 2ebd937f3b4c..8a641bcf777c 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2718,7 +2718,7 @@ static int emit_pdps(struct i915_request *rq) int err, i; u32 *cs; - GEM_BUG_ON(intel_vgpu_active(rq->engine->i915)); + GEM_BUG_ON(intel_vgpu_active(rq->i915)); /* * Beware ye of the dragons, this sequence is magic! @@ -3556,16 +3556,16 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine) lrc_init_wa_ctx(engine); if (HAS_LOGICAL_RING_ELSQ(i915)) { - execlists->submit_reg = uncore->regs + + execlists->submit_reg = intel_uncore_regs(uncore) + i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(base)); - execlists->ctrl_reg = uncore->regs + + execlists->ctrl_reg = intel_uncore_regs(uncore) + i915_mmio_reg_offset(RING_EXECLIST_CONTROL(base)); engine->fw_domain = intel_uncore_forcewake_for_reg(engine->uncore, RING_EXECLIST_CONTROL(engine->mmio_base), FW_REG_WRITE); } else { - execlists->submit_reg = uncore->regs + + execlists->submit_reg = intel_uncore_regs(uncore) + i915_mmio_reg_offset(RING_ELSP(base)); } diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index 37d0b0fe791d..40371b8a9bbb 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -818,7 +818,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, if (obj->bit_17 == NULL) { obj->bit_17 = bitmap_zalloc(page_count, GFP_KERNEL); if (obj->bit_17 == NULL) { - drm_err(&to_i915(obj->base.dev)->drm, + drm_err(obj->base.dev, "Failed to allocate memory for bit 17 record\n"); return; } diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h index 5d143e2a8db0..2bd8d98d2110 100644 --- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h +++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h @@ -121,6 +121,7 @@ #define MI_SEMAPHORE_TARGET(engine) ((engine)<<15) #define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */ #define MI_SEMAPHORE_WAIT_TOKEN MI_INSTR(0x1c, 3) /* GEN12+ */ +#define MI_SEMAPHORE_REGISTER_POLL (1 << 16) #define MI_SEMAPHORE_POLL (1 << 15) #define MI_SEMAPHORE_SAD_GT_SDD (0 << 12) #define MI_SEMAPHORE_SAD_GTE_SDD (1 << 12) @@ -299,6 +300,7 @@ #define PIPE_CONTROL_QW_WRITE (1<<14) #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) #define PIPE_CONTROL_DEPTH_STALL (1<<13) +#define PIPE_CONTROL_CCS_FLUSH (1<<13) /* MTL+ */ #define PIPE_CONTROL_WRITE_FLUSH (1<<12) #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on ILK */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 7a008e829d4d..449f0b7fc843 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -33,6 +33,7 @@ #include "intel_rps.h" #include "intel_sa_media.h" #include "intel_gt_sysfs.h" +#include "intel_tlb.h" #include "intel_uncore.h" #include "shmem_utils.h" @@ -50,8 +51,7 @@ void intel_gt_common_init_early(struct intel_gt *gt) intel_gt_init_reset(gt); intel_gt_init_requests(gt); intel_gt_init_timelines(gt); - mutex_init(>->tlb.invalidate_lock); - seqcount_mutex_init(>->tlb.seqno, >->tlb.invalidate_lock); + intel_gt_init_tlb(gt); intel_gt_pm_init_early(gt); intel_wopcm_init_early(>->wopcm); @@ -179,7 +179,7 @@ int intel_gt_init_hw(struct intel_gt *gt) if (IS_HASWELL(i915)) intel_uncore_write(uncore, HSW_MI_PREDICATE_RESULT_2, - IS_HSW_GT3(i915) ? + IS_HASWELL_GT3(i915) ? LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); /* Apply the GT workarounds... */ @@ -466,7 +466,7 @@ static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size) obj = i915_gem_object_create_lmem(i915, size, I915_BO_ALLOC_VOLATILE | I915_BO_ALLOC_GPU_ONLY); - if (IS_ERR(obj)) + if (IS_ERR(obj) && !IS_METEORLAKE(i915)) /* Wa_22018444074 */ obj = i915_gem_object_create_stolen(i915, size); if (IS_ERR(obj)) obj = i915_gem_object_create_internal(i915, size); @@ -846,7 +846,7 @@ void intel_gt_driver_late_release_all(struct drm_i915_private *i915) intel_gt_fini_requests(gt); intel_gt_fini_reset(gt); intel_gt_fini_timelines(gt); - mutex_destroy(>->tlb.invalidate_lock); + intel_gt_fini_tlb(gt); intel_engines_free(gt); } } @@ -887,7 +887,7 @@ static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr) int intel_gt_probe_all(struct drm_i915_private *i915) { struct pci_dev *pdev = to_pci_dev(i915->drm.dev); - struct intel_gt *gt = &i915->gt0; + struct intel_gt *gt = to_gt(i915); const struct intel_gt_definition *gtdef; phys_addr_t phys_addr; unsigned int mmio_bar; @@ -904,7 +904,7 @@ int intel_gt_probe_all(struct drm_i915_private *i915) */ gt->i915 = i915; gt->name = "Primary GT"; - gt->info.engine_mask = RUNTIME_INFO(i915)->platform_engine_mask; + gt->info.engine_mask = INTEL_INFO(i915)->platform_engine_mask; gt_dbg(gt, "Setting up %s\n", gt->name); ret = intel_gt_tile_setup(gt, phys_addr); @@ -1004,136 +1004,18 @@ void intel_gt_info_print(const struct intel_gt_info *info, intel_sseu_dump(&info->sseu, p); } -/* - * HW architecture suggest typical invalidation time at 40us, - * with pessimistic cases up to 100us and a recommendation to - * cap at 1ms. We go a bit higher just in case. - */ -#define TLB_INVAL_TIMEOUT_US 100 -#define TLB_INVAL_TIMEOUT_MS 4 - -/* - * On Xe_HP the TLB invalidation registers are located at the same MMIO offsets - * but are now considered MCR registers. Since they exist within a GAM range, - * the primary instance of the register rolls up the status from each unit. - */ -static int wait_for_invalidate(struct intel_engine_cs *engine) +enum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt, + struct drm_i915_gem_object *obj, + bool always_coherent) { - if (engine->tlb_inv.mcr) - return intel_gt_mcr_wait_for_reg(engine->gt, - engine->tlb_inv.reg.mcr_reg, - engine->tlb_inv.done, - 0, - TLB_INVAL_TIMEOUT_US, - TLB_INVAL_TIMEOUT_MS); - else - return __intel_wait_for_register_fw(engine->gt->uncore, - engine->tlb_inv.reg.reg, - engine->tlb_inv.done, - 0, - TLB_INVAL_TIMEOUT_US, - TLB_INVAL_TIMEOUT_MS, - NULL); -} - -static void mmio_invalidate_full(struct intel_gt *gt) -{ - struct drm_i915_private *i915 = gt->i915; - struct intel_uncore *uncore = gt->uncore; - struct intel_engine_cs *engine; - intel_engine_mask_t awake, tmp; - enum intel_engine_id id; - unsigned long flags; - - if (GRAPHICS_VER(i915) < 8) - return; - - intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); - - intel_gt_mcr_lock(gt, &flags); - spin_lock(&uncore->lock); /* serialise invalidate with GT reset */ - - awake = 0; - for_each_engine(engine, gt, id) { - if (!intel_engine_pm_is_awake(engine)) - continue; - - if (engine->tlb_inv.mcr) - intel_gt_mcr_multicast_write_fw(gt, - engine->tlb_inv.reg.mcr_reg, - engine->tlb_inv.request); - else - intel_uncore_write_fw(uncore, - engine->tlb_inv.reg.reg, - engine->tlb_inv.request); - - awake |= engine->mask; - } - - GT_TRACE(gt, "invalidated engines %08x\n", awake); - - /* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */ - if (awake && - (IS_TIGERLAKE(i915) || - IS_DG1(i915) || - IS_ROCKETLAKE(i915) || - IS_ALDERLAKE_S(i915) || - IS_ALDERLAKE_P(i915))) - intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1); - - spin_unlock(&uncore->lock); - intel_gt_mcr_unlock(gt, flags); - - for_each_engine_masked(engine, gt, awake, tmp) { - if (wait_for_invalidate(engine)) - gt_err_ratelimited(gt, - "%s TLB invalidation did not complete in %ums!\n", - engine->name, TLB_INVAL_TIMEOUT_MS); - } - /* - * Use delayed put since a) we mostly expect a flurry of TLB - * invalidations so it is good to avoid paying the forcewake cost and - * b) it works around a bug in Icelake which cannot cope with too rapid - * transitions. + * Wa_22016122933: always return I915_MAP_WC for Media + * version 13.0 when the object is on the Media GT */ - intel_uncore_forcewake_put_delayed(uncore, FORCEWAKE_ALL); -} - -static bool tlb_seqno_passed(const struct intel_gt *gt, u32 seqno) -{ - u32 cur = intel_gt_tlb_seqno(gt); - - /* Only skip if a *full* TLB invalidate barrier has passed */ - return (s32)(cur - ALIGN(seqno, 2)) > 0; -} - -void intel_gt_invalidate_tlb(struct intel_gt *gt, u32 seqno) -{ - intel_wakeref_t wakeref; - - if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) - return; - - if (intel_gt_is_wedged(gt)) - return; - - if (tlb_seqno_passed(gt, seqno)) - return; - - with_intel_gt_pm_if_awake(gt, wakeref) { - mutex_lock(>->tlb.invalidate_lock); - if (tlb_seqno_passed(gt, seqno)) - goto unlock; - - mmio_invalidate_full(gt); - - write_seqcount_invalidate(>->tlb.seqno); -unlock: - mutex_unlock(>->tlb.invalidate_lock); - } + if (i915_gem_object_is_lmem(obj) || intel_gt_needs_wa_22016122933(gt)) + return I915_MAP_WC; + if (HAS_LLC(gt->i915) || always_coherent) + return I915_MAP_WB; + else + return I915_MAP_WC; } - -#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) -#include "selftest_tlb.c" -#endif diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index d2f4fbde5f9f..6c34547b58b5 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -6,6 +6,7 @@ #ifndef __INTEL_GT__ #define __INTEL_GT__ +#include "i915_drv.h" #include "intel_engine_types.h" #include "intel_gt_types.h" #include "intel_reset.h" @@ -24,6 +25,11 @@ static inline bool gt_is_root(struct intel_gt *gt) return !gt->info.id; } +static inline bool intel_gt_needs_wa_22016122933(struct intel_gt *gt) +{ + return MEDIA_VER_FULL(gt->i915) == IP_VER(13, 0) && gt->type == GT_MEDIA; +} + static inline struct intel_gt *uc_to_gt(struct intel_uc *uc) { return container_of(uc, struct intel_gt, uc); @@ -107,16 +113,8 @@ void intel_gt_info_print(const struct intel_gt_info *info, void intel_gt_watchdog_work(struct work_struct *work); -static inline u32 intel_gt_tlb_seqno(const struct intel_gt *gt) -{ - return seqprop_sequence(>->tlb.seqno); -} - -static inline u32 intel_gt_next_invalidate_tlb_full(const struct intel_gt *gt) -{ - return intel_gt_tlb_seqno(gt) | 1; -} - -void intel_gt_invalidate_tlb(struct intel_gt *gt, u32 seqno); +enum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt, + struct drm_i915_gem_object *obj, + bool always_coherent); #endif /* __INTEL_GT_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_defines.h b/drivers/gpu/drm/i915/gt/intel_gt_defines.h new file mode 100644 index 000000000000..5017788bac8f --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_defines.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_GT_DEFINES__ +#define __INTEL_GT_DEFINES__ + +#define I915_MAX_GT 2 + +#endif diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index 62fd00c9e519..77fb57223465 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -31,7 +31,7 @@ static u32 gen11_gt_engine_identity(struct intel_gt *gt, const unsigned int bank, const unsigned int bit) { - void __iomem * const regs = gt->uncore->regs; + void __iomem * const regs = intel_uncore_regs(gt->uncore); u32 timeout_ts; u32 ident; @@ -148,7 +148,7 @@ gen11_gt_identity_handler(struct intel_gt *gt, const u32 identity) static void gen11_gt_bank_handler(struct intel_gt *gt, const unsigned int bank) { - void __iomem * const regs = gt->uncore->regs; + void __iomem * const regs = intel_uncore_regs(gt->uncore); unsigned long intr_dw; unsigned int bit; @@ -183,7 +183,7 @@ void gen11_gt_irq_handler(struct intel_gt *gt, const u32 master_ctl) bool gen11_gt_reset_one_iir(struct intel_gt *gt, const unsigned int bank, const unsigned int bit) { - void __iomem * const regs = gt->uncore->regs; + void __iomem * const regs = intel_uncore_regs(gt->uncore); u32 dw; lockdep_assert_held(gt->irq_lock); @@ -404,7 +404,7 @@ void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir) void gen8_gt_irq_handler(struct intel_gt *gt, u32 master_ctl) { - void __iomem * const regs = gt->uncore->regs; + void __iomem * const regs = intel_uncore_regs(gt->uncore); u32 iir; if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 718cb2c80f79..2cdfb2f713d0 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -332,9 +332,11 @@ #define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) #define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index) * 4) #define BSD_HWS_PGA_GEN7 _MMIO(0x4180) -#define GEN12_GFX_CCS_AUX_NV _MMIO(0x4208) -#define GEN12_VD0_AUX_NV _MMIO(0x4218) -#define GEN12_VD1_AUX_NV _MMIO(0x4228) + +#define GEN12_CCS_AUX_INV _MMIO(0x4208) +#define GEN12_VD0_AUX_INV _MMIO(0x4218) +#define GEN12_VE0_AUX_INV _MMIO(0x4238) +#define GEN12_BCS0_AUX_INV _MMIO(0x4248) #define GEN8_RTCR _MMIO(0x4260) #define GEN8_M1TCR _MMIO(0x4264) @@ -342,14 +344,12 @@ #define GEN8_BTCR _MMIO(0x426c) #define GEN8_VTCR _MMIO(0x4270) -#define GEN12_VD2_AUX_NV _MMIO(0x4298) -#define GEN12_VD3_AUX_NV _MMIO(0x42a8) -#define GEN12_VE0_AUX_NV _MMIO(0x4238) - #define BLT_HWS_PGA_GEN7 _MMIO(0x4280) -#define GEN12_VE1_AUX_NV _MMIO(0x42b8) +#define GEN12_VD2_AUX_INV _MMIO(0x4298) +#define GEN12_CCS0_AUX_INV _MMIO(0x42c8) #define AUX_INV REG_BIT(0) + #define VEBOX_HWS_PGA_GEN7 _MMIO(0x4380) #define GEN12_AUX_ERR_DBG _MMIO(0x43f4) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c index ee2b44f896a2..f0dea54880af 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -701,6 +701,80 @@ static const struct attribute *media_perf_power_attrs[] = { }; static ssize_t +rps_up_threshold_pct_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); + struct intel_rps *rps = >->rps; + + return sysfs_emit(buf, "%u\n", intel_rps_get_up_threshold(rps)); +} + +static ssize_t +rps_up_threshold_pct_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); + struct intel_rps *rps = >->rps; + int ret; + u8 val; + + ret = kstrtou8(buf, 10, &val); + if (ret) + return ret; + + ret = intel_rps_set_up_threshold(rps, val); + + return ret == 0 ? count : ret; +} + +static struct kobj_attribute rps_up_threshold_pct = + __ATTR(rps_up_threshold_pct, + 0664, + rps_up_threshold_pct_show, + rps_up_threshold_pct_store); + +static ssize_t +rps_down_threshold_pct_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); + struct intel_rps *rps = >->rps; + + return sysfs_emit(buf, "%u\n", intel_rps_get_down_threshold(rps)); +} + +static ssize_t +rps_down_threshold_pct_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); + struct intel_rps *rps = >->rps; + int ret; + u8 val; + + ret = kstrtou8(buf, 10, &val); + if (ret) + return ret; + + ret = intel_rps_set_down_threshold(rps, val); + + return ret == 0 ? count : ret; +} + +static struct kobj_attribute rps_down_threshold_pct = + __ATTR(rps_down_threshold_pct, + 0664, + rps_down_threshold_pct_show, + rps_down_threshold_pct_store); + +static const struct attribute * const gen6_gt_rps_attrs[] = { + &rps_up_threshold_pct.attr, + &rps_down_threshold_pct.attr, + NULL +}; + +static ssize_t default_min_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct intel_gt *gt = kobj_to_gt(kobj->parent); @@ -722,9 +796,37 @@ default_max_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, cha static struct kobj_attribute default_max_freq_mhz = __ATTR(rps_max_freq_mhz, 0444, default_max_freq_mhz_show, NULL); +static ssize_t +default_rps_up_threshold_pct_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct intel_gt *gt = kobj_to_gt(kobj->parent); + + return sysfs_emit(buf, "%u\n", gt->defaults.rps_up_threshold); +} + +static struct kobj_attribute default_rps_up_threshold_pct = +__ATTR(rps_up_threshold_pct, 0444, default_rps_up_threshold_pct_show, NULL); + +static ssize_t +default_rps_down_threshold_pct_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct intel_gt *gt = kobj_to_gt(kobj->parent); + + return sysfs_emit(buf, "%u\n", gt->defaults.rps_down_threshold); +} + +static struct kobj_attribute default_rps_down_threshold_pct = +__ATTR(rps_down_threshold_pct, 0444, default_rps_down_threshold_pct_show, NULL); + static const struct attribute * const rps_defaults_attrs[] = { &default_min_freq_mhz.attr, &default_max_freq_mhz.attr, + &default_rps_up_threshold_pct.attr, + &default_rps_down_threshold_pct.attr, NULL }; @@ -752,6 +854,12 @@ static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj) if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) ret = sysfs_create_file(kobj, vlv_attr); + if (is_object_gt(kobj) && !intel_uc_uses_guc_slpc(>->uc)) { + ret = sysfs_create_files(kobj, gen6_gt_rps_attrs); + if (ret) + return ret; + } + return ret; } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h index f08c2556aa25..def7dd0eb6f1 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h @@ -83,6 +83,9 @@ enum intel_submission_method { struct gt_defaults { u32 min_freq; u32 max_freq; + + u8 rps_up_threshold; + u8 rps_down_threshold; }; enum intel_gt_type { @@ -306,4 +309,6 @@ enum intel_gt_scratch_field { INTEL_GT_SCRATCH_FIELD_COHERENTL3_WA = 256, }; +#define intel_gt_support_legacy_fencing(gt) ((gt)->ggtt->num_fences > 0) + #endif /* __INTEL_GT_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 731d9f2bbc56..13944a14ea2d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -89,7 +89,7 @@ int map_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj) enum i915_map_type type; void *vaddr; - type = i915_coherent_map_type(vm->i915, obj, true); + type = intel_gt_coherent_map_type(vm->gt, obj, true); vaddr = i915_gem_object_pin_map_unlocked(obj, type); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -103,7 +103,7 @@ int map_pt_dma_locked(struct i915_address_space *vm, struct drm_i915_gem_object enum i915_map_type type; void *vaddr; - type = i915_coherent_map_type(vm->i915, obj, true); + type = intel_gt_coherent_map_type(vm->gt, obj, true); vaddr = i915_gem_object_pin_map(obj, type); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index a4ec20aaafe2..957d0aeb0c02 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1092,8 +1092,16 @@ __lrc_alloc_state(struct intel_context *ce, struct intel_engine_cs *engine) obj = i915_gem_object_create_lmem(engine->i915, context_size, I915_BO_ALLOC_PM_VOLATILE); - if (IS_ERR(obj)) + if (IS_ERR(obj)) { obj = i915_gem_object_create_shmem(engine->i915, context_size); + /* + * Wa_22016122933: For Media version 13.0, all Media GT shared + * memory needs to be mapped as WC on CPU side and UC (PAT + * index 2) on GPU side. + */ + if (intel_gt_needs_wa_22016122933(engine->gt)) + i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); + } if (IS_ERR(obj)) return ERR_CAST(obj); @@ -1184,9 +1192,9 @@ lrc_pre_pin(struct intel_context *ce, GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); *vaddr = i915_gem_object_pin_map(ce->state->obj, - i915_coherent_map_type(ce->engine->i915, - ce->state->obj, - false) | + intel_gt_coherent_map_type(ce->engine->gt, + ce->state->obj, + false) | I915_MAP_OVERRIDE); return PTR_ERR_OR_ZERO(*vaddr); @@ -1364,10 +1372,7 @@ gen12_emit_indirect_ctx_rcs(const struct intel_context *ce, u32 *cs) IS_DG2_G11(ce->engine->i915)) cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); - /* hsdes: 1809175790 */ - if (!HAS_FLAT_CCS(ce->engine->i915)) - cs = gen12_emit_aux_table_inv(ce->engine->gt, - cs, GEN12_GFX_CCS_AUX_NV); + cs = gen12_emit_aux_table_inv(ce->engine, cs); /* Wa_16014892111 */ if (IS_MTL_GRAPHICS_STEP(ce->engine->i915, M, STEP_A0, STEP_B0) || @@ -1392,17 +1397,7 @@ gen12_emit_indirect_ctx_xcs(const struct intel_context *ce, u32 *cs) PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); - /* hsdes: 1809175790 */ - if (!HAS_FLAT_CCS(ce->engine->i915)) { - if (ce->engine->class == VIDEO_DECODE_CLASS) - cs = gen12_emit_aux_table_inv(ce->engine->gt, - cs, GEN12_VD0_AUX_NV); - else if (ce->engine->class == VIDEO_ENHANCEMENT_CLASS) - cs = gen12_emit_aux_table_inv(ce->engine->gt, - cs, GEN12_VE0_AUX_NV); - } - - return cs; + return gen12_emit_aux_table_inv(ce->engine, cs); } static void diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c index 6023288b0e2d..576e5ef0289b 100644 --- a/drivers/gpu/drm/i915/gt/intel_migrate.c +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c @@ -366,7 +366,7 @@ static int emit_pte(struct i915_request *rq, u64 offset, int length) { - bool has_64K_pages = HAS_64K_PAGES(rq->engine->i915); + bool has_64K_pages = HAS_64K_PAGES(rq->i915); const u64 encode = rq->context->vm->pte_encode(0, pat_index, is_lmem ? PTE_LM : 0); struct intel_ring *ring = rq->ring; @@ -375,7 +375,7 @@ static int emit_pte(struct i915_request *rq, u32 page_size; u32 *hdr, *cs; - GEM_BUG_ON(GRAPHICS_VER(rq->engine->i915) < 8); + GEM_BUG_ON(GRAPHICS_VER(rq->i915) < 8); page_size = I915_GTT_PAGE_SIZE; dword_length = 0x400; @@ -531,7 +531,7 @@ static int emit_copy_ccs(struct i915_request *rq, u32 dst_offset, u8 dst_access, u32 src_offset, u8 src_access, int size) { - struct drm_i915_private *i915 = rq->engine->i915; + struct drm_i915_private *i915 = rq->i915; int mocs = rq->engine->gt->mocs.uc_index << 1; u32 num_ccs_blks; u32 *cs; @@ -581,7 +581,7 @@ static int emit_copy_ccs(struct i915_request *rq, static int emit_copy(struct i915_request *rq, u32 dst_offset, u32 src_offset, int size) { - const int ver = GRAPHICS_VER(rq->engine->i915); + const int ver = GRAPHICS_VER(rq->i915); u32 instance = rq->engine->instance; u32 *cs; @@ -917,7 +917,7 @@ out_ce: static int emit_clear(struct i915_request *rq, u32 offset, int size, u32 value, bool is_lmem) { - struct drm_i915_private *i915 = rq->engine->i915; + struct drm_i915_private *i915 = rq->i915; int mocs = rq->engine->gt->mocs.uc_index << 1; const int ver = GRAPHICS_VER(i915); int ring_sz; diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index 436756bfbb1a..d07a4f97b943 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -8,6 +8,7 @@ #include "gem/i915_gem_lmem.h" #include "i915_trace.h" +#include "intel_gt.h" #include "intel_gtt.h" #include "gen6_ppgtt.h" #include "gen8_ppgtt.h" @@ -210,8 +211,7 @@ void ppgtt_unbind_vma(struct i915_address_space *vm, return; vm->clear_range(vm, vma_res->start, vma_res->vma_size); - if (vma_res->tlb) - vma_invalidate_tlb(vm, vma_res->tlb); + vma_invalidate_tlb(vm, vma_res->tlb); } static unsigned long pd_count(u64 size, int shift) diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index 2a3217e2890f..f8512aee58a8 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -220,7 +220,7 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) resource_size_t lmem_range; u64 tile_stolen, flat_ccs_base; - lmem_range = intel_gt_mcr_read_any(&i915->gt0, XEHP_TILE0_ADDR_RANGE) & 0xFFFF; + lmem_range = intel_gt_mcr_read_any(to_gt(i915), XEHP_TILE0_ADDR_RANGE) & 0xFFFF; lmem_size = lmem_range >> XEHP_TILE_LMEM_RANGE_SHIFT; lmem_size *= SZ_1G; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index e2152f75ba2e..cc6bd21a3e51 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -35,9 +35,6 @@ #define RESET_MAX_RETRIES 3 -/* XXX How to handle concurrent GGTT updates using tiling registers? */ -#define RESET_UNDER_STOP_MACHINE 0 - static void client_mark_guilty(struct i915_gem_context *ctx, bool banned) { struct drm_i915_file_private *file_priv = ctx->file_priv; diff --git a/drivers/gpu/drm/i915/gt/intel_ring.c b/drivers/gpu/drm/i915/gt/intel_ring.c index fb99143be98e..59da4b7bd262 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring.c +++ b/drivers/gpu/drm/i915/gt/intel_ring.c @@ -13,6 +13,7 @@ #include "intel_engine_regs.h" #include "intel_gpu_commands.h" #include "intel_ring.h" +#include "intel_gt.h" #include "intel_timeline.h" unsigned int intel_ring_update_space(struct intel_ring *ring) @@ -56,7 +57,7 @@ int intel_ring_pin(struct intel_ring *ring, struct i915_gem_ww_ctx *ww) if (i915_vma_is_map_and_fenceable(vma) && !HAS_LLC(vma->vm->i915)) { addr = (void __force *)i915_vma_pin_iomap(vma); } else { - int type = i915_coherent_map_type(vma->vm->i915, vma->obj, false); + int type = intel_gt_coherent_map_type(vma->vm->gt, vma->obj, false); addr = i915_gem_object_pin_map(vma->obj, type); } diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 3fd795c3263f..92085ffd23de 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -805,7 +805,7 @@ static int mi_set_context(struct i915_request *rq, static int remap_l3_slice(struct i915_request *rq, int slice) { #define L3LOG_DW (GEN7_L3LOG_SIZE / sizeof(u32)) - u32 *cs, *remap_info = rq->engine->i915->l3_parity.remap_info[slice]; + u32 *cs, *remap_info = rq->i915->l3_parity.remap_info[slice]; int i; if (!remap_info) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index e92e626d4994..092542f53aad 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -16,7 +16,9 @@ #include "intel_gt.h" #include "intel_gt_clock_utils.h" #include "intel_gt_irq.h" +#include "intel_gt_pm.h" #include "intel_gt_pm_irq.h" +#include "intel_gt_print.h" #include "intel_gt_regs.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" @@ -672,7 +674,6 @@ static void rps_set_power(struct intel_rps *rps, int new_power) { struct intel_gt *gt = rps_to_gt(rps); struct intel_uncore *uncore = gt->uncore; - u32 threshold_up = 0, threshold_down = 0; /* in % */ u32 ei_up = 0, ei_down = 0; lockdep_assert_held(&rps->power.mutex); @@ -680,9 +681,6 @@ static void rps_set_power(struct intel_rps *rps, int new_power) if (new_power == rps->power.mode) return; - threshold_up = 95; - threshold_down = 85; - /* Note the units here are not exactly 1us, but 1280ns. */ switch (new_power) { case LOW_POWER: @@ -709,17 +707,22 @@ static void rps_set_power(struct intel_rps *rps, int new_power) GT_TRACE(gt, "changing power mode [%d], up %d%% @ %dus, down %d%% @ %dus\n", - new_power, threshold_up, ei_up, threshold_down, ei_down); + new_power, + rps->power.up_threshold, ei_up, + rps->power.down_threshold, ei_down); set(uncore, GEN6_RP_UP_EI, intel_gt_ns_to_pm_interval(gt, ei_up * 1000)); set(uncore, GEN6_RP_UP_THRESHOLD, - intel_gt_ns_to_pm_interval(gt, ei_up * threshold_up * 10)); + intel_gt_ns_to_pm_interval(gt, + ei_up * rps->power.up_threshold * 10)); set(uncore, GEN6_RP_DOWN_EI, intel_gt_ns_to_pm_interval(gt, ei_down * 1000)); set(uncore, GEN6_RP_DOWN_THRESHOLD, - intel_gt_ns_to_pm_interval(gt, ei_down * threshold_down * 10)); + intel_gt_ns_to_pm_interval(gt, + ei_down * + rps->power.down_threshold * 10)); set(uncore, GEN6_RP_CONTROL, (GRAPHICS_VER(gt->i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) | @@ -731,8 +734,6 @@ static void rps_set_power(struct intel_rps *rps, int new_power) skip_hw_write: rps->power.mode = new_power; - rps->power.up_threshold = threshold_up; - rps->power.down_threshold = threshold_down; } static void gen6_rps_set_thresholds(struct intel_rps *rps, u8 val) @@ -1559,10 +1560,12 @@ void intel_rps_enable(struct intel_rps *rps) return; GT_TRACE(rps_to_gt(rps), - "min:%x, max:%x, freq:[%d, %d]\n", + "min:%x, max:%x, freq:[%d, %d], thresholds:[%u, %u]\n", rps->min_freq, rps->max_freq, intel_gpu_freq(rps, rps->min_freq), - intel_gpu_freq(rps, rps->max_freq)); + intel_gpu_freq(rps, rps->max_freq), + rps->power.up_threshold, + rps->power.down_threshold); GEM_BUG_ON(rps->max_freq < rps->min_freq); GEM_BUG_ON(rps->idle_freq > rps->max_freq); @@ -2015,6 +2018,12 @@ void intel_rps_init(struct intel_rps *rps) } } + /* Set default thresholds in % */ + rps->power.up_threshold = 95; + rps_to_gt(rps)->defaults.rps_up_threshold = rps->power.up_threshold; + rps->power.down_threshold = 85; + rps_to_gt(rps)->defaults.rps_down_threshold = rps->power.down_threshold; + /* Finally allow us to boost to max by default */ rps->boost_freq = rps->max_freq; rps->idle_freq = rps->min_freq; @@ -2569,6 +2578,58 @@ int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val) return set_min_freq(rps, val); } +u8 intel_rps_get_up_threshold(struct intel_rps *rps) +{ + return rps->power.up_threshold; +} + +static int rps_set_threshold(struct intel_rps *rps, u8 *threshold, u8 val) +{ + int ret; + + if (val > 100) + return -EINVAL; + + ret = mutex_lock_interruptible(&rps->lock); + if (ret) + return ret; + + if (*threshold == val) + goto out_unlock; + + *threshold = val; + + /* Force reset. */ + rps->last_freq = -1; + mutex_lock(&rps->power.mutex); + rps->power.mode = -1; + mutex_unlock(&rps->power.mutex); + + intel_rps_set(rps, clamp(rps->cur_freq, + rps->min_freq_softlimit, + rps->max_freq_softlimit)); + +out_unlock: + mutex_unlock(&rps->lock); + + return ret; +} + +int intel_rps_set_up_threshold(struct intel_rps *rps, u8 threshold) +{ + return rps_set_threshold(rps, &rps->power.up_threshold, threshold); +} + +u8 intel_rps_get_down_threshold(struct intel_rps *rps) +{ + return rps->power.down_threshold; +} + +int intel_rps_set_down_threshold(struct intel_rps *rps, u8 threshold) +{ + return rps_set_threshold(rps, &rps->power.down_threshold, threshold); +} + static void intel_rps_set_manual(struct intel_rps *rps, bool enable) { struct intel_uncore *uncore = rps_to_uncore(rps); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index a3fa987aa91f..92fb01f5a452 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -37,6 +37,10 @@ void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive); int intel_gpu_freq(struct intel_rps *rps, int val); int intel_freq_opcode(struct intel_rps *rps, int val); +u8 intel_rps_get_up_threshold(struct intel_rps *rps); +int intel_rps_set_up_threshold(struct intel_rps *rps, u8 threshold); +u8 intel_rps_get_down_threshold(struct intel_rps *rps); +int intel_rps_set_down_threshold(struct intel_rps *rps, u8 threshold); u32 intel_rps_read_actual_frequency(struct intel_rps *rps); u32 intel_rps_read_actual_frequency_fw(struct intel_rps *rps); u32 intel_rps_get_requested_frequency(struct intel_rps *rps); diff --git a/drivers/gpu/drm/i915/gt/intel_sa_media.c b/drivers/gpu/drm/i915/gt/intel_sa_media.c index e8f3d18c12b8..8c1dbcbcbc4f 100644 --- a/drivers/gpu/drm/i915/gt/intel_sa_media.c +++ b/drivers/gpu/drm/i915/gt/intel_sa_media.c @@ -29,7 +29,7 @@ int intel_sa_mediagt_setup(struct intel_gt *gt, phys_addr_t phys_addr, * Standalone media shares the general MMIO space with the primary * GT. We'll re-use the primary GT's mapping. */ - uncore->regs = i915->uncore.regs; + uncore->regs = intel_uncore_regs(&i915->uncore); if (drm_WARN_ON(&i915->drm, uncore->regs == NULL)) return -EIO; diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c index 1141f875f5bd..f602895f6d0d 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c @@ -302,7 +302,7 @@ static void gen11_sseu_info_init(struct intel_gt *gt) u8 eu_en; u8 s_en; - if (IS_JSL_EHL(gt->i915)) + if (IS_JASPERLAKE(gt->i915) || IS_ELKHARTLAKE(gt->i915)) intel_sseu_set_info(sseu, 1, 4, 8); else intel_sseu_set_info(sseu, 1, 8, 8); diff --git a/drivers/gpu/drm/i915/gt/intel_tlb.c b/drivers/gpu/drm/i915/gt/intel_tlb.c new file mode 100644 index 000000000000..139608c30d97 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_tlb.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_perf_oa_regs.h" +#include "intel_engine_pm.h" +#include "intel_gt.h" +#include "intel_gt_mcr.h" +#include "intel_gt_pm.h" +#include "intel_gt_print.h" +#include "intel_gt_regs.h" +#include "intel_tlb.h" + +/* + * HW architecture suggest typical invalidation time at 40us, + * with pessimistic cases up to 100us and a recommendation to + * cap at 1ms. We go a bit higher just in case. + */ +#define TLB_INVAL_TIMEOUT_US 100 +#define TLB_INVAL_TIMEOUT_MS 4 + +/* + * On Xe_HP the TLB invalidation registers are located at the same MMIO offsets + * but are now considered MCR registers. Since they exist within a GAM range, + * the primary instance of the register rolls up the status from each unit. + */ +static int wait_for_invalidate(struct intel_engine_cs *engine) +{ + if (engine->tlb_inv.mcr) + return intel_gt_mcr_wait_for_reg(engine->gt, + engine->tlb_inv.reg.mcr_reg, + engine->tlb_inv.done, + 0, + TLB_INVAL_TIMEOUT_US, + TLB_INVAL_TIMEOUT_MS); + else + return __intel_wait_for_register_fw(engine->gt->uncore, + engine->tlb_inv.reg.reg, + engine->tlb_inv.done, + 0, + TLB_INVAL_TIMEOUT_US, + TLB_INVAL_TIMEOUT_MS, + NULL); +} + +static void mmio_invalidate_full(struct intel_gt *gt) +{ + struct drm_i915_private *i915 = gt->i915; + struct intel_uncore *uncore = gt->uncore; + struct intel_engine_cs *engine; + intel_engine_mask_t awake, tmp; + enum intel_engine_id id; + unsigned long flags; + + if (GRAPHICS_VER(i915) < 8) + return; + + intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); + + intel_gt_mcr_lock(gt, &flags); + spin_lock(&uncore->lock); /* serialise invalidate with GT reset */ + + awake = 0; + for_each_engine(engine, gt, id) { + if (!intel_engine_pm_is_awake(engine)) + continue; + + if (engine->tlb_inv.mcr) + intel_gt_mcr_multicast_write_fw(gt, + engine->tlb_inv.reg.mcr_reg, + engine->tlb_inv.request); + else + intel_uncore_write_fw(uncore, + engine->tlb_inv.reg.reg, + engine->tlb_inv.request); + + awake |= engine->mask; + } + + GT_TRACE(gt, "invalidated engines %08x\n", awake); + + /* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */ + if (awake && + (IS_TIGERLAKE(i915) || + IS_DG1(i915) || + IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || + IS_ALDERLAKE_P(i915))) + intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1); + + spin_unlock(&uncore->lock); + intel_gt_mcr_unlock(gt, flags); + + for_each_engine_masked(engine, gt, awake, tmp) { + if (wait_for_invalidate(engine)) + gt_err_ratelimited(gt, + "%s TLB invalidation did not complete in %ums!\n", + engine->name, TLB_INVAL_TIMEOUT_MS); + } + + /* + * Use delayed put since a) we mostly expect a flurry of TLB + * invalidations so it is good to avoid paying the forcewake cost and + * b) it works around a bug in Icelake which cannot cope with too rapid + * transitions. + */ + intel_uncore_forcewake_put_delayed(uncore, FORCEWAKE_ALL); +} + +static bool tlb_seqno_passed(const struct intel_gt *gt, u32 seqno) +{ + u32 cur = intel_gt_tlb_seqno(gt); + + /* Only skip if a *full* TLB invalidate barrier has passed */ + return (s32)(cur - ALIGN(seqno, 2)) > 0; +} + +void intel_gt_invalidate_tlb_full(struct intel_gt *gt, u32 seqno) +{ + intel_wakeref_t wakeref; + + if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) + return; + + if (intel_gt_is_wedged(gt)) + return; + + if (tlb_seqno_passed(gt, seqno)) + return; + + with_intel_gt_pm_if_awake(gt, wakeref) { + mutex_lock(>->tlb.invalidate_lock); + if (tlb_seqno_passed(gt, seqno)) + goto unlock; + + mmio_invalidate_full(gt); + + write_seqcount_invalidate(>->tlb.seqno); +unlock: + mutex_unlock(>->tlb.invalidate_lock); + } +} + +void intel_gt_init_tlb(struct intel_gt *gt) +{ + mutex_init(>->tlb.invalidate_lock); + seqcount_mutex_init(>->tlb.seqno, >->tlb.invalidate_lock); +} + +void intel_gt_fini_tlb(struct intel_gt *gt) +{ + mutex_destroy(>->tlb.invalidate_lock); +} + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftest_tlb.c" +#endif diff --git a/drivers/gpu/drm/i915/gt/intel_tlb.h b/drivers/gpu/drm/i915/gt/intel_tlb.h new file mode 100644 index 000000000000..337327af92ac --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_tlb.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef INTEL_TLB_H +#define INTEL_TLB_H + +#include <linux/seqlock.h> +#include <linux/types.h> + +#include "intel_gt_types.h" + +void intel_gt_invalidate_tlb_full(struct intel_gt *gt, u32 seqno); + +void intel_gt_init_tlb(struct intel_gt *gt); +void intel_gt_fini_tlb(struct intel_gt *gt); + +static inline u32 intel_gt_tlb_seqno(const struct intel_gt *gt) +{ + return seqprop_sequence(>->tlb.seqno); +} + +static inline u32 intel_gt_next_invalidate_tlb_full(const struct intel_gt *gt) +{ + return intel_gt_tlb_seqno(gt) | 1; +} + +#endif /* INTEL_TLB_H */ diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 4d2dece96011..3ae0dbd39eaa 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -123,6 +123,22 @@ static void wa_init_finish(struct i915_wa_list *wal) wal->wa_count, wal->name, wal->engine_name); } +static enum forcewake_domains +wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal) +{ + enum forcewake_domains fw = 0; + struct i915_wa *wa; + unsigned int i; + + for (i = 0, wa = wal->list; i < wal->count; i++, wa++) + fw |= intel_uncore_forcewake_for_reg(uncore, + wa->reg, + FW_REG_READ | + FW_REG_WRITE); + + return fw; +} + static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) { unsigned int addr = i915_mmio_reg_offset(wa->reg); @@ -225,13 +241,13 @@ static void wa_mcr_add(struct i915_wa_list *wal, i915_mcr_reg_t reg, static void wa_write_clr_set(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set) { - wa_add(wal, reg, clear, set, clear, false); + wa_add(wal, reg, clear, set, clear | set, false); } static void wa_mcr_write_clr_set(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 clear, u32 set) { - wa_mcr_add(wal, reg, clear, set, clear, false); + wa_mcr_add(wal, reg, clear, set, clear | set, false); } static void @@ -404,7 +420,7 @@ static void bdw_ctx_workarounds_init(struct intel_engine_cs *engine, /* WaForceContextSaveRestoreNonCoherent:bdw */ HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ - (IS_BDW_GT3(i915) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); + (IS_BROADWELL_GT3(i915) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); } static void chv_ctx_workarounds_init(struct intel_engine_cs *engine, @@ -584,7 +600,7 @@ static void kbl_ctx_workarounds_init(struct intel_engine_cs *engine, gen9_ctx_workarounds_init(engine, wal); /* WaToEnableHwFixForPushConstHWBug:kbl */ - if (IS_KBL_GRAPHICS_STEP(i915, STEP_C0, STEP_FOREVER)) + if (IS_KABYLAKE(i915) && IS_GRAPHICS_STEP(i915, STEP_C0, STEP_FOREVER)) wa_masked_en(wal, COMMON_SLICE_CHICKEN2, GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); @@ -621,10 +637,7 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) { /* Wa_1406697149 (WaDisableBankHangMode:icl) */ - wa_write(wal, - GEN8_L3CNTLREG, - intel_uncore_read(engine->uncore, GEN8_L3CNTLREG) | - GEN8_ERRDETBCTRL); + wa_write(wal, GEN8_L3CNTLREG, GEN8_ERRDETBCTRL); /* WaForceEnableNonCoherent:icl * This is not the same workaround as in early Gen9 platforms, where @@ -653,7 +666,7 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, /* Wa_1604278689:icl,ehl */ wa_write(wal, IVB_FBC_RT_BASE, 0xFFFFFFFF & ~ILK_FBC_RT_VALID); wa_write_clr_set(wal, IVB_FBC_RT_BASE_UPPER, - 0, /* write-only register; skip validation */ + 0, 0xFFFFFFFF); /* Wa_1406306137:icl,ehl */ @@ -670,38 +683,8 @@ static void dg2_ctx_gt_tuning_init(struct intel_engine_cs *engine, wa_mcr_masked_en(wal, CHICKEN_RASTER_2, TBIMR_FAST_CLIP); wa_mcr_write_clr_set(wal, XEHP_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK, REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f)); - wa_mcr_add(wal, - XEHP_FF_MODE2, - FF_MODE2_TDS_TIMER_MASK, - FF_MODE2_TDS_TIMER_128, - 0, false); -} - -/* - * These settings aren't actually workarounds, but general tuning settings that - * need to be programmed on several platforms. - */ -static void gen12_ctx_gt_tuning_init(struct intel_engine_cs *engine, - struct i915_wa_list *wal) -{ - /* - * Although some platforms refer to it as Wa_1604555607, we need to - * program it even on those that don't explicitly list that - * workaround. - * - * Note that the programming of this register is further modified - * according to the FF_MODE2 guidance given by Wa_1608008084:gen12. - * Wa_1608008084 tells us the FF_MODE2 register will return the wrong - * value when read. The default value for this register is zero for all - * fields and there are no bit masks. So instead of doing a RMW we - * should just write TDS timer value. For the same reason read - * verification is ignored. - */ - wa_add(wal, - GEN12_FF_MODE2, - FF_MODE2_TDS_TIMER_MASK, - FF_MODE2_TDS_TIMER_128, - 0, false); + wa_mcr_write_clr_set(wal, XEHP_FF_MODE2, FF_MODE2_TDS_TIMER_MASK, + FF_MODE2_TDS_TIMER_128); } static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, @@ -709,8 +692,6 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, { struct drm_i915_private *i915 = engine->i915; - gen12_ctx_gt_tuning_init(engine, wal); - /* * Wa_1409142259:tgl,dg1,adl-p * Wa_1409347922:tgl,dg1,adl-p @@ -732,15 +713,27 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL); /* - * Wa_16011163337 + * Wa_16011163337 - GS_TIMER + * + * TDS_TIMER: Although some platforms refer to it as Wa_1604555607, we + * need to program it even on those that don't explicitly list that + * workaround. + * + * Note that the programming of GEN12_FF_MODE2 is further modified + * according to the FF_MODE2 guidance given by Wa_1608008084. + * Wa_1608008084 tells us the FF_MODE2 register will return the wrong + * value when read from the CPU. * - * Like in gen12_ctx_gt_tuning_init(), read verification is ignored due - * to Wa_1608008084. + * The default value for this register is zero for all fields. + * So instead of doing a RMW we should just write the desired values + * for TDS and GS timers. Note that since the readback can't be trusted, + * the clear mask is just set to ~0 to make sure other bits are not + * inadvertently set. For the same reason read verification is ignored. */ wa_add(wal, GEN12_FF_MODE2, - FF_MODE2_GS_TIMER_MASK, - FF_MODE2_GS_TIMER_224, + ~0, + FF_MODE2_TDS_TIMER_128 | FF_MODE2_GS_TIMER_224, 0, false); if (!IS_DG1(i915)) { @@ -987,6 +980,9 @@ void intel_engine_init_ctx_wa(struct intel_engine_cs *engine) int intel_engine_emit_ctx_wa(struct i915_request *rq) { struct i915_wa_list *wal = &rq->engine->ctx_wa_list; + struct intel_uncore *uncore = rq->engine->uncore; + enum forcewake_domains fw; + unsigned long flags; struct i915_wa *wa; unsigned int i; u32 *cs; @@ -1003,13 +999,36 @@ int intel_engine_emit_ctx_wa(struct i915_request *rq) if (IS_ERR(cs)) return PTR_ERR(cs); + fw = wal_get_fw_for_rmw(uncore, wal); + + intel_gt_mcr_lock(wal->gt, &flags); + spin_lock(&uncore->lock); + intel_uncore_forcewake_get__locked(uncore, fw); + *cs++ = MI_LOAD_REGISTER_IMM(wal->count); for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { + u32 val; + + /* Skip reading the register if it's not really needed */ + if (wa->masked_reg || (wa->clr | wa->set) == U32_MAX) { + val = wa->set; + } else { + val = wa->is_mcr ? + intel_gt_mcr_read_any_fw(wal->gt, wa->mcr_reg) : + intel_uncore_read_fw(uncore, wa->reg); + val &= ~wa->clr; + val |= wa->set; + } + *cs++ = i915_mmio_reg_offset(wa->reg); - *cs++ = wa->set; + *cs++ = val; } *cs++ = MI_NOOP; + intel_uncore_forcewake_put__locked(uncore, fw); + spin_unlock(&uncore->lock); + intel_gt_mcr_unlock(wal->gt, flags); + intel_ring_advance(rq, cs); ret = rq->engine->emit_flush(rq, EMIT_BARRIER); @@ -1173,7 +1192,7 @@ skl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); /* WaInPlaceDecompressionHang:skl */ - if (IS_SKL_GRAPHICS_STEP(gt->i915, STEP_A0, STEP_H0)) + if (IS_SKYLAKE(gt->i915) && IS_GRAPHICS_STEP(gt->i915, STEP_A0, STEP_H0)) wa_write_or(wal, GEN9_GAMT_ECO_REG_RW_IA, GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); @@ -1185,7 +1204,7 @@ kbl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) gen9_gt_workarounds_init(gt, wal); /* WaDisableDynamicCreditSharing:kbl */ - if (IS_KBL_GRAPHICS_STEP(gt->i915, 0, STEP_C0)) + if (IS_KABYLAKE(gt->i915) && IS_GRAPHICS_STEP(gt->i915, 0, STEP_C0)) wa_write_or(wal, GAMT_CHKN_BIT_REG, GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); @@ -1441,7 +1460,8 @@ icl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) /* Wa_1607087056:icl,ehl,jsl */ if (IS_ICELAKE(i915) || - IS_JSL_EHL_GRAPHICS_STEP(i915, STEP_A0, STEP_B0)) + ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) && + IS_GRAPHICS_STEP(i915, STEP_A0, STEP_B0))) wa_write_or(wal, GEN11_SLICE_UNIT_LEVEL_CLKGATE, L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS); @@ -1485,6 +1505,18 @@ gen12_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) /* Wa_14011059788:tgl,rkl,adl-s,dg1,adl-p */ wa_mcr_write_or(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE); + + /* + * Wa_14015795083 + * + * Firmware on some gen12 platforms locks the MISCCPCTL register, + * preventing i915 from modifying it for this workaround. Skip the + * readback verification for this workaround on debug builds; if the + * workaround doesn't stick due to firmware behavior, it's not an error + * that we want CI to flag. + */ + wa_add(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE, + 0, 0, false); } static void @@ -1710,7 +1742,6 @@ static void xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) { /* Wa_14018778641 / Wa_18018781329 */ - wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB); wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); /* Wa_22016670082 */ @@ -1743,8 +1774,6 @@ xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) * GT, the media GT's versions are regular singleton registers. */ wa_write_or(wal, XELPMP_GSC_MOD_CTRL, FORCE_MISS_FTLB); - wa_write_or(wal, XELPMP_VDBX_MOD_CTRL, FORCE_MISS_FTLB); - wa_write_or(wal, XELPMP_VEBX_MOD_CTRL, FORCE_MISS_FTLB); debug_dump_steering(gt); } @@ -1850,22 +1879,6 @@ void intel_gt_init_workarounds(struct intel_gt *gt) wa_init_finish(wal); } -static enum forcewake_domains -wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal) -{ - enum forcewake_domains fw = 0; - struct i915_wa *wa; - unsigned int i; - - for (i = 0, wa = wal->list; i < wal->count; i++, wa++) - fw |= intel_uncore_forcewake_for_reg(uncore, - wa->reg, - FW_REG_READ | - FW_REG_WRITE); - - return fw; -} - static bool wa_verify(struct intel_gt *gt, const struct i915_wa *wa, u32 cur, const char *name, const char *from) @@ -2933,7 +2946,7 @@ xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) struct drm_i915_private *i915 = engine->i915; /* WaKBLVECSSemaphoreWaitPoll:kbl */ - if (IS_KBL_GRAPHICS_STEP(i915, STEP_A0, STEP_F0)) { + if (IS_KABYLAKE(i915) && IS_GRAPHICS_STEP(i915, STEP_A0, STEP_F0)) { wa_write(wal, RING_SEMA_WAIT_POLL(engine->mmio_base), 1); @@ -3237,7 +3250,7 @@ wa_list_srm(struct i915_request *rq, const struct i915_wa_list *wal, struct i915_vma *vma) { - struct drm_i915_private *i915 = rq->engine->i915; + struct drm_i915_private *i915 = rq->i915; unsigned int i, count = 0; const struct i915_wa *wa; u32 srm, *cs; @@ -3336,7 +3349,7 @@ retry: err = 0; for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { - if (mcr_range(rq->engine->i915, i915_mmio_reg_offset(wa->reg))) + if (mcr_range(rq->i915, i915_mmio_reg_offset(wa->reg))) continue; if (!wa_verify(wal->gt, wa, results[i], wal->name, from)) diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 76fbae358072..47070cba7eb1 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -88,8 +88,9 @@ static int __live_context_size(struct intel_engine_cs *engine) goto err; vaddr = i915_gem_object_pin_map_unlocked(ce->state->obj, - i915_coherent_map_type(engine->i915, - ce->state->obj, false)); + intel_gt_coherent_map_type(engine->gt, + ce->state->obj, + false)); if (IS_ERR(vaddr)) { err = PTR_ERR(vaddr); intel_context_unpin(ce); diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c index 78cdfc6f315f..86cecf7a1105 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c @@ -62,7 +62,7 @@ static int write_timestamp(struct i915_request *rq, int slot) return PTR_ERR(cs); cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT; - if (GRAPHICS_VER(rq->engine->i915) >= 8) + if (GRAPHICS_VER(rq->i915) >= 8) cmd++; *cs++ = cmd; *cs++ = i915_mmio_reg_offset(timestamp_reg(rq->engine)); diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index 8b0d84f2aad2..0dd4d00ee894 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -73,7 +73,7 @@ static int hang_init(struct hang *h, struct intel_gt *gt) h->seqno = memset(vaddr, 0xff, PAGE_SIZE); vaddr = i915_gem_object_pin_map_unlocked(h->obj, - i915_coherent_map_type(gt->i915, h->obj, false)); + intel_gt_coherent_map_type(gt, h->obj, false)); if (IS_ERR(vaddr)) { err = PTR_ERR(vaddr); goto err_unpin_hws; @@ -119,7 +119,7 @@ hang_create_request(struct hang *h, struct intel_engine_cs *engine) return ERR_CAST(obj); } - vaddr = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(gt->i915, obj, false)); + vaddr = i915_gem_object_pin_map_unlocked(obj, intel_gt_coherent_map_type(gt, obj, false)); if (IS_ERR(vaddr)) { i915_gem_object_put(obj); i915_vm_put(vm); diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index a78a3d2c2e16..5f826b6dcf5d 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -1292,9 +1292,9 @@ static int compare_isolation(struct intel_engine_cs *engine, } lrc = i915_gem_object_pin_map_unlocked(ce->state->obj, - i915_coherent_map_type(engine->i915, - ce->state->obj, - false)); + intel_gt_coherent_map_type(engine->gt, + ce->state->obj, + false)); if (IS_ERR(lrc)) { err = PTR_ERR(lrc); goto err_B1; diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c index a8446ab82501..d73e438fb85f 100644 --- a/drivers/gpu/drm/i915/gt/selftest_mocs.c +++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c @@ -137,7 +137,7 @@ static int read_mocs_table(struct i915_request *rq, if (!table) return 0; - if (HAS_GLOBAL_MOCS_REGISTERS(rq->engine->i915)) + if (HAS_GLOBAL_MOCS_REGISTERS(rq->i915)) addr = global_mocs_offset() + gt->uncore->gsi_offset; else addr = mocs_offset(rq->engine); diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c index 2ceeadecc639..a7189c2d660c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.c +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -140,7 +140,7 @@ static const u32 *__live_rc6_ctx(struct intel_context *ce) } cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT; - if (GRAPHICS_VER(rq->engine->i915) >= 8) + if (GRAPHICS_VER(rq->i915) >= 8) cmd++; *cs++ = cmd; diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 39c3ec12df1a..fa36cf920bde 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -459,12 +459,12 @@ static int emit_ggtt_store_dw(struct i915_request *rq, u32 addr, u32 value) if (IS_ERR(cs)) return PTR_ERR(cs); - if (GRAPHICS_VER(rq->engine->i915) >= 8) { + if (GRAPHICS_VER(rq->i915) >= 8) { *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; *cs++ = addr; *cs++ = 0; *cs++ = value; - } else if (GRAPHICS_VER(rq->engine->i915) >= 4) { + } else if (GRAPHICS_VER(rq->i915) >= 4) { *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; *cs++ = 0; *cs++ = addr; diff --git a/drivers/gpu/drm/i915/gt/selftest_tlb.c b/drivers/gpu/drm/i915/gt/selftest_tlb.c index 3bd6b540257b..7e41f69fc818 100644 --- a/drivers/gpu/drm/i915/gt/selftest_tlb.c +++ b/drivers/gpu/drm/i915/gt/selftest_tlb.c @@ -6,6 +6,7 @@ #include "i915_selftest.h" #include "gem/i915_gem_internal.h" +#include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" #include "gen8_engine_cs.h" @@ -354,7 +355,7 @@ out_a: static void tlbinv_full(struct i915_address_space *vm, u64 addr, u64 length) { - intel_gt_invalidate_tlb(vm->gt, intel_gt_tlb_seqno(vm->gt) | 1); + intel_gt_invalidate_tlb_full(vm->gt, intel_gt_tlb_seqno(vm->gt) | 1); } static int invalidate_full(void *arg) diff --git a/drivers/gpu/drm/i915/gt/shmem_utils.c b/drivers/gpu/drm/i915/gt/shmem_utils.c index 449c9ed44382..bccc3a1200bc 100644 --- a/drivers/gpu/drm/i915/gt/shmem_utils.c +++ b/drivers/gpu/drm/i915/gt/shmem_utils.c @@ -33,7 +33,6 @@ struct file *shmem_create_from_data(const char *name, void *data, size_t len) struct file *shmem_create_from_object(struct drm_i915_gem_object *obj) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); enum i915_map_type map_type; struct file *file; void *ptr; @@ -44,7 +43,7 @@ struct file *shmem_create_from_object(struct drm_i915_gem_object *obj) return file; } - map_type = i915_coherent_map_type(i915, obj, true); + map_type = i915_gem_object_is_lmem(obj) ? I915_MAP_WC : I915_MAP_WB; ptr = i915_gem_object_pin_map_unlocked(obj, map_type); if (IS_ERR(ptr)) return ERR_CAST(ptr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h index 714f0c256118..6d009a905269 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_binary_headers.h @@ -8,6 +8,74 @@ #include <linux/types.h> +struct intel_gsc_version { + u16 major; + u16 minor; + u16 hotfix; + u16 build; +} __packed; + +struct intel_gsc_partition { + u32 offset; + u32 size; +} __packed; + +struct intel_gsc_layout_pointers { + u8 rom_bypass_vector[16]; + + /* size of pointers layout not including ROM bypass vector */ + u16 size; + + /* + * bit0: Backup copy of layout pointers exist + * bits1-15: reserved + */ + u8 flags; + + u8 reserved; + + u32 crc32; + + struct intel_gsc_partition datap; + struct intel_gsc_partition boot1; + struct intel_gsc_partition boot2; + struct intel_gsc_partition boot3; + struct intel_gsc_partition boot4; + struct intel_gsc_partition boot5; + struct intel_gsc_partition temp_pages; +} __packed; + +/* Boot partition structures */ +struct intel_gsc_bpdt_header { + u32 signature; +#define INTEL_GSC_BPDT_HEADER_SIGNATURE 0x000055AA + + u16 descriptor_count; /* num of entries after the header */ + + u8 version; + u8 configuration; + + u32 crc32; + + u32 build_version; + struct intel_gsc_version tool_version; +} __packed; + +struct intel_gsc_bpdt_entry { + /* + * Bits 0-15: BPDT entry type + * Bits 16-17: reserved + * Bit 18: code sub-partition + * Bits 19-31: reserved + */ + u32 type; +#define INTEL_GSC_BPDT_ENTRY_TYPE_MASK GENMASK(15, 0) +#define INTEL_GSC_BPDT_ENTRY_TYPE_GSC_RBE 0x1 + + u32 sub_partition_offset; /* from the base of the BPDT header */ + u32 sub_partition_size; +} __packed; + /* Code partition directory (CPD) structures */ struct intel_gsc_cpd_header_v2 { u32 header_marker; @@ -44,13 +112,6 @@ struct intel_gsc_cpd_entry { u8 reserved[4]; } __packed; -struct intel_gsc_version { - u16 major; - u16 minor; - u16 hotfix; - u16 build; -} __packed; - struct intel_gsc_manifest_header { u32 header_type; /* 0x4 for manifest type */ u32 header_length; /* in dwords */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c index 60e9c6c9e775..e2e42b3e0d5d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c @@ -3,48 +3,216 @@ * Copyright © 2022 Intel Corporation */ +#include "gem/i915_gem_lmem.h" #include "gt/intel_engine_pm.h" #include "gt/intel_gpu_commands.h" #include "gt/intel_gt.h" #include "gt/intel_gt_print.h" #include "gt/intel_ring.h" +#include "intel_gsc_binary_headers.h" #include "intel_gsc_fw.h" - -#define GSC_FW_STATUS_REG _MMIO(0x116C40) -#define GSC_FW_CURRENT_STATE REG_GENMASK(3, 0) -#define GSC_FW_CURRENT_STATE_RESET 0 -#define GSC_FW_PROXY_STATE_NORMAL 5 -#define GSC_FW_INIT_COMPLETE_BIT REG_BIT(9) +#include "intel_gsc_uc_heci_cmd_submit.h" +#include "i915_reg.h" static bool gsc_is_in_reset(struct intel_uncore *uncore) { - u32 fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG); + u32 fw_status = intel_uncore_read(uncore, HECI_FWSTS(MTL_GSC_HECI1_BASE, 1)); - return REG_FIELD_GET(GSC_FW_CURRENT_STATE, fw_status) == - GSC_FW_CURRENT_STATE_RESET; + return REG_FIELD_GET(HECI1_FWSTS1_CURRENT_STATE, fw_status) == + HECI1_FWSTS1_CURRENT_STATE_RESET; } -static u32 gsc_uc_get_fw_status(struct intel_uncore *uncore) +static u32 gsc_uc_get_fw_status(struct intel_uncore *uncore, bool needs_wakeref) { intel_wakeref_t wakeref; u32 fw_status = 0; - with_intel_runtime_pm(uncore->rpm, wakeref) - fw_status = intel_uncore_read(uncore, GSC_FW_STATUS_REG); + if (needs_wakeref) + wakeref = intel_runtime_pm_get(uncore->rpm); + + fw_status = intel_uncore_read(uncore, HECI_FWSTS(MTL_GSC_HECI1_BASE, 1)); + if (needs_wakeref) + intel_runtime_pm_put(uncore->rpm, wakeref); return fw_status; } -bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc) +bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc, bool needs_wakeref) +{ + return REG_FIELD_GET(HECI1_FWSTS1_CURRENT_STATE, + gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore, + needs_wakeref)) == + HECI1_FWSTS1_PROXY_STATE_NORMAL; +} + +int intel_gsc_uc_fw_proxy_get_status(struct intel_gsc_uc *gsc) { - return REG_FIELD_GET(GSC_FW_CURRENT_STATE, - gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore)) == - GSC_FW_PROXY_STATE_NORMAL; + if (!(IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY))) + return -ENODEV; + if (!intel_uc_fw_is_loadable(&gsc->fw)) + return -ENODEV; + if (__intel_uc_fw_status(&gsc->fw) == INTEL_UC_FIRMWARE_LOAD_FAIL) + return -ENOLINK; + if (!intel_gsc_uc_fw_proxy_init_done(gsc, true)) + return -EAGAIN; + + return 0; } bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc) { - return gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore) & GSC_FW_INIT_COMPLETE_BIT; + return gsc_uc_get_fw_status(gsc_uc_to_gt(gsc)->uncore, false) & + HECI1_FWSTS1_INIT_COMPLETE; +} + +static inline u32 cpd_entry_offset(const struct intel_gsc_cpd_entry *entry) +{ + return entry->offset & INTEL_GSC_CPD_ENTRY_OFFSET_MASK; +} + +int intel_gsc_fw_get_binary_info(struct intel_uc_fw *gsc_fw, const void *data, size_t size) +{ + struct intel_gsc_uc *gsc = container_of(gsc_fw, struct intel_gsc_uc, fw); + struct intel_gt *gt = gsc_uc_to_gt(gsc); + const struct intel_gsc_layout_pointers *layout = data; + const struct intel_gsc_bpdt_header *bpdt_header = NULL; + const struct intel_gsc_bpdt_entry *bpdt_entry = NULL; + const struct intel_gsc_cpd_header_v2 *cpd_header = NULL; + const struct intel_gsc_cpd_entry *cpd_entry = NULL; + const struct intel_gsc_manifest_header *manifest; + size_t min_size = sizeof(*layout); + int i; + + if (size < min_size) { + gt_err(gt, "GSC FW too small! %zu < %zu\n", size, min_size); + return -ENODATA; + } + + /* + * The GSC binary starts with the pointer layout, which contains the + * locations of the various partitions of the binary. The one we're + * interested in to get the version is the boot1 partition, where we can + * find a BPDT header followed by entries, one of which points to the + * RBE sub-section of the partition. From here, we can parse the CPD + * header and the following entries to find the manifest location + * (entry identified by the "RBEP.man" name), from which we can finally + * extract the version. + * + * -------------------------------------------------- + * [ intel_gsc_layout_pointers ] + * [ ... ] + * [ boot1.offset >---------------------------]------o + * [ ... ] | + * -------------------------------------------------- | + * | + * -------------------------------------------------- | + * [ intel_gsc_bpdt_header ]<-----o + * -------------------------------------------------- + * [ intel_gsc_bpdt_entry[] ] + * [ entry1 ] + * [ ... ] + * [ entryX ] + * [ type == GSC_RBE ] + * [ offset >-----------------------------]------o + * [ ... ] | + * -------------------------------------------------- | + * | + * -------------------------------------------------- | + * [ intel_gsc_cpd_header_v2 ]<-----o + * -------------------------------------------------- + * [ intel_gsc_cpd_entry[] ] + * [ entry1 ] + * [ ... ] + * [ entryX ] + * [ "RBEP.man" ] + * [ ... ] + * [ offset >----------------------------]------o + * [ ... ] | + * -------------------------------------------------- | + * | + * -------------------------------------------------- | + * [ intel_gsc_manifest_header ]<-----o + * [ ... ] + * [ intel_gsc_version fw_version ] + * [ ... ] + * -------------------------------------------------- + */ + + min_size = layout->boot1.offset + layout->boot1.size; + if (size < min_size) { + gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n", + size, min_size); + return -ENODATA; + } + + min_size = sizeof(*bpdt_header); + if (layout->boot1.size < min_size) { + gt_err(gt, "GSC FW boot section too small for BPDT header: %u < %zu\n", + layout->boot1.size, min_size); + return -ENODATA; + } + + bpdt_header = data + layout->boot1.offset; + if (bpdt_header->signature != INTEL_GSC_BPDT_HEADER_SIGNATURE) { + gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n", + bpdt_header->signature); + return -EINVAL; + } + + min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count; + if (layout->boot1.size < min_size) { + gt_err(gt, "GSC FW boot section too small for BPDT entries: %u < %zu\n", + layout->boot1.size, min_size); + return -ENODATA; + } + + bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header); + for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) { + if ((bpdt_entry->type & INTEL_GSC_BPDT_ENTRY_TYPE_MASK) != + INTEL_GSC_BPDT_ENTRY_TYPE_GSC_RBE) + continue; + + cpd_header = (void *)bpdt_header + bpdt_entry->sub_partition_offset; + min_size = bpdt_entry->sub_partition_offset + sizeof(*cpd_header); + break; + } + + if (!cpd_header) { + gt_err(gt, "couldn't find CPD header in GSC binary!\n"); + return -ENODATA; + } + + if (layout->boot1.size < min_size) { + gt_err(gt, "GSC FW boot section too small for CPD header: %u < %zu\n", + layout->boot1.size, min_size); + return -ENODATA; + } + + if (cpd_header->header_marker != INTEL_GSC_CPD_HEADER_MARKER) { + gt_err(gt, "invalid marker for CPD header in GSC bin: 0x%08x!\n", + cpd_header->header_marker); + return -EINVAL; + } + + min_size += sizeof(*cpd_entry) * cpd_header->num_of_entries; + if (layout->boot1.size < min_size) { + gt_err(gt, "GSC FW boot section too small for CPD entries: %u < %zu\n", + layout->boot1.size, min_size); + return -ENODATA; + } + + cpd_entry = (void *)cpd_header + cpd_header->header_length; + for (i = 0; i < cpd_header->num_of_entries; i++, cpd_entry++) { + if (strcmp(cpd_entry->name, "RBEP.man") == 0) { + manifest = (void *)cpd_header + cpd_entry_offset(cpd_entry); + intel_uc_fw_version_from_gsc_manifest(&gsc->release, + manifest); + gsc->security_version = manifest->security_version; + break; + } + } + + return 0; } static int emit_gsc_fw_load(struct i915_request *rq, struct intel_gsc_uc *gsc) @@ -114,48 +282,25 @@ out_rq: static int gsc_fw_load_prepare(struct intel_gsc_uc *gsc) { struct intel_gt *gt = gsc_uc_to_gt(gsc); - struct drm_i915_private *i915 = gt->i915; - struct drm_i915_gem_object *obj; - void *src, *dst; + void *src; if (!gsc->local) return -ENODEV; - obj = gsc->local->obj; - - if (obj->base.size < gsc->fw.size) + if (gsc->local->size < gsc->fw.size) return -ENOSPC; - /* - * Wa_22016122933: For MTL the shared memory needs to be mapped - * as WC on CPU side and UC (PAT index 2) on GPU side - */ - if (IS_METEORLAKE(i915)) - i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); - - dst = i915_gem_object_pin_map_unlocked(obj, - i915_coherent_map_type(i915, obj, true)); - if (IS_ERR(dst)) - return PTR_ERR(dst); - src = i915_gem_object_pin_map_unlocked(gsc->fw.obj, - i915_coherent_map_type(i915, gsc->fw.obj, true)); - if (IS_ERR(src)) { - i915_gem_object_unpin_map(obj); + intel_gt_coherent_map_type(gt, gsc->fw.obj, true)); + if (IS_ERR(src)) return PTR_ERR(src); - } - memset(dst, 0, obj->base.size); - memcpy(dst, src, gsc->fw.size); + memcpy_toio(gsc->local_vaddr, src, gsc->fw.size); + memset_io(gsc->local_vaddr + gsc->fw.size, 0, gsc->local->size - gsc->fw.size); - /* - * Wa_22016122933: Making sure the data in dst is - * visible to GSC right away - */ intel_guc_write_barrier(>->uc.guc); i915_gem_object_unpin_map(gsc->fw.obj); - i915_gem_object_unpin_map(obj); return 0; } @@ -163,12 +308,94 @@ static int gsc_fw_load_prepare(struct intel_gsc_uc *gsc) static int gsc_fw_wait(struct intel_gt *gt) { return intel_wait_for_register(gt->uncore, - GSC_FW_STATUS_REG, - GSC_FW_INIT_COMPLETE_BIT, - GSC_FW_INIT_COMPLETE_BIT, + HECI_FWSTS(MTL_GSC_HECI1_BASE, 1), + HECI1_FWSTS1_INIT_COMPLETE, + HECI1_FWSTS1_INIT_COMPLETE, 500); } +struct intel_gsc_mkhi_header { + u8 group_id; +#define MKHI_GROUP_ID_GFX_SRV 0x30 + + u8 command; +#define MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION (0x42) + + u8 reserved; + u8 result; +} __packed; + +struct mtl_gsc_ver_msg_in { + struct intel_gsc_mtl_header header; + struct intel_gsc_mkhi_header mkhi; +} __packed; + +struct mtl_gsc_ver_msg_out { + struct intel_gsc_mtl_header header; + struct intel_gsc_mkhi_header mkhi; + u16 proj_major; + u16 compat_major; + u16 compat_minor; + u16 reserved[5]; +} __packed; + +#define GSC_VER_PKT_SZ SZ_4K + +static int gsc_fw_query_compatibility_version(struct intel_gsc_uc *gsc) +{ + struct intel_gt *gt = gsc_uc_to_gt(gsc); + struct mtl_gsc_ver_msg_in *msg_in; + struct mtl_gsc_ver_msg_out *msg_out; + struct i915_vma *vma; + u64 offset; + void *vaddr; + int err; + + err = intel_guc_allocate_and_map_vma(>->uc.guc, GSC_VER_PKT_SZ * 2, + &vma, &vaddr); + if (err) { + gt_err(gt, "failed to allocate vma for GSC version query\n"); + return err; + } + + offset = i915_ggtt_offset(vma); + msg_in = vaddr; + msg_out = vaddr + GSC_VER_PKT_SZ; + + intel_gsc_uc_heci_cmd_emit_mtl_header(&msg_in->header, + HECI_MEADDRESS_MKHI, + sizeof(*msg_in), 0); + msg_in->mkhi.group_id = MKHI_GROUP_ID_GFX_SRV; + msg_in->mkhi.command = MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION; + + err = intel_gsc_uc_heci_cmd_submit_packet(>->uc.gsc, + offset, + sizeof(*msg_in), + offset + GSC_VER_PKT_SZ, + GSC_VER_PKT_SZ); + if (err) { + gt_err(gt, + "failed to submit GSC request for compatibility version: %d\n", + err); + goto out_vma; + } + + if (msg_out->header.message_size != sizeof(*msg_out)) { + gt_err(gt, "invalid GSC reply length %u [expected %zu], s=0x%x, f=0x%x, r=0x%x\n", + msg_out->header.message_size, sizeof(*msg_out), + msg_out->header.status, msg_out->header.flags, msg_out->mkhi.result); + err = -EPROTO; + goto out_vma; + } + + gsc->fw.file_selected.ver.major = msg_out->compat_major; + gsc->fw.file_selected.ver.minor = msg_out->compat_minor; + +out_vma: + i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); + return err; +} + int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc) { struct intel_gt *gt = gsc_uc_to_gt(gsc); @@ -226,10 +453,24 @@ int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc) if (err) goto fail; + err = gsc_fw_query_compatibility_version(gsc); + if (err) + goto fail; + + /* we only support compatibility version 1.0 at the moment */ + err = intel_uc_check_file_version(gsc_fw, NULL); + if (err) + goto fail; + /* FW is not fully operational until we enable SW proxy */ intel_uc_fw_change_status(gsc_fw, INTEL_UC_FIRMWARE_TRANSFERRED); - gt_info(gt, "Loaded GSC firmware %s\n", gsc_fw->file_selected.path); + gt_info(gt, "Loaded GSC firmware %s (cv%u.%u, r%u.%u.%u.%u, svn %u)\n", + gsc_fw->file_selected.path, + gsc_fw->file_selected.ver.major, gsc_fw->file_selected.ver.minor, + gsc->release.major, gsc->release.minor, + gsc->release.patch, gsc->release.build, + gsc->security_version); return 0; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h index fff8928218df..bc9dd0de8aaf 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.h @@ -9,10 +9,13 @@ #include <linux/types.h> struct intel_gsc_uc; +struct intel_uc_fw; struct intel_uncore; +int intel_gsc_fw_get_binary_info(struct intel_uc_fw *gsc_fw, const void *data, size_t size); int intel_gsc_uc_fw_upload(struct intel_gsc_uc *gsc); bool intel_gsc_uc_fw_init_done(struct intel_gsc_uc *gsc); -bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc); +bool intel_gsc_uc_fw_proxy_init_done(struct intel_gsc_uc *gsc, bool needs_wakeref); +int intel_gsc_uc_fw_proxy_get_status(struct intel_gsc_uc *gsc); #endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c index c659cc01f32f..0d3b22a74365 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c @@ -7,10 +7,11 @@ #include "gt/intel_gt.h" #include "gt/intel_gt_print.h" -#include "intel_gsc_uc.h" #include "intel_gsc_fw.h" -#include "i915_drv.h" #include "intel_gsc_proxy.h" +#include "intel_gsc_uc.h" +#include "i915_drv.h" +#include "i915_reg.h" static void gsc_work(struct work_struct *work) { @@ -61,8 +62,18 @@ static void gsc_work(struct work_struct *work) } ret = intel_gsc_proxy_request_handler(gsc); - if (ret) + if (ret) { + if (actions & GSC_ACTION_FW_LOAD) { + /* + * A proxy failure right after firmware load means the proxy-init + * step has failed so mark GSC as not usable after this + */ + drm_err(>->i915->drm, + "GSC proxy handler failed to init\n"); + intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL); + } goto out_put; + } /* mark the GSC FW init as done the first time we run this */ if (actions & GSC_ACTION_FW_LOAD) { @@ -71,12 +82,13 @@ static void gsc_work(struct work_struct *work) * complete the request handling cleanly, so we need to check the * status register to check if the proxy init was actually successful */ - if (intel_gsc_uc_fw_proxy_init_done(gsc)) { + if (intel_gsc_uc_fw_proxy_init_done(gsc, false)) { drm_dbg(>->i915->drm, "GSC Proxy initialized\n"); intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_RUNNING); } else { drm_err(>->i915->drm, "GSC status reports proxy init not complete\n"); + intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL); } } } @@ -98,7 +110,7 @@ static bool gsc_engine_supported(struct intel_gt *gt) GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask); if (gt_is_root(gt)) - mask = RUNTIME_INFO(gt->i915)->platform_engine_mask; + mask = INTEL_INFO(gt->i915)->platform_engine_mask; else mask = gt->info.engine_mask; @@ -133,26 +145,85 @@ void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc) } } +static int gsc_allocate_and_map_vma(struct intel_gsc_uc *gsc, u32 size) +{ + struct intel_gt *gt = gsc_uc_to_gt(gsc); + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + void __iomem *vaddr; + int ret = 0; + + /* + * The GSC FW doesn't immediately suspend after becoming idle, so there + * is a chance that it could still be awake after we successfully + * return from the pci suspend function, even if there are no pending + * operations. + * The FW might therefore try to access memory for its suspend operation + * after the kernel has completed the HW suspend flow; this can cause + * issues if the FW is mapped in normal RAM memory, as some of the + * involved HW units might've already lost power. + * The driver must therefore avoid this situation and the recommended + * way to do so is to use stolen memory for the GSC memory allocation, + * because stolen memory takes a different path in HW and it is + * guaranteed to always work as long as the GPU itself is awake (which + * it must be if the GSC is awake). + */ + obj = i915_gem_object_create_stolen(gt->i915, size); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; + } + + vaddr = i915_vma_pin_iomap(vma); + i915_vma_unpin(vma); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + goto err; + } + + i915_vma_make_unshrinkable(vma); + + gsc->local = vma; + gsc->local_vaddr = vaddr; + + return 0; + +err: + i915_gem_object_put(obj); + return ret; +} + +static void gsc_unmap_and_free_vma(struct intel_gsc_uc *gsc) +{ + struct i915_vma *vma = fetch_and_zero(&gsc->local); + + if (!vma) + return; + + gsc->local_vaddr = NULL; + i915_vma_unpin_iomap(vma); + i915_gem_object_put(vma->obj); +} + int intel_gsc_uc_init(struct intel_gsc_uc *gsc) { static struct lock_class_key gsc_lock; struct intel_gt *gt = gsc_uc_to_gt(gsc); struct intel_engine_cs *engine = gt->engine[GSC0]; struct intel_context *ce; - struct i915_vma *vma; int err; err = intel_uc_fw_init(&gsc->fw); if (err) goto out; - vma = intel_guc_allocate_vma(>->uc.guc, SZ_8M); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); + err = gsc_allocate_and_map_vma(gsc, SZ_4M); + if (err) goto out_fw; - } - - gsc->local = vma; ce = intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_4K, I915_GEM_HWS_GSC_ADDR, @@ -173,7 +244,7 @@ int intel_gsc_uc_init(struct intel_gsc_uc *gsc) return 0; out_vma: - i915_vma_unpin_and_release(&gsc->local, 0); + gsc_unmap_and_free_vma(gsc); out_fw: intel_uc_fw_fini(&gsc->fw); out: @@ -197,7 +268,7 @@ void intel_gsc_uc_fini(struct intel_gsc_uc *gsc) if (gsc->ce) intel_engine_destroy_pinned_context(fetch_and_zero(&gsc->ce)); - i915_vma_unpin_and_release(&gsc->local, 0); + gsc_unmap_and_free_vma(gsc); intel_uc_fw_fini(&gsc->fw); } @@ -245,3 +316,45 @@ void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc) queue_work(gsc->wq, &gsc->work); } + +void intel_gsc_uc_load_status(struct intel_gsc_uc *gsc, struct drm_printer *p) +{ + struct intel_gt *gt = gsc_uc_to_gt(gsc); + struct intel_uncore *uncore = gt->uncore; + intel_wakeref_t wakeref; + + if (!intel_gsc_uc_is_supported(gsc)) { + drm_printf(p, "GSC not supported\n"); + return; + } + + if (!intel_gsc_uc_is_wanted(gsc)) { + drm_printf(p, "GSC disabled\n"); + return; + } + + drm_printf(p, "GSC firmware: %s\n", gsc->fw.file_selected.path); + if (gsc->fw.file_selected.path != gsc->fw.file_wanted.path) + drm_printf(p, "GSC firmware wanted: %s\n", gsc->fw.file_wanted.path); + drm_printf(p, "\tstatus: %s\n", intel_uc_fw_status_repr(gsc->fw.status)); + + drm_printf(p, "Release: %u.%u.%u.%u\n", + gsc->release.major, gsc->release.minor, + gsc->release.patch, gsc->release.build); + + drm_printf(p, "Compatibility Version: %u.%u [min expected %u.%u]\n", + gsc->fw.file_selected.ver.major, gsc->fw.file_selected.ver.minor, + gsc->fw.file_wanted.ver.major, gsc->fw.file_wanted.ver.minor); + + drm_printf(p, "SVN: %u\n", gsc->security_version); + + with_intel_runtime_pm(uncore->rpm, wakeref) { + u32 i; + + for (i = 1; i <= 6; i++) { + u32 status = intel_uncore_read(uncore, + HECI_FWSTS(MTL_GSC_HECI1_BASE, i)); + drm_printf(p, "HECI1 FWSTST%u = 0x%08x\n", i, status); + } + } +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h index a2a0813b8a76..c8082cf200fc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h @@ -8,6 +8,7 @@ #include "intel_uc_fw.h" +struct drm_printer; struct i915_vma; struct intel_context; struct i915_gsc_proxy_component; @@ -17,7 +18,26 @@ struct intel_gsc_uc { struct intel_uc_fw fw; /* GSC-specific additions */ + + /* + * The GSC has 3 version numbers: + * - Release version (incremented with each build) + * - Security version (incremented on security fix) + * - Compatibility version (incremented on interface change) + * + * The one we care about to use the binary is the last one, so that's + * the one we save inside the intel_uc_fw structure. The other two + * versions are only used for debug/info purposes, so we save them here. + * + * Note that the release and security versions are available in the + * binary header, while the compatibility version must be queried after + * loading the binary. + */ + struct intel_uc_fw_ver release; + u32 security_version; + struct i915_vma *local; /* private memory for GSC usage */ + void __iomem *local_vaddr; /* pointer to access the private memory */ struct intel_context *ce; /* for submission to GSC FW via GSC engine */ /* for delayed load and proxy handling */ @@ -44,6 +64,7 @@ void intel_gsc_uc_suspend(struct intel_gsc_uc *gsc); void intel_gsc_uc_resume(struct intel_gsc_uc *gsc); void intel_gsc_uc_flush_work(struct intel_gsc_uc *gsc); void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc); +void intel_gsc_uc_load_status(struct intel_gsc_uc *gsc, struct drm_printer *p); static inline bool intel_gsc_uc_is_supported(struct intel_gsc_uc *gsc) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.c new file mode 100644 index 000000000000..5baacd822a1c --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include <drm/drm_print.h> + +#include "gt/intel_gt.h" +#include "gt/intel_gt_debugfs.h" +#include "gt/intel_gt_print.h" +#include "intel_gsc_uc.h" +#include "intel_gsc_uc_debugfs.h" +#include "i915_drv.h" + +static int gsc_info_show(struct seq_file *m, void *data) +{ + struct drm_printer p = drm_seq_file_printer(m); + struct intel_gsc_uc *gsc = m->private; + + if (!intel_gsc_uc_is_supported(gsc)) + return -ENODEV; + + intel_gsc_uc_load_status(gsc, &p); + + return 0; +} +DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(gsc_info); + +void intel_gsc_uc_debugfs_register(struct intel_gsc_uc *gsc_uc, struct dentry *root) +{ + static const struct intel_gt_debugfs_file files[] = { + { "gsc_info", &gsc_info_fops, NULL }, + }; + + if (!intel_gsc_uc_is_supported(gsc_uc)) + return; + + intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), gsc_uc); +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.h new file mode 100644 index 000000000000..3415ad39aabb --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_debugfs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef DEBUGFS_GSC_UC_H +#define DEBUGFS_GSC_UC_H + +struct intel_gsc_uc; +struct dentry; + +void intel_gsc_uc_debugfs_register(struct intel_gsc_uc *gsc, struct dentry *root); + +#endif /* DEBUGFS_GSC_UC_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h index ef70e304904a..09d3fbdad05a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc_heci_cmd_submit.h @@ -17,6 +17,7 @@ struct intel_gsc_mtl_header { #define GSC_HECI_VALIDITY_MARKER 0xA578875A u8 heci_client_id; +#define HECI_MEADDRESS_MKHI 7 #define HECI_MEADDRESS_PROXY 10 #define HECI_MEADDRESS_PXP 17 #define HECI_MEADDRESS_HDCP 18 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2eb891b270ae..569b5fe94c41 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -745,10 +745,11 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) return ERR_CAST(obj); /* - * Wa_22016122933: For MTL the shared memory needs to be mapped - * as WC on CPU side and UC (PAT index 2) on GPU side + * Wa_22016122933: For Media version 13.0, all Media GT shared + * memory needs to be mapped as WC on CPU side and UC (PAT + * index 2) on GPU side. */ - if (IS_METEORLAKE(gt->i915)) + if (intel_gt_needs_wa_22016122933(gt)) i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); vma = i915_vma_instance(obj, >->ggtt->vm, NULL); @@ -792,8 +793,8 @@ int intel_guc_allocate_and_map_vma(struct intel_guc *guc, u32 size, return PTR_ERR(vma); vaddr = i915_gem_object_pin_map_unlocked(vma->obj, - i915_coherent_map_type(guc_to_gt(guc)->i915, - vma->obj, true)); + intel_gt_coherent_map_type(guc_to_gt(guc), + vma->obj, true)); if (IS_ERR(vaddr)) { i915_vma_unpin_and_release(&vma, 0); return PTR_ERR(vaddr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index f28a3a83742d..97eadd08181d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -960,10 +960,6 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg) /* now update descriptor */ WRITE_ONCE(desc->head, head); - /* - * Wa_22016122933: Making sure the head update is - * visible to GuC right away - */ intel_guc_write_barrier(ct_to_guc(ct)); return available - len; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 364d0d546ec8..0f79cb658518 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -251,9 +251,11 @@ static int guc_wait_ucode(struct intel_guc *guc) if (ret == 0) ret = -ENXIO; } else if (delta_ms > 200) { - guc_warn(guc, "excessive init time: %lldms! [freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d]\n", - delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), - before_freq, status, count, ret); + guc_warn(guc, "excessive init time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", + delta_ms, status, count, ret); + guc_warn(guc, "excessive init time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", + intel_rps_read_actual_frequency(&uncore->gt->rps), before_freq, + intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); } else { guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c index 852bea0208ce..cc9569af7f0c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c @@ -94,7 +94,7 @@ static int guc_hwconfig_fill_buffer(struct intel_guc *guc, struct intel_hwconfig static bool has_table(struct drm_i915_private *i915) { - if (IS_ALDERLAKE_P(i915) && !IS_ADLP_N(i915)) + if (IS_ALDERLAKE_P(i915) && !IS_ALDERLAKE_P_N(i915)) return true; if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) return true; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index ee9f83af7cf6..477df260ae3a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -470,12 +470,19 @@ int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val) ret = slpc_set_param(slpc, SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY, val); - if (ret) + if (ret) { guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n", val, ERR_PTR(ret)); - else + } else { slpc->ignore_eff_freq = val; + /* Set min to RPn when we disable efficient freq */ + if (val) + ret = slpc_set_param(slpc, + SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, + slpc->min_freq); + } + intel_runtime_pm_put(&i915->runtime_pm, wakeref); mutex_unlock(&slpc->lock); return ret; @@ -602,9 +609,8 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) return ret; if (!slpc->min_freq_softlimit) { - ret = intel_guc_slpc_get_min_freq(slpc, &slpc->min_freq_softlimit); - if (unlikely(ret)) - return ret; + /* Min softlimit is initialized to RPn */ + slpc->min_freq_softlimit = slpc->min_freq; slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit; } else { return intel_guc_slpc_set_min_freq(slpc, @@ -755,6 +761,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) return ret; } + /* Set cached value of ignore efficient freq */ + intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq); + /* Revert SLPC min/max to softlimits if necessary */ ret = slpc_set_softlimits(slpc); if (unlikely(ret)) { @@ -765,9 +774,6 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) /* Set cached media freq ratio mode */ intel_guc_slpc_set_media_ratio_mode(slpc, slpc->media_ratio_mode); - /* Set cached value of ignore efficient freq */ - intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq); - return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index ddd146265beb..ba9e07fc2b57 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -26,6 +26,7 @@ * The kernel driver is only responsible for loading the HuC firmware and * triggering its security authentication. This is done differently depending * on the platform: + * * - older platforms (from Gen9 to most Gen12s): the load is performed via DMA * and the authentication via GuC * - DG2: load and authentication are both performed via GSC. @@ -33,6 +34,7 @@ * not-DG2 older platforms), while the authentication is done in 2-steps, * a first auth for clear-media workloads via GuC and a second one for all * workloads via GSC. + * * On platforms where the GuC does the authentication, to correctly do so the * HuC binary must be loaded before the GuC one. * Loading the HuC is optional; however, not using the HuC might negatively @@ -265,7 +267,7 @@ static bool vcs_supported(struct intel_gt *gt) GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask); if (gt_is_root(gt)) - mask = RUNTIME_INFO(gt->i915)->platform_engine_mask; + mask = INTEL_INFO(gt->i915)->platform_engine_mask; else mask = gt->info.engine_mask; @@ -308,9 +310,9 @@ void intel_huc_init_early(struct intel_huc *huc) huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HUC_LOAD_SUCCESSFUL; huc->status[INTEL_HUC_AUTH_BY_GSC].value = HUC_LOAD_SUCCESSFUL; } else { - huc->status[INTEL_HUC_AUTH_BY_GSC].reg = HECI_FWSTS5(MTL_GSC_HECI1_BASE); - huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HECI_FWSTS5_HUC_AUTH_DONE; - huc->status[INTEL_HUC_AUTH_BY_GSC].value = HECI_FWSTS5_HUC_AUTH_DONE; + huc->status[INTEL_HUC_AUTH_BY_GSC].reg = HECI_FWSTS(MTL_GSC_HECI1_BASE, 5); + huc->status[INTEL_HUC_AUTH_BY_GSC].mask = HECI1_FWSTS5_HUC_AUTH_DONE; + huc->status[INTEL_HUC_AUTH_BY_GSC].value = HECI1_FWSTS5_HUC_AUTH_DONE; } } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c index e608152fecfc..b648238cc675 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c @@ -27,7 +27,6 @@ struct mtl_huc_auth_msg_out { int intel_huc_fw_auth_via_gsccs(struct intel_huc *huc) { struct intel_gt *gt = huc_to_gt(huc); - struct drm_i915_private *i915 = gt->i915; struct drm_i915_gem_object *obj; struct mtl_huc_auth_msg_in *msg_in; struct mtl_huc_auth_msg_out *msg_out; @@ -43,7 +42,7 @@ int intel_huc_fw_auth_via_gsccs(struct intel_huc *huc) pkt_offset = i915_ggtt_offset(huc->heci_pkt); pkt_vaddr = i915_gem_object_pin_map_unlocked(obj, - i915_coherent_map_type(i915, obj, true)); + intel_gt_coherent_map_type(gt, obj, true)); if (IS_ERR(pkt_vaddr)) return PTR_ERR(pkt_vaddr); @@ -107,15 +106,6 @@ out_unpin: return err; } -static void get_version_from_gsc_manifest(struct intel_uc_fw_ver *ver, const void *data) -{ - const struct intel_gsc_manifest_header *manifest = data; - - ver->major = manifest->fw_version.major; - ver->minor = manifest->fw_version.minor; - ver->patch = manifest->fw_version.hotfix; -} - static bool css_valid(const void *data, size_t size) { const struct uc_css_header *css = data; @@ -227,8 +217,8 @@ int intel_huc_fw_get_binary_info(struct intel_uc_fw *huc_fw, const void *data, s for (i = 0; i < header->num_of_entries; i++, entry++) { if (strcmp(entry->name, "HUCP.man") == 0) - get_version_from_gsc_manifest(&huc_fw->file_selected.ver, - data + entry_offset(entry)); + intel_uc_fw_version_from_gsc_manifest(&huc_fw->file_selected.ver, + data + entry_offset(entry)); if (strcmp(entry->name, "huc_fw") == 0) { u32 offset = entry_offset(entry); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 18250fb64bd8..98b103375b7a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -43,7 +43,7 @@ static void uc_expand_default_options(struct intel_uc *uc) } /* Intermediate platforms are HuC authentication only */ - if (IS_ALDERLAKE_S(i915) && !IS_ADLS_RPLS(i915)) { + if (IS_ALDERLAKE_S(i915) && !IS_RAPTORLAKE_S(i915)) { i915->params.enable_guc = ENABLE_GUC_LOAD_HUC; return; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c index 2f93cc4e408a..6d541c866edb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c @@ -10,6 +10,7 @@ #include "gt/intel_gt_debugfs.h" #include "intel_guc_debugfs.h" +#include "intel_gsc_uc_debugfs.h" #include "intel_huc_debugfs.h" #include "intel_uc.h" #include "intel_uc_debugfs.h" @@ -58,6 +59,7 @@ void intel_uc_debugfs_register(struct intel_uc *uc, struct dentry *gt_root) intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), uc); + intel_gsc_uc_debugfs_register(&uc->gsc, root); intel_guc_debugfs_register(&uc->guc, root); intel_huc_debugfs_register(&uc->huc, root); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 944725e62414..8be005de1d28 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -11,7 +11,10 @@ #include <drm/drm_print.h> #include "gem/i915_gem_lmem.h" +#include "gt/intel_gt.h" #include "gt/intel_gt_print.h" +#include "intel_gsc_binary_headers.h" +#include "intel_gsc_fw.h" #include "intel_uc_fw.h" #include "intel_uc_fw_abi.h" #include "i915_drv.h" @@ -277,7 +280,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) * ADL-S, otherwise the GuC might attempt to fetch a config table that * does not exist. */ - if (IS_ADLP_N(i915)) + if (IS_ALDERLAKE_P_N(i915)) p = INTEL_ALDERLAKE_S; GEM_BUG_ON(uc_fw->type >= ARRAY_SIZE(blobs_all)); @@ -468,6 +471,17 @@ static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc } } +void intel_uc_fw_version_from_gsc_manifest(struct intel_uc_fw_ver *ver, + const void *data) +{ + const struct intel_gsc_manifest_header *manifest = data; + + ver->major = manifest->fw_version.major; + ver->minor = manifest->fw_version.minor; + ver->patch = manifest->fw_version.hotfix; + ver->build = manifest->fw_version.build; +} + /** * intel_uc_fw_init_early - initialize the uC object and select the firmware * @uc_fw: uC firmware @@ -668,13 +682,18 @@ static int check_gsc_manifest(struct intel_gt *gt, const struct firmware *fw, struct intel_uc_fw *uc_fw) { - if (uc_fw->type != INTEL_UC_FW_TYPE_HUC) { - gt_err(gt, "trying to GSC-parse a non-HuC binary"); + switch (uc_fw->type) { + case INTEL_UC_FW_TYPE_HUC: + intel_huc_fw_get_binary_info(uc_fw, fw->data, fw->size); + break; + case INTEL_UC_FW_TYPE_GSC: + intel_gsc_fw_get_binary_info(uc_fw, fw->data, fw->size); + break; + default: + MISSING_CASE(uc_fw->type); return -EINVAL; } - intel_huc_fw_get_binary_info(uc_fw, fw->data, fw->size); - if (uc_fw->dma_start_offset) { u32 delta = uc_fw->dma_start_offset; @@ -734,10 +753,6 @@ static int check_fw_header(struct intel_gt *gt, { int err = 0; - /* GSC FW version is queried after the FW is loaded */ - if (uc_fw->type == INTEL_UC_FW_TYPE_GSC) - return 0; - if (uc_fw->has_gsc_headers) err = check_gsc_manifest(gt, fw, uc_fw); else @@ -773,6 +788,80 @@ static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware ** return 0; } +static int check_mtl_huc_guc_compatibility(struct intel_gt *gt, + struct intel_uc_fw_file *huc_selected) +{ + struct intel_uc_fw_file *guc_selected = >->uc.guc.fw.file_selected; + struct intel_uc_fw_ver *huc_ver = &huc_selected->ver; + struct intel_uc_fw_ver *guc_ver = &guc_selected->ver; + bool new_huc, new_guc; + + /* we can only do this check after having fetched both GuC and HuC */ + GEM_BUG_ON(!huc_selected->path || !guc_selected->path); + + /* + * Due to changes in the authentication flow for MTL, HuC 8.5.1 or newer + * requires GuC 70.7.0 or newer. Older HuC binaries will instead require + * GuC < 70.7.0. + */ + new_huc = huc_ver->major > 8 || + (huc_ver->major == 8 && huc_ver->minor > 5) || + (huc_ver->major == 8 && huc_ver->minor == 5 && huc_ver->patch >= 1); + + new_guc = guc_ver->major > 70 || + (guc_ver->major == 70 && guc_ver->minor >= 7); + + if (new_huc != new_guc) { + UNEXPECTED(gt, "HuC %u.%u.%u is incompatible with GuC %u.%u.%u\n", + huc_ver->major, huc_ver->minor, huc_ver->patch, + guc_ver->major, guc_ver->minor, guc_ver->patch); + gt_info(gt, "MTL GuC 70.7.0+ and HuC 8.5.1+ don't work with older releases\n"); + return -ENOEXEC; + } + + return 0; +} + +int intel_uc_check_file_version(struct intel_uc_fw *uc_fw, bool *old_ver) +{ + struct intel_gt *gt = __uc_fw_to_gt(uc_fw); + struct intel_uc_fw_file *wanted = &uc_fw->file_wanted; + struct intel_uc_fw_file *selected = &uc_fw->file_selected; + int ret; + + /* + * MTL has some compatibility issues with early GuC/HuC binaries + * not working with newer ones. This is specific to MTL and we + * don't expect it to extend to other platforms. + */ + if (IS_METEORLAKE(gt->i915) && uc_fw->type == INTEL_UC_FW_TYPE_HUC) { + ret = check_mtl_huc_guc_compatibility(gt, selected); + if (ret) + return ret; + } + + if (!wanted->ver.major || !selected->ver.major) + return 0; + + /* Check the file's major version was as it claimed */ + if (selected->ver.major != wanted->ver.major) { + UNEXPECTED(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n", + intel_uc_fw_type_repr(uc_fw->type), selected->path, + selected->ver.major, selected->ver.minor, + wanted->ver.major, wanted->ver.minor); + if (!intel_uc_fw_is_overridden(uc_fw)) + return -ENOEXEC; + } else if (old_ver) { + if (selected->ver.minor < wanted->ver.minor) + *old_ver = true; + else if ((selected->ver.minor == wanted->ver.minor) && + (selected->ver.patch < wanted->ver.patch)) + *old_ver = true; + } + + return 0; +} + /** * intel_uc_fw_fetch - fetch uC firmware * @uc_fw: uC firmware @@ -840,25 +929,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) goto fail; } - if (uc_fw->file_wanted.ver.major && uc_fw->file_selected.ver.major) { - /* Check the file's major version was as it claimed */ - if (uc_fw->file_selected.ver.major != uc_fw->file_wanted.ver.major) { - UNEXPECTED(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n", - intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path, - uc_fw->file_selected.ver.major, uc_fw->file_selected.ver.minor, - uc_fw->file_wanted.ver.major, uc_fw->file_wanted.ver.minor); - if (!intel_uc_fw_is_overridden(uc_fw)) { - err = -ENOEXEC; - goto fail; - } - } else { - if (uc_fw->file_selected.ver.minor < uc_fw->file_wanted.ver.minor) - old_ver = true; - else if ((uc_fw->file_selected.ver.minor == uc_fw->file_wanted.ver.minor) && - (uc_fw->file_selected.ver.patch < uc_fw->file_wanted.ver.patch)) - old_ver = true; - } - } + err = intel_uc_check_file_version(uc_fw, &old_ver); + if (err) + goto fail; if (old_ver && uc_fw->file_selected.ver.major) { /* Preserve the version that was really wanted */ @@ -1125,7 +1198,7 @@ static int uc_fw_rsa_data_create(struct intel_uc_fw *uc_fw) return PTR_ERR(vma); vaddr = i915_gem_object_pin_map_unlocked(vma->obj, - i915_coherent_map_type(gt->i915, vma->obj, true)); + intel_gt_coherent_map_type(gt, vma->obj, true)); if (IS_ERR(vaddr)) { i915_vma_unpin_and_release(&vma, 0); err = PTR_ERR(vaddr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h index 054f02811971..9a431726c8d5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h @@ -70,6 +70,7 @@ struct intel_uc_fw_ver { u32 major; u32 minor; u32 patch; + u32 build; }; /* @@ -289,6 +290,9 @@ static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw) return __intel_uc_fw_get_upload_size(uc_fw); } +void intel_uc_fw_version_from_gsc_manifest(struct intel_uc_fw_ver *ver, + const void *data); +int intel_uc_check_file_version(struct intel_uc_fw *uc_fw, bool *old_ver); void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type, bool needs_ggtt_mapping); diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index 1fd760539f77..bfb72143566f 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -204,9 +204,9 @@ static int intel_guc_steal_guc_ids(void *arg) if (IS_ERR(rq)) { ret = PTR_ERR(rq); rq = NULL; - if (ret != -EAGAIN) { - guc_err(guc, "Failed to create request %d: %pe\n", - context_index, ERR_PTR(ret)); + if ((ret != -EAGAIN) || !last) { + guc_err(guc, "Failed to create %srequest %d: %pe\n", + last ? "" : "first ", context_index, ERR_PTR(ret)); goto err_spin_rq; } } else { diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c index 2a0438f12a14..af9afdb53c7f 100644 --- a/drivers/gpu/drm/i915/gvt/edid.c +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -491,7 +491,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, return; } - msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, reg); + msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, value); // check the msg in DATA register. msg = vgpu_vreg(vgpu, offset + 4); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index f4055804aad1..a5c8005ec484 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -974,7 +974,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) context_page_num = rq->engine->context_size; context_page_num = context_page_num >> PAGE_SHIFT; - if (IS_BROADWELL(rq->engine->i915) && rq->engine->id == RCS0) + if (IS_BROADWELL(rq->i915) && rq->engine->id == RCS0) context_page_num = 19; context_base = (void *) ctx->lrc_reg_state - diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 8ef93889061a..5ec293011d99 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -449,8 +449,11 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq) } } while (unlikely(is_barrier(active))); - if (!__i915_active_fence_set(active, fence)) + fence = __i915_active_fence_set(active, fence); + if (!fence) __i915_active_acquire(ref); + else + dma_fence_put(fence); out: i915_active_release(ref); @@ -469,13 +472,9 @@ __i915_active_set_fence(struct i915_active *ref, return NULL; } - rcu_read_lock(); prev = __i915_active_fence_set(active, fence); - if (prev) - prev = dma_fence_get_rcu(prev); - else + if (!prev) __i915_active_acquire(ref); - rcu_read_unlock(); return prev; } @@ -1019,10 +1018,11 @@ void i915_request_add_active_barriers(struct i915_request *rq) * * Records the new @fence as the last active fence along its timeline in * this active tracker, moving the tracking callbacks from the previous - * fence onto this one. Returns the previous fence (if not already completed), - * which the caller must ensure is executed before the new fence. To ensure - * that the order of fences within the timeline of the i915_active_fence is - * understood, it should be locked by the caller. + * fence onto this one. Gets and returns a reference to the previous fence + * (if not already completed), which the caller must put after making sure + * that it is executed before the new fence. To ensure that the order of + * fences within the timeline of the i915_active_fence is understood, it + * should be locked by the caller. */ struct dma_fence * __i915_active_fence_set(struct i915_active_fence *active, @@ -1031,7 +1031,23 @@ __i915_active_fence_set(struct i915_active_fence *active, struct dma_fence *prev; unsigned long flags; - if (fence == rcu_access_pointer(active->fence)) + /* + * In case of fences embedded in i915_requests, their memory is + * SLAB_FAILSAFE_BY_RCU, then it can be reused right after release + * by new requests. Then, there is a risk of passing back a pointer + * to a new, completely unrelated fence that reuses the same memory + * while tracked under a different active tracker. Combined with i915 + * perf open/close operations that build await dependencies between + * engine kernel context requests and user requests from different + * timelines, this can lead to dependency loops and infinite waits. + * + * As a countermeasure, we try to get a reference to the active->fence + * first, so if we succeed and pass it back to our user then it is not + * released and potentially reused by an unrelated request before the + * user has a chance to set up an await dependency on it. + */ + prev = i915_active_fence_get(active); + if (fence == prev) return fence; GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)); @@ -1040,27 +1056,56 @@ __i915_active_fence_set(struct i915_active_fence *active, * Consider that we have two threads arriving (A and B), with * C already resident as the active->fence. * - * A does the xchg first, and so it sees C or NULL depending - * on the timing of the interrupt handler. If it is NULL, the - * previous fence must have been signaled and we know that - * we are first on the timeline. If it is still present, - * we acquire the lock on that fence and serialise with the interrupt - * handler, in the process removing it from any future interrupt - * callback. A will then wait on C before executing (if present). - * - * As B is second, it sees A as the previous fence and so waits for - * it to complete its transition and takes over the occupancy for - * itself -- remembering that it needs to wait on A before executing. + * Both A and B have got a reference to C or NULL, depending on the + * timing of the interrupt handler. Let's assume that if A has got C + * then it has locked C first (before B). * * Note the strong ordering of the timeline also provides consistent * nesting rules for the fence->lock; the inner lock is always the * older lock. */ spin_lock_irqsave(fence->lock, flags); - prev = xchg(__active_fence_slot(active), fence); - if (prev) { - GEM_BUG_ON(prev == fence); + if (prev) spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); + + /* + * A does the cmpxchg first, and so it sees C or NULL, as before, or + * something else, depending on the timing of other threads and/or + * interrupt handler. If not the same as before then A unlocks C if + * applicable and retries, starting from an attempt to get a new + * active->fence. Meanwhile, B follows the same path as A. + * Once A succeeds with cmpxch, B fails again, retires, gets A from + * active->fence, locks it as soon as A completes, and possibly + * succeeds with cmpxchg. + */ + while (cmpxchg(__active_fence_slot(active), prev, fence) != prev) { + if (prev) { + spin_unlock(prev->lock); + dma_fence_put(prev); + } + spin_unlock_irqrestore(fence->lock, flags); + + prev = i915_active_fence_get(active); + GEM_BUG_ON(prev == fence); + + spin_lock_irqsave(fence->lock, flags); + if (prev) + spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); + } + + /* + * If prev is NULL then the previous fence must have been signaled + * and we know that we are first on the timeline. If it is still + * present then, having the lock on that fence already acquired, we + * serialise with the interrupt handler, in the process of removing it + * from any future interrupt callback. A will then wait on C before + * executing (if present). + * + * As B is second, it sees A as the previous fence and so waits for + * it to complete its transition and takes over the occupancy for + * itself -- remembering that it needs to wait on A before executing. + */ + if (prev) { __list_del_entry(&active->cb.node); spin_unlock(prev->lock); /* serialise with prev->cb_list */ } @@ -1077,11 +1122,7 @@ int i915_active_fence_set(struct i915_active_fence *active, int err = 0; /* Must maintain timeline ordering wrt previous active requests */ - rcu_read_lock(); fence = __i915_active_fence_set(active, &rq->fence); - if (fence) /* but the previous fence may not belong to that timeline! */ - fence = dma_fence_get_rcu(fence); - rcu_read_unlock(); if (fence) { err = i915_request_await_dma_fence(rq, fence); dma_fence_put(fence); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 76ccd4e03e31..4de44cf1026d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -67,6 +67,7 @@ static int i915_capabilities(struct seq_file *m, void *data) seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(i915)); intel_device_info_print(INTEL_INFO(i915), RUNTIME_INFO(i915), &p); + intel_display_device_info_print(DISPLAY_INFO(i915), DISPLAY_RUNTIME_INFO(i915), &p); i915_print_iommu_status(i915, &p); intel_gt_info_print(&to_gt(i915)->info, &p); intel_driver_caps_print(&i915->caps, &p); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 0ad0c5885ec2..ec4d26b3c17c 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -175,7 +175,7 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) { bool pre = false; - pre |= IS_HSW_EARLY_SDV(dev_priv); + pre |= IS_HASWELL_EARLY_SDV(dev_priv); pre |= IS_SKYLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x6; pre |= IS_BROXTON(dev_priv) && INTEL_REVID(dev_priv) < 0xA; pre |= IS_KABYLAKE(dev_priv) && INTEL_REVID(dev_priv) < 0x1; @@ -443,7 +443,6 @@ static int i915_pcode_init(struct drm_i915_private *i915) static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); - struct pci_dev *root_pdev; int ret; if (i915_inject_probe_failure(dev_priv)) @@ -557,15 +556,6 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) intel_bw_init_hw(dev_priv); - /* - * FIXME: Temporary hammer to avoid freezing the machine on our DGFX - * This should be totally removed when we handle the pci states properly - * on runtime PM and on s2idle cases. - */ - root_pdev = pcie_find_root_port(pdev); - if (root_pdev) - pci_d3cold_disable(root_pdev); - return 0; err_opregion: @@ -591,7 +581,6 @@ err_perf: static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); - struct pci_dev *root_pdev; i915_perf_fini(dev_priv); @@ -599,10 +588,6 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) if (pdev->msi_enabled) pci_disable_msi(pdev); - - root_pdev = pcie_find_root_port(pdev); - if (root_pdev) - pci_d3cold_enable(root_pdev); } /** @@ -711,6 +696,8 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) intel_device_info_print(INTEL_INFO(dev_priv), RUNTIME_INFO(dev_priv), &p); + intel_display_device_info_print(DISPLAY_INFO(dev_priv), + DISPLAY_RUNTIME_INFO(dev_priv), &p); i915_print_iommu_status(dev_priv, &p); for_each_gt(gt, dev_priv, i) intel_gt_info_print(>->info, &p); @@ -1517,6 +1504,8 @@ static int intel_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *root_pdev; struct intel_gt *gt; int ret, i; @@ -1568,6 +1557,15 @@ static int intel_runtime_suspend(struct device *kdev) drm_err(&dev_priv->drm, "Unclaimed access detected prior to suspending\n"); + /* + * FIXME: Temporary hammer to avoid freezing the machine on our DGFX + * This should be totally removed when we handle the pci states properly + * on runtime PM. + */ + root_pdev = pcie_find_root_port(pdev); + if (root_pdev) + pci_d3cold_disable(root_pdev); + rpm->suspended = true; /* @@ -1606,6 +1604,8 @@ static int intel_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *root_pdev; struct intel_gt *gt; int ret, i; @@ -1619,6 +1619,11 @@ static int intel_runtime_resume(struct device *kdev) intel_opregion_notify_adapter(dev_priv, PCI_D0); rpm->suspended = false; + + root_pdev = pcie_find_root_port(pdev); + if (root_pdev) + pci_d3cold_enable(root_pdev); + if (intel_uncore_unclaimed_mmio(&dev_priv->uncore)) drm_dbg(&dev_priv->drm, "Unclaimed access during suspend, bios?\n"); @@ -1818,8 +1823,6 @@ static const struct drm_driver i915_drm_driver = { .postclose = i915_driver_postclose, .show_fdinfo = PTR_IF(IS_ENABLED(CONFIG_PROC_FS), i915_drm_client_fdinfo), - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = i915_gem_prime_import, .dumb_create = i915_gem_dumb_create, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b4cf6f0f636d..7a8ce7239bc9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -203,9 +203,8 @@ struct drm_i915_private { /* i915 device parameters */ struct i915_params params; - const struct intel_device_info __info; /* Use INTEL_INFO() to access. */ + const struct intel_device_info *__info; /* Use INTEL_INFO() to access. */ struct intel_runtime_info __runtime; /* Use RUNTIME_INFO() to access. */ - struct intel_display_runtime_info __display_runtime; /* Access with DISPLAY_RUNTIME_INFO() */ struct intel_driver_caps caps; struct i915_dsm dsm; @@ -324,7 +323,6 @@ struct drm_i915_private { /* * i915->gt[0] == &i915->gt0 */ -#define I915_MAX_GT 2 struct intel_gt *gt[I915_MAX_GT]; struct kobject *sysfs_gt; @@ -416,10 +414,10 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) (engine__) && (engine__)->uabi_class == (class__); \ (engine__) = rb_to_uabi_engine(rb_next(&(engine__)->uabi_node))) -#define INTEL_INFO(i915) (&(i915)->__info) -#define DISPLAY_INFO(i915) (INTEL_INFO(i915)->display) +#define INTEL_INFO(i915) ((i915)->__info) #define RUNTIME_INFO(i915) (&(i915)->__runtime) -#define DISPLAY_RUNTIME_INFO(i915) (&(i915)->__display_runtime) +#define DISPLAY_INFO(i915) ((i915)->display.info.__device_info) +#define DISPLAY_RUNTIME_INFO(i915) (&(i915)->display.info.__runtime_info) #define DRIVER_CAPS(i915) (&(i915)->caps) #define INTEL_DEVID(i915) (RUNTIME_INFO(i915)->device_id) @@ -563,8 +561,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_COFFEELAKE(i915) IS_PLATFORM(i915, INTEL_COFFEELAKE) #define IS_COMETLAKE(i915) IS_PLATFORM(i915, INTEL_COMETLAKE) #define IS_ICELAKE(i915) IS_PLATFORM(i915, INTEL_ICELAKE) -#define IS_JSL_EHL(i915) (IS_PLATFORM(i915, INTEL_JASPERLAKE) || \ - IS_PLATFORM(i915, INTEL_ELKHARTLAKE)) +#define IS_JASPERLAKE(i915) IS_PLATFORM(i915, INTEL_JASPERLAKE) +#define IS_ELKHARTLAKE(i915) IS_PLATFORM(i915, INTEL_ELKHARTLAKE) #define IS_TIGERLAKE(i915) IS_PLATFORM(i915, INTEL_TIGERLAKE) #define IS_ROCKETLAKE(i915) IS_PLATFORM(i915, INTEL_ROCKETLAKE) #define IS_DG1(i915) IS_PLATFORM(i915, INTEL_DG1) @@ -585,105 +583,77 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G11) #define IS_DG2_G12(i915) \ IS_SUBPLATFORM(i915, INTEL_DG2, INTEL_SUBPLATFORM_G12) -#define IS_ADLS_RPLS(i915) \ +#define IS_RAPTORLAKE_S(i915) \ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_S, INTEL_SUBPLATFORM_RPL) -#define IS_ADLP_N(i915) \ +#define IS_ALDERLAKE_P_N(i915) \ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_N) -#define IS_ADLP_RPLP(i915) \ +#define IS_RAPTORLAKE_P(i915) \ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_RPL) -#define IS_ADLP_RPLU(i915) \ +#define IS_RAPTORLAKE_U(i915) \ IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, INTEL_SUBPLATFORM_RPLU) -#define IS_HSW_EARLY_SDV(i915) (IS_HASWELL(i915) && \ +#define IS_HASWELL_EARLY_SDV(i915) (IS_HASWELL(i915) && \ (INTEL_DEVID(i915) & 0xFF00) == 0x0C00) -#define IS_BDW_ULT(i915) \ +#define IS_BROADWELL_ULT(i915) \ IS_SUBPLATFORM(i915, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULT) -#define IS_BDW_ULX(i915) \ +#define IS_BROADWELL_ULX(i915) \ IS_SUBPLATFORM(i915, INTEL_BROADWELL, INTEL_SUBPLATFORM_ULX) -#define IS_BDW_GT3(i915) (IS_BROADWELL(i915) && \ +#define IS_BROADWELL_GT3(i915) (IS_BROADWELL(i915) && \ INTEL_INFO(i915)->gt == 3) -#define IS_HSW_ULT(i915) \ +#define IS_HASWELL_ULT(i915) \ IS_SUBPLATFORM(i915, INTEL_HASWELL, INTEL_SUBPLATFORM_ULT) -#define IS_HSW_GT3(i915) (IS_HASWELL(i915) && \ +#define IS_HASWELL_GT3(i915) (IS_HASWELL(i915) && \ INTEL_INFO(i915)->gt == 3) -#define IS_HSW_GT1(i915) (IS_HASWELL(i915) && \ +#define IS_HASWELL_GT1(i915) (IS_HASWELL(i915) && \ INTEL_INFO(i915)->gt == 1) /* ULX machines are also considered ULT. */ -#define IS_HSW_ULX(i915) \ +#define IS_HASWELL_ULX(i915) \ IS_SUBPLATFORM(i915, INTEL_HASWELL, INTEL_SUBPLATFORM_ULX) -#define IS_SKL_ULT(i915) \ +#define IS_SKYLAKE_ULT(i915) \ IS_SUBPLATFORM(i915, INTEL_SKYLAKE, INTEL_SUBPLATFORM_ULT) -#define IS_SKL_ULX(i915) \ +#define IS_SKYLAKE_ULX(i915) \ IS_SUBPLATFORM(i915, INTEL_SKYLAKE, INTEL_SUBPLATFORM_ULX) -#define IS_KBL_ULT(i915) \ +#define IS_KABYLAKE_ULT(i915) \ IS_SUBPLATFORM(i915, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULT) -#define IS_KBL_ULX(i915) \ +#define IS_KABYLAKE_ULX(i915) \ IS_SUBPLATFORM(i915, INTEL_KABYLAKE, INTEL_SUBPLATFORM_ULX) -#define IS_SKL_GT2(i915) (IS_SKYLAKE(i915) && \ +#define IS_SKYLAKE_GT2(i915) (IS_SKYLAKE(i915) && \ INTEL_INFO(i915)->gt == 2) -#define IS_SKL_GT3(i915) (IS_SKYLAKE(i915) && \ +#define IS_SKYLAKE_GT3(i915) (IS_SKYLAKE(i915) && \ INTEL_INFO(i915)->gt == 3) -#define IS_SKL_GT4(i915) (IS_SKYLAKE(i915) && \ +#define IS_SKYLAKE_GT4(i915) (IS_SKYLAKE(i915) && \ INTEL_INFO(i915)->gt == 4) -#define IS_KBL_GT2(i915) (IS_KABYLAKE(i915) && \ +#define IS_KABYLAKE_GT2(i915) (IS_KABYLAKE(i915) && \ INTEL_INFO(i915)->gt == 2) -#define IS_KBL_GT3(i915) (IS_KABYLAKE(i915) && \ +#define IS_KABYLAKE_GT3(i915) (IS_KABYLAKE(i915) && \ INTEL_INFO(i915)->gt == 3) -#define IS_CFL_ULT(i915) \ +#define IS_COFFEELAKE_ULT(i915) \ IS_SUBPLATFORM(i915, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULT) -#define IS_CFL_ULX(i915) \ +#define IS_COFFEELAKE_ULX(i915) \ IS_SUBPLATFORM(i915, INTEL_COFFEELAKE, INTEL_SUBPLATFORM_ULX) -#define IS_CFL_GT2(i915) (IS_COFFEELAKE(i915) && \ +#define IS_COFFEELAKE_GT2(i915) (IS_COFFEELAKE(i915) && \ INTEL_INFO(i915)->gt == 2) -#define IS_CFL_GT3(i915) (IS_COFFEELAKE(i915) && \ +#define IS_COFFEELAKE_GT3(i915) (IS_COFFEELAKE(i915) && \ INTEL_INFO(i915)->gt == 3) -#define IS_CML_ULT(i915) \ +#define IS_COMETLAKE_ULT(i915) \ IS_SUBPLATFORM(i915, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULT) -#define IS_CML_ULX(i915) \ +#define IS_COMETLAKE_ULX(i915) \ IS_SUBPLATFORM(i915, INTEL_COMETLAKE, INTEL_SUBPLATFORM_ULX) -#define IS_CML_GT2(i915) (IS_COMETLAKE(i915) && \ +#define IS_COMETLAKE_GT2(i915) (IS_COMETLAKE(i915) && \ INTEL_INFO(i915)->gt == 2) #define IS_ICL_WITH_PORT_F(i915) \ IS_SUBPLATFORM(i915, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF) -#define IS_TGL_UY(i915) \ +#define IS_TIGERLAKE_UY(i915) \ IS_SUBPLATFORM(i915, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_UY) -#define IS_SKL_GRAPHICS_STEP(p, since, until) (IS_SKYLAKE(p) && IS_GRAPHICS_STEP(p, since, until)) -#define IS_KBL_GRAPHICS_STEP(i915, since, until) \ - (IS_KABYLAKE(i915) && IS_GRAPHICS_STEP(i915, since, until)) -#define IS_KBL_DISPLAY_STEP(i915, since, until) \ - (IS_KABYLAKE(i915) && IS_DISPLAY_STEP(i915, since, until)) -#define IS_JSL_EHL_GRAPHICS_STEP(p, since, until) \ - (IS_JSL_EHL(p) && IS_GRAPHICS_STEP(p, since, until)) -#define IS_JSL_EHL_DISPLAY_STEP(p, since, until) \ - (IS_JSL_EHL(p) && IS_DISPLAY_STEP(p, since, until)) -#define IS_TGL_DISPLAY_STEP(__i915, since, until) \ - (IS_TIGERLAKE(__i915) && \ - IS_DISPLAY_STEP(__i915, since, until)) - -#define IS_RKL_DISPLAY_STEP(p, since, until) \ - (IS_ROCKETLAKE(p) && IS_DISPLAY_STEP(p, since, until)) -#define IS_ADLS_DISPLAY_STEP(__i915, since, until) \ - (IS_ALDERLAKE_S(__i915) && \ - IS_DISPLAY_STEP(__i915, since, until)) -#define IS_ADLS_GRAPHICS_STEP(__i915, since, until) \ - (IS_ALDERLAKE_S(__i915) && \ - IS_GRAPHICS_STEP(__i915, since, until)) -#define IS_ADLP_DISPLAY_STEP(__i915, since, until) \ - (IS_ALDERLAKE_P(__i915) && \ - IS_DISPLAY_STEP(__i915, since, until)) - -#define IS_ADLP_GRAPHICS_STEP(__i915, since, until) \ - (IS_ALDERLAKE_P(__i915) && \ - IS_GRAPHICS_STEP(__i915, since, until)) #define IS_XEHPSDV_GRAPHICS_STEP(__i915, since, until) \ (IS_XEHPSDV(__i915) && IS_GRAPHICS_STEP(__i915, since, until)) @@ -801,7 +771,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, /* WaRsDisableCoarsePowerGating:skl,cnl */ #define NEEDS_WaRsDisableCoarsePowerGating(i915) \ - (IS_SKL_GT3(i915) || IS_SKL_GT4(i915)) + (IS_SKYLAKE_GT3(i915) || IS_SKYLAKE_GT4(i915)) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. @@ -839,7 +809,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, */ #define HAS_64K_PAGES(i915) (INTEL_INFO(i915)->has_64k_pages) -#define HAS_REGION(i915, i) (RUNTIME_INFO(i915)->memory_regions & (i)) +#define HAS_REGION(i915, i) (INTEL_INFO(i915)->memory_regions & (i)) #define HAS_LMEM(i915) HAS_REGION(i915, REGION_LMEM) #define HAS_EXTRA_GT_LIST(i915) (INTEL_INFO(i915)->extra_gt_list) @@ -862,7 +832,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, /* DPF == dynamic parity feature */ #define HAS_L3_DPF(i915) (INTEL_INFO(i915)->has_l3_dpf) -#define NUM_L3_SLICES(i915) (IS_HSW_GT3(i915) ? \ +#define NUM_L3_SLICES(i915) (IS_HASWELL_GT3(i915) ? \ 2 : HAS_L3_DPF(i915)) /* Only valid when HAS_DISPLAY() is true */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 0c38bfb60c9a..4008bb09fdb5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -649,6 +649,8 @@ static void err_print_capabilities(struct drm_i915_error_state_buf *m, struct drm_printer p = i915_error_printer(m); intel_device_info_print(&error->device_info, &error->runtime_info, &p); + intel_display_device_info_print(&error->display_device_info, + &error->display_runtime_info, &p); intel_driver_caps_print(&error->driver_caps, &p); } @@ -1173,9 +1175,9 @@ i915_vma_coredump_create(const struct intel_gt *gt, drm_clflush_pages(&page, 1); - s = kmap(page); + s = kmap_local_page(page); ret = compress_page(compress, s, dst, false); - kunmap(page); + kunmap_local(s); drm_clflush_pages(&page, 1); @@ -1983,6 +1985,10 @@ static void capture_gen(struct i915_gpu_coredump *error) memcpy(&error->runtime_info, RUNTIME_INFO(i915), sizeof(error->runtime_info)); + memcpy(&error->display_device_info, DISPLAY_INFO(i915), + sizeof(error->display_device_info)); + memcpy(&error->display_runtime_info, DISPLAY_RUNTIME_INFO(i915), + sizeof(error->display_runtime_info)); error->driver_caps = i915->caps; } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index a78c061ce26f..9f5971f5e980 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -14,6 +14,7 @@ #include <drm/drm_mm.h> +#include "display/intel_display_device.h" #include "gt/intel_engine.h" #include "gt/intel_gt_types.h" #include "gt/uc/intel_uc_fw.h" @@ -209,6 +210,8 @@ struct i915_gpu_coredump { struct intel_device_info device_info; struct intel_runtime_info runtime_info; + struct intel_display_device_info display_device_info; + struct intel_display_runtime_info display_runtime_info; struct intel_driver_caps driver_caps; struct i915_params params; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 82fbabcdd7a5..1bfcfbe6e30b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -423,7 +423,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) static irqreturn_t ilk_irq_handler(int irq, void *arg) { struct drm_i915_private *i915 = arg; - void __iomem * const regs = i915->uncore.regs; + void __iomem * const regs = intel_uncore_regs(&i915->uncore); u32 de_iir, gt_iir, de_ier, sde_ier = 0; irqreturn_t ret = IRQ_NONE; @@ -511,7 +511,7 @@ static inline void gen8_master_intr_enable(void __iomem * const regs) static irqreturn_t gen8_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - void __iomem * const regs = dev_priv->uncore.regs; + void __iomem * const regs = intel_uncore_regs(&dev_priv->uncore); u32 master_ctl; if (!intel_irqs_enabled(dev_priv)) @@ -561,7 +561,7 @@ static inline void gen11_master_intr_enable(void __iomem * const regs) static irqreturn_t gen11_irq_handler(int irq, void *arg) { struct drm_i915_private *i915 = arg; - void __iomem * const regs = i915->uncore.regs; + void __iomem * const regs = intel_uncore_regs(&i915->uncore); struct intel_gt *gt = to_gt(i915); u32 master_ctl; u32 gu_misc_iir; @@ -619,7 +619,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) { struct drm_i915_private * const i915 = arg; struct intel_gt *gt = to_gt(i915); - void __iomem * const regs = gt->uncore->regs; + void __iomem * const regs = intel_uncore_regs(gt->uncore); u32 master_tile_ctl, master_ctl; u32 gu_misc_iir; @@ -711,7 +711,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; - gen8_master_intr_disable(uncore->regs); + gen8_master_intr_disable(intel_uncore_regs(uncore)); gen8_gt_irq_reset(to_gt(dev_priv)); gen8_display_irq_reset(dev_priv); @@ -727,7 +727,7 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv) struct intel_gt *gt = to_gt(dev_priv); struct intel_uncore *uncore = gt->uncore; - gen11_master_intr_disable(dev_priv->uncore.regs); + gen11_master_intr_disable(intel_uncore_regs(&dev_priv->uncore)); gen11_gt_irq_reset(gt); gen11_display_irq_reset(dev_priv); @@ -742,7 +742,7 @@ static void dg1_irq_reset(struct drm_i915_private *dev_priv) struct intel_gt *gt; unsigned int i; - dg1_master_intr_disable(dev_priv->uncore.regs); + dg1_master_intr_disable(intel_uncore_regs(&dev_priv->uncore)); for_each_gt(gt, dev_priv, i) gen11_gt_irq_reset(gt); @@ -772,45 +772,9 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_uncore *uncore = &dev_priv->uncore; - u32 display_mask, extra_mask; - - if (GRAPHICS_VER(dev_priv) >= 7) { - display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | - DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); - extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | - DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | - DE_PLANE_FLIP_DONE_IVB(PLANE_C) | - DE_PLANE_FLIP_DONE_IVB(PLANE_B) | - DE_PLANE_FLIP_DONE_IVB(PLANE_A) | - DE_DP_A_HOTPLUG_IVB); - } else { - display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | - DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | - DE_PIPEA_CRC_DONE | DE_POISON); - extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | - DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | - DE_PLANE_FLIP_DONE(PLANE_A) | - DE_PLANE_FLIP_DONE(PLANE_B) | - DE_DP_A_HOTPLUG); - } - - if (IS_HASWELL(dev_priv)) { - gen3_assert_iir_is_zero(uncore, EDP_PSR_IIR); - display_mask |= DE_EDP_PSR_INT_HSW; - } - - if (IS_IRONLAKE_M(dev_priv)) - extra_mask |= DE_PCU_EVENT; - - dev_priv->irq_mask = ~display_mask; - - ibx_irq_postinstall(dev_priv); - gen5_gt_irq_postinstall(to_gt(dev_priv)); - GEN3_IRQ_INIT(uncore, DE, dev_priv->irq_mask, - display_mask | extra_mask); + ilk_de_irq_postinstall(dev_priv); } static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) @@ -828,15 +792,10 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) { - if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - icp_irq_postinstall(dev_priv); - else if (HAS_PCH_SPLIT(dev_priv)) - ibx_irq_postinstall(dev_priv); - gen8_gt_irq_postinstall(to_gt(dev_priv)); gen8_de_irq_postinstall(dev_priv); - gen8_master_intr_enable(dev_priv->uncore.regs); + gen8_master_intr_enable(intel_uncore_regs(&dev_priv->uncore)); } static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) @@ -845,15 +804,12 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) struct intel_uncore *uncore = gt->uncore; u32 gu_misc_masked = GEN11_GU_MISC_GSE; - if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - icp_irq_postinstall(dev_priv); - gen11_gt_irq_postinstall(gt); gen11_de_irq_postinstall(dev_priv); GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); - gen11_master_intr_enable(uncore->regs); + gen11_master_intr_enable(intel_uncore_regs(uncore)); intel_uncore_posting_read(&dev_priv->uncore, GEN11_GFX_MSTR_IRQ); } @@ -869,18 +825,9 @@ static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) GEN3_IRQ_INIT(uncore, GEN11_GU_MISC_, ~gu_misc_masked, gu_misc_masked); - if (HAS_DISPLAY(dev_priv)) { - if (DISPLAY_VER(dev_priv) >= 14) - mtp_irq_postinstall(dev_priv); - else - icp_irq_postinstall(dev_priv); + dg1_de_irq_postinstall(dev_priv); - gen8_de_irq_postinstall(dev_priv); - intel_uncore_write(&dev_priv->uncore, GEN11_DISPLAY_INT_CTL, - GEN11_DISPLAY_IRQ_ENABLE); - } - - dg1_master_intr_enable(uncore->regs); + dg1_master_intr_enable(intel_uncore_regs(uncore)); intel_uncore_posting_read(uncore, DG1_MSTR_TILE_INTR); } @@ -1343,23 +1290,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) /* pre-gen11 the guc irqs bits are in the upper 16 bits of the pm reg */ if (HAS_GT_UC(dev_priv) && GRAPHICS_VER(dev_priv) < 11) to_gt(dev_priv)->pm_guc_events = GUC_INTR_GUC2HOST << 16; - - if (!HAS_DISPLAY(dev_priv)) - return; - - dev_priv->drm.vblank_disable_immediate = true; - - /* Most platforms treat the display irq block as an always-on - * power domain. vlv/chv can disable it at runtime and need - * special care to avoid writing any of the display block registers - * outside of the power domain. We defer setting up the display irqs - * in this case to the runtime pm. - */ - dev_priv->display_irqs_enabled = true; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - dev_priv->display_irqs_enabled = false; - - intel_hotplug_irq_init(dev_priv); } /** diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 928975d5fe2f..fcacdc21643c 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -81,7 +81,7 @@ .__runtime.page_sizes = I915_GTT_PAGE_SIZE_4K #define GEN_DEFAULT_REGIONS \ - .__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_SMEM + .memory_regions = REGION_SMEM | REGION_STOLEN_SMEM #define I830_FEATURES \ GEN(2), \ @@ -90,7 +90,7 @@ .has_3d_pipeline = 1, \ .hws_needs_physical = 1, \ .unfenced_needs_alignment = 1, \ - .__runtime.platform_engine_mask = BIT(RCS0), \ + .platform_engine_mask = BIT(RCS0), \ .has_snoop = true, \ .has_coherent_ggtt = false, \ .dma_mask_size = 32, \ @@ -105,7 +105,7 @@ .gpu_reset_clobbers_display = true, \ .hws_needs_physical = 1, \ .unfenced_needs_alignment = 1, \ - .__runtime.platform_engine_mask = BIT(RCS0), \ + .platform_engine_mask = BIT(RCS0), \ .has_snoop = true, \ .has_coherent_ggtt = false, \ .dma_mask_size = 32, \ @@ -137,7 +137,7 @@ static const struct intel_device_info i865g_info = { #define GEN3_FEATURES \ GEN(3), \ .gpu_reset_clobbers_display = true, \ - .__runtime.platform_engine_mask = BIT(RCS0), \ + .platform_engine_mask = BIT(RCS0), \ .has_3d_pipeline = 1, \ .has_snoop = true, \ .has_coherent_ggtt = true, \ @@ -200,7 +200,7 @@ static const struct intel_device_info pnv_m_info = { #define GEN4_FEATURES \ GEN(4), \ .gpu_reset_clobbers_display = true, \ - .__runtime.platform_engine_mask = BIT(RCS0), \ + .platform_engine_mask = BIT(RCS0), \ .has_3d_pipeline = 1, \ .has_snoop = true, \ .has_coherent_ggtt = true, \ @@ -228,7 +228,7 @@ static const struct intel_device_info i965gm_info = { static const struct intel_device_info g45_info = { GEN4_FEATURES, PLATFORM(INTEL_G45), - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), + .platform_engine_mask = BIT(RCS0) | BIT(VCS0), .gpu_reset_clobbers_display = false, }; @@ -236,13 +236,13 @@ static const struct intel_device_info gm45_info = { GEN4_FEATURES, PLATFORM(INTEL_GM45), .is_mobile = 1, - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), + .platform_engine_mask = BIT(RCS0) | BIT(VCS0), .gpu_reset_clobbers_display = false, }; #define GEN5_FEATURES \ GEN(5), \ - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0), \ + .platform_engine_mask = BIT(RCS0) | BIT(VCS0), \ .has_3d_pipeline = 1, \ .has_snoop = true, \ .has_coherent_ggtt = true, \ @@ -268,7 +268,7 @@ static const struct intel_device_info ilk_m_info = { #define GEN6_FEATURES \ GEN(6), \ - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ .has_3d_pipeline = 1, \ .has_coherent_ggtt = true, \ .has_llc = 1, \ @@ -316,7 +316,7 @@ static const struct intel_device_info snb_m_gt2_info = { #define GEN7_FEATURES \ GEN(7), \ - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), \ .has_3d_pipeline = 1, \ .has_coherent_ggtt = true, \ .has_llc = 1, \ @@ -384,7 +384,7 @@ static const struct intel_device_info vlv_info = { .__runtime.ppgtt_size = 31, .has_snoop = true, .has_coherent_ggtt = false, - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0), GEN_DEFAULT_PAGE_SIZES, GEN_DEFAULT_REGIONS, LEGACY_CACHELEVEL, @@ -392,7 +392,7 @@ static const struct intel_device_info vlv_info = { #define G75_FEATURES \ GEN7_FEATURES, \ - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ .has_rc6p = 0 /* RC6p removed-by HSW */, \ .has_runtime_pm = 1 @@ -450,7 +450,7 @@ static const struct intel_device_info bdw_rsvd_info = { static const struct intel_device_info bdw_gt3_info = { BDW_PLATFORM, .gt = 3, - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1), }; @@ -458,7 +458,7 @@ static const struct intel_device_info chv_info = { PLATFORM(INTEL_CHERRYVIEW), GEN(8), .is_lp = 1, - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), .has_64bit_reloc = 1, .has_runtime_pm = 1, .has_rc6 = 1, @@ -502,7 +502,7 @@ static const struct intel_device_info skl_gt2_info = { #define SKL_GT3_PLUS_PLATFORM \ SKL_PLATFORM, \ - .__runtime.platform_engine_mask = \ + .platform_engine_mask = \ BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1) @@ -519,7 +519,7 @@ static const struct intel_device_info skl_gt4_info = { #define GEN9_LP_FEATURES \ GEN(9), \ .is_lp = 1, \ - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0), \ .has_3d_pipeline = 1, \ .has_64bit_reloc = 1, \ .has_runtime_pm = 1, \ @@ -565,7 +565,7 @@ static const struct intel_device_info kbl_gt2_info = { static const struct intel_device_info kbl_gt3_info = { KBL_PLATFORM, .gt = 3, - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1), }; @@ -586,7 +586,7 @@ static const struct intel_device_info cfl_gt2_info = { static const struct intel_device_info cfl_gt3_info = { CFL_PLATFORM, .gt = 3, - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(VCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS1), }; @@ -619,21 +619,21 @@ static const struct intel_device_info cml_gt2_info = { static const struct intel_device_info icl_info = { GEN11_FEATURES, PLATFORM(INTEL_ICELAKE), - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), }; static const struct intel_device_info ehl_info = { GEN11_FEATURES, PLATFORM(INTEL_ELKHARTLAKE), - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), .__runtime.ppgtt_size = 36, }; static const struct intel_device_info jsl_info = { GEN11_FEATURES, PLATFORM(INTEL_JASPERLAKE), - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VCS0) | BIT(VECS0), .__runtime.ppgtt_size = 36, }; @@ -648,19 +648,19 @@ static const struct intel_device_info jsl_info = { static const struct intel_device_info tgl_info = { GEN12_FEATURES, PLATFORM(INTEL_TIGERLAKE), - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), }; static const struct intel_device_info rkl_info = { GEN12_FEATURES, PLATFORM(INTEL_ROCKETLAKE), - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0), }; #define DGFX_FEATURES \ - .__runtime.memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \ + .memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \ .has_llc = 0, \ .has_pxp = 0, \ .has_snoop = 1, \ @@ -673,7 +673,7 @@ static const struct intel_device_info dg1_info = { .__runtime.graphics.ip.rel = 10, PLATFORM(INTEL_DG1), .require_force_probe = 1, - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), /* Wa_16011227922 */ @@ -683,7 +683,7 @@ static const struct intel_device_info dg1_info = { static const struct intel_device_info adl_s_info = { GEN12_FEATURES, PLATFORM(INTEL_ALDERLAKE_S), - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), .dma_mask_size = 39, }; @@ -691,7 +691,7 @@ static const struct intel_device_info adl_s_info = { static const struct intel_device_info adl_p_info = { GEN12_FEATURES, PLATFORM(INTEL_ALDERLAKE_P), - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), .__runtime.ppgtt_size = 48, .dma_mask_size = 39, @@ -743,7 +743,7 @@ static const struct intel_device_info xehpsdv_info = { PLATFORM(INTEL_XEHPSDV), .has_64k_pages = 1, .has_media_ratio_mode = 1, - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VECS1) | BIT(VECS2) | BIT(VECS3) | BIT(VCS0) | BIT(VCS1) | BIT(VCS2) | BIT(VCS3) | @@ -763,7 +763,7 @@ static const struct intel_device_info xehpsdv_info = { .has_guc_deprivilege = 1, \ .has_heci_pxp = 1, \ .has_media_ratio_mode = 1, \ - .__runtime.platform_engine_mask = \ + .platform_engine_mask = \ BIT(RCS0) | BIT(BCS0) | \ BIT(VECS0) | BIT(VECS1) | \ BIT(VCS0) | BIT(VCS2) | \ @@ -798,7 +798,7 @@ static const struct intel_device_info pvc_info = { PLATFORM(INTEL_PONTEVECCHIO), .has_flat_ccs = 0, .max_pat_index = 7, - .__runtime.platform_engine_mask = + .platform_engine_mask = BIT(BCS0) | BIT(VCS0) | BIT(CCS0) | BIT(CCS1) | BIT(CCS2) | BIT(CCS3), @@ -835,8 +835,8 @@ static const struct intel_device_info mtl_info = { .has_snoop = 1, .max_pat_index = 4, .has_pxp = 1, - .__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, - .__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), + .memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), .require_force_probe = 1, MTL_CACHELEVEL, }; diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 49c6f1ff1128..04bc1f4a1115 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1319,7 +1319,7 @@ __store_reg_to_mem(struct i915_request *rq, i915_reg_t reg, u32 ggtt_offset) u32 *cs, cmd; cmd = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; - if (GRAPHICS_VER(rq->engine->i915) >= 8) + if (GRAPHICS_VER(rq->i915) >= 8) cmd++; cs = intel_ring_begin(rq, 4); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7a4f462e8b70..aefad14ab27a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -941,8 +941,30 @@ #define HECI_H_GS1(base) _MMIO((base) + 0xc4c) #define HECI_H_GS1_ER_PREP REG_BIT(0) -#define HECI_FWSTS5(base) _MMIO((base) + 0xc68) -#define HECI_FWSTS5_HUC_AUTH_DONE (1 << 19) +/* + * The FWSTS register values are FW defined and can be different between + * HECI1 and HECI2 + */ +#define HECI_FWSTS1 0xc40 +#define HECI1_FWSTS1_CURRENT_STATE REG_GENMASK(3, 0) +#define HECI1_FWSTS1_CURRENT_STATE_RESET 0 +#define HECI1_FWSTS1_PROXY_STATE_NORMAL 5 +#define HECI1_FWSTS1_INIT_COMPLETE REG_BIT(9) +#define HECI_FWSTS2 0xc48 +#define HECI_FWSTS3 0xc60 +#define HECI_FWSTS4 0xc64 +#define HECI_FWSTS5 0xc68 +#define HECI1_FWSTS5_HUC_AUTH_DONE (1 << 19) +#define HECI_FWSTS6 0xc6c + +/* the FWSTS regs are 1-based, so we use -base for index 0 to get an invalid reg */ +#define HECI_FWSTS(base, x) _MMIO((base) + _PICK(x, -(base), \ + HECI_FWSTS1, \ + HECI_FWSTS2, \ + HECI_FWSTS3, \ + HECI_FWSTS4, \ + HECI_FWSTS5, \ + HECI_FWSTS6)) #define HSW_GTT_CACHE_EN _MMIO(0x4024) #define GTT_CACHE_EN_ALL 0xF0007FFF @@ -4917,6 +4939,7 @@ #define SHPD_FILTER_CNT _MMIO(0xc4038) #define SHPD_FILTER_CNT_500_ADJ 0x001D9 +#define SHPD_FILTER_CNT_250 0x000F8 #define _PCH_DPLL_A 0xc6014 #define _PCH_DPLL_B 0xc6018 diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 894068bb37b6..7c7da284990d 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1220,7 +1220,7 @@ emit_semaphore_wait(struct i915_request *to, /* * If this or its dependents are waiting on an external fence * that may fail catastrophically, then we want to avoid using - * sempahores as they bypass the fence signaling metadata, and we + * semaphores as they bypass the fence signaling metadata, and we * lose the fence->error propagation. */ if (from->sched.flags & I915_SCHED_HAS_EXTERNAL_CHAIN) @@ -1353,7 +1353,7 @@ __i915_request_await_external(struct i915_request *rq, struct dma_fence *fence) { mark_external(rq); return i915_sw_fence_await_dma_fence(&rq->submit, fence, - i915_fence_context_timeout(rq->engine->i915, + i915_fence_context_timeout(rq->i915, fence->context), I915_FENCE_GFP); } @@ -1661,6 +1661,11 @@ __i915_request_ensure_parallel_ordering(struct i915_request *rq, request_to_parent(rq)->parallel.last_rq = i915_request_get(rq); + /* + * Users have to put a reference potentially got by + * __i915_active_fence_set() to the returned request + * when no longer needed + */ return to_request(__i915_active_fence_set(&timeline->last_request, &rq->fence)); } @@ -1707,6 +1712,10 @@ __i915_request_ensure_ordering(struct i915_request *rq, 0); } + /* + * Users have to put the reference to prev potentially got + * by __i915_active_fence_set() when no longer needed + */ return prev; } @@ -1760,6 +1769,8 @@ __i915_request_add_to_timeline(struct i915_request *rq) prev = __i915_request_ensure_ordering(rq, timeline); else prev = __i915_request_ensure_parallel_ordering(rq, timeline); + if (prev) + i915_request_put(prev); /* * Make sure that no request gazumped us - if it was allocated after diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index f6f9228a1351..ce1cbee1b39d 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -277,7 +277,7 @@ TRACE_EVENT(i915_request_queue, ), TP_fast_assign( - __entry->dev = rq->engine->i915->drm.primary->index; + __entry->dev = rq->i915->drm.primary->index; __entry->class = rq->engine->uabi_class; __entry->instance = rq->engine->uabi_instance; __entry->ctx = rq->fence.context; @@ -304,7 +304,7 @@ DECLARE_EVENT_CLASS(i915_request, ), TP_fast_assign( - __entry->dev = rq->engine->i915->drm.primary->index; + __entry->dev = rq->i915->drm.primary->index; __entry->class = rq->engine->uabi_class; __entry->instance = rq->engine->uabi_instance; __entry->ctx = rq->fence.context; @@ -353,7 +353,7 @@ TRACE_EVENT(i915_request_in, ), TP_fast_assign( - __entry->dev = rq->engine->i915->drm.primary->index; + __entry->dev = rq->i915->drm.primary->index; __entry->class = rq->engine->uabi_class; __entry->instance = rq->engine->uabi_instance; __entry->ctx = rq->fence.context; @@ -382,7 +382,7 @@ TRACE_EVENT(i915_request_out, ), TP_fast_assign( - __entry->dev = rq->engine->i915->drm.primary->index; + __entry->dev = rq->i915->drm.primary->index; __entry->class = rq->engine->uabi_class; __entry->instance = rq->engine->uabi_instance; __entry->ctx = rq->fence.context; @@ -623,7 +623,7 @@ TRACE_EVENT(i915_request_wait_begin, * less desirable. */ TP_fast_assign( - __entry->dev = rq->engine->i915->drm.primary->index; + __entry->dev = rq->i915->drm.primary->index; __entry->class = rq->engine->uabi_class; __entry->instance = rq->engine->uabi_instance; __entry->ctx = rq->fence.context; diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index ffb425ba591c..6f180ee13853 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -34,6 +34,7 @@ #include "gt/intel_engine_heartbeat.h" #include "gt/intel_gt.h" #include "gt/intel_gt_requests.h" +#include "gt/intel_tlb.h" #include "i915_drv.h" #include "i915_gem_evict.h" @@ -74,14 +75,14 @@ static void vma_print_allocator(struct i915_vma *vma, const char *reason) char buf[512]; if (!vma->node.stack) { - drm_dbg(&to_i915(vma->obj->base.dev)->drm, + drm_dbg(vma->obj->base.dev, "vma.node [%08llx + %08llx] %s: unknown owner\n", vma->node.start, vma->node.size, reason); return; } stack_depot_snprint(vma->node.stack, buf, sizeof(buf), 0); - drm_dbg(&to_i915(vma->obj->base.dev)->drm, + drm_dbg(vma->obj->base.dev, "vma.node [%08llx + %08llx] %s: inserted at %s\n", vma->node.start, vma->node.size, reason, buf); } @@ -805,7 +806,7 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, * attempt to find space. */ if (size > end - 2 * guard) { - drm_dbg(&to_i915(vma->obj->base.dev)->drm, + drm_dbg(vma->obj->base.dev, "Attempting to bind an object larger than the aperture: request=%llu > %s aperture=%llu\n", size, flags & PIN_MAPPABLE ? "mappable" : "total", end); return -ENOSPC; @@ -1339,6 +1340,12 @@ err_unpin: void vma_invalidate_tlb(struct i915_address_space *vm, u32 *tlb) { + struct intel_gt *gt; + int id; + + if (!tlb) + return; + /* * Before we release the pages that were bound by this vma, we * must invalidate all the TLBs that may still have a reference @@ -1347,7 +1354,9 @@ void vma_invalidate_tlb(struct i915_address_space *vm, u32 *tlb) * the most recent TLB invalidation seqno, and if we have not yet * flushed the TLBs upon release, perform a full invalidation. */ - WRITE_ONCE(*tlb, intel_gt_next_invalidate_tlb_full(vm->gt)); + for_each_gt(gt, vm->i915, id) + WRITE_ONCE(tlb[id], + intel_gt_next_invalidate_tlb_full(gt)); } static void __vma_put_pages(struct i915_vma *vma, unsigned int count) @@ -1629,6 +1638,26 @@ int i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, return err; } +/** + * i915_ggtt_clear_scanout - Clear scanout flag for all objects ggtt vmas + * @obj: i915 GEM object + * This function clears scanout flags for objects ggtt vmas. These flags are set + * when object is pinned for display use and this function to clear them all is + * targeted to be called by frontbuffer tracking code when the frontbuffer is + * about to be released. + */ +void i915_ggtt_clear_scanout(struct drm_i915_gem_object *obj) +{ + struct i915_vma *vma; + + spin_lock(&obj->vma.lock); + for_each_ggtt_vma(vma, obj) { + i915_vma_clear_scanout(vma); + vma->display_alignment = I915_GTT_MIN_ALIGNMENT; + } + spin_unlock(&obj->vma.lock); +} + static void __vma_close(struct i915_vma *vma, struct intel_gt *gt) { /* @@ -1908,7 +1937,7 @@ int _i915_vma_move_to_active(struct i915_vma *vma, if (flags & EXEC_OBJECT_WRITE) { struct intel_frontbuffer *front; - front = __intel_frontbuffer_get(obj); + front = i915_gem_object_get_frontbuffer(obj); if (unlikely(front)) { if (intel_frontbuffer_invalidate(front, ORIGIN_CS)) i915_active_add_request(&front->write, rq); @@ -1994,7 +2023,7 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async) if (async) unbind_fence = i915_vma_resource_unbind(vma_res, - &vma->obj->mm.tlb); + vma->obj->mm.tlb); else unbind_fence = i915_vma_resource_unbind(vma_res, NULL); @@ -2011,7 +2040,7 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async) dma_fence_put(unbind_fence); unbind_fence = NULL; } - vma_invalidate_tlb(vma->vm, &vma->obj->mm.tlb); + vma_invalidate_tlb(vma->vm, vma->obj->mm.tlb); } /* diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 9a9729205d5b..e356dfb883d3 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -418,6 +418,11 @@ i915_vma_unpin_fence(struct i915_vma *vma) __i915_vma_unpin_fence(vma); } +static inline int i915_vma_fence_id(const struct i915_vma *vma) +{ + return vma->fence ? vma->fence->id : -1; +} + void i915_vma_parked(struct intel_gt *gt); static inline bool i915_vma_is_scanout(const struct i915_vma *vma) @@ -435,6 +440,8 @@ static inline void i915_vma_clear_scanout(struct i915_vma *vma) clear_bit(I915_VMA_SCANOUT_BIT, __i915_vma_flags(vma)); } +void i915_ggtt_clear_scanout(struct drm_i915_gem_object *obj); + #define for_each_until(cond) if (cond) break; else /** diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index a27600bc5976..81a4d32734e9 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -456,12 +456,12 @@ static void kbl_init_clock_gating(struct drm_i915_private *i915) intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); /* WaDisableSDEUnitClockGating:kbl */ - if (IS_KBL_GRAPHICS_STEP(i915, 0, STEP_C0)) + if (IS_KABYLAKE(i915) && IS_GRAPHICS_STEP(i915, 0, STEP_C0)) intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); /* WaDisableGamClockGating:kbl */ - if (IS_KBL_GRAPHICS_STEP(i915, 0, STEP_C0)) + if (IS_KABYLAKE(i915) && IS_GRAPHICS_STEP(i915, 0, STEP_C0)) intel_uncore_rmw(&i915->uncore, GEN6_UCGCTL1, 0, GEN6_GAMUNIT_CLOCK_GATE_DISABLE); @@ -559,9 +559,20 @@ static void bdw_init_clock_gating(struct drm_i915_private *i915) static void hsw_init_clock_gating(struct drm_i915_private *i915) { + enum pipe pipe; + /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); + /* WaPsrDPAMaskVBlankInSRD:hsw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD); + + for_each_pipe(i915, pipe) { + /* WaPsrDPRSUnmaskVBlankInSRD:hsw */ + intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(pipe), + 0, HSW_UNMASK_VBL_TO_REGS_IN_SRD); + } + /* This is required by WaCatErrorRejectionIssue:hsw */ intel_uncore_rmw(&i915->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 6e49caf241a5..ea0ec6174ce5 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -93,9 +93,6 @@ void intel_device_info_print(const struct intel_device_info *info, const struct intel_runtime_info *runtime, struct drm_printer *p) { - const struct intel_display_runtime_info *display_runtime = - &info->display->__runtime_defaults; - if (runtime->graphics.ip.rel) drm_printf(p, "graphics version: %u.%02u\n", runtime->graphics.ip.ver, @@ -112,21 +109,13 @@ void intel_device_info_print(const struct intel_device_info *info, drm_printf(p, "media version: %u\n", runtime->media.ip.ver); - if (display_runtime->ip.rel) - drm_printf(p, "display version: %u.%02u\n", - display_runtime->ip.ver, - display_runtime->ip.rel); - else - drm_printf(p, "display version: %u\n", - display_runtime->ip.ver); - drm_printf(p, "graphics stepping: %s\n", intel_step_name(runtime->step.graphics_step)); drm_printf(p, "media stepping: %s\n", intel_step_name(runtime->step.media_step)); drm_printf(p, "display stepping: %s\n", intel_step_name(runtime->step.display_step)); drm_printf(p, "base die stepping: %s\n", intel_step_name(runtime->step.basedie_step)); drm_printf(p, "gt: %d\n", info->gt); - drm_printf(p, "memory-regions: 0x%x\n", runtime->memory_regions); + drm_printf(p, "memory-regions: 0x%x\n", info->memory_regions); drm_printf(p, "page-sizes: 0x%x\n", runtime->page_sizes); drm_printf(p, "platform: %s\n", intel_platform_name(info->platform)); drm_printf(p, "ppgtt-size: %d\n", runtime->ppgtt_size); @@ -138,15 +127,6 @@ void intel_device_info_print(const struct intel_device_info *info, #undef PRINT_FLAG drm_printf(p, "has_pooled_eu: %s\n", str_yes_no(runtime->has_pooled_eu)); - -#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->display->name)) - DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); -#undef PRINT_FLAG - - drm_printf(p, "has_hdcp: %s\n", str_yes_no(display_runtime->has_hdcp)); - drm_printf(p, "has_dmc: %s\n", str_yes_no(display_runtime->has_dmc)); - drm_printf(p, "has_dsc: %s\n", str_yes_no(display_runtime->has_dsc)); - drm_printf(p, "rawclk rate: %u kHz\n", runtime->rawclk_freq); } @@ -260,15 +240,19 @@ static void intel_device_info_subplatform_init(struct drm_i915_private *i915) if (find_devid(devid, subplatform_ult_ids, ARRAY_SIZE(subplatform_ult_ids))) { mask = BIT(INTEL_SUBPLATFORM_ULT); + if (IS_HASWELL(i915) || IS_BROADWELL(i915)) + DISPLAY_RUNTIME_INFO(i915)->port_mask &= ~BIT(PORT_D); } else if (find_devid(devid, subplatform_ulx_ids, ARRAY_SIZE(subplatform_ulx_ids))) { mask = BIT(INTEL_SUBPLATFORM_ULX); if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { /* ULX machines are also considered ULT. */ mask |= BIT(INTEL_SUBPLATFORM_ULT); + DISPLAY_RUNTIME_INFO(i915)->port_mask &= ~BIT(PORT_D); } } else if (find_devid(devid, subplatform_portf_ids, ARRAY_SIZE(subplatform_portf_ids))) { + DISPLAY_RUNTIME_INFO(i915)->port_mask |= BIT(PORT_F); mask = BIT(INTEL_SUBPLATFORM_PORTF); } else if (find_devid(devid, subplatform_uy_ids, ARRAY_SIZE(subplatform_uy_ids))) { @@ -380,13 +364,6 @@ void intel_device_info_runtime_init_early(struct drm_i915_private *i915) intel_device_info_subplatform_init(i915); } -/* FIXME: Remove this, and make device info a const pointer to rodata. */ -static struct intel_device_info * -mkwrite_device_info(struct drm_i915_private *i915) -{ - return (struct intel_device_info *)INTEL_INFO(i915); -} - static const struct intel_display_device_info no_display = {}; /** @@ -407,7 +384,6 @@ static const struct intel_display_device_info no_display = {}; */ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) { - struct intel_device_info *info = mkwrite_device_info(dev_priv); struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv); if (HAS_DISPLAY(dev_priv)) @@ -417,7 +393,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) { dev_priv->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); - info->display = &no_display; + dev_priv->display.info.__device_info = &no_display; } /* Disable nuclear pageflip by default on pre-g4x */ @@ -447,26 +423,24 @@ void intel_device_info_driver_create(struct drm_i915_private *i915, u16 device_id, const struct intel_device_info *match_info) { - struct intel_device_info *info; struct intel_runtime_info *runtime; u16 ver, rel, step; - /* Setup the write-once "constant" device info */ - info = mkwrite_device_info(i915); - memcpy(info, match_info, sizeof(*info)); + /* Setup INTEL_INFO() */ + i915->__info = match_info; /* Initialize initial runtime info from static const data and pdev. */ runtime = RUNTIME_INFO(i915); memcpy(runtime, &INTEL_INFO(i915)->__runtime, sizeof(*runtime)); /* Probe display support */ - info->display = intel_display_device_probe(i915, info->has_gmd_id, - &ver, &rel, &step); + i915->display.info.__device_info = intel_display_device_probe(i915, HAS_GMD_ID(i915), + &ver, &rel, &step); memcpy(DISPLAY_RUNTIME_INFO(i915), &DISPLAY_INFO(i915)->__runtime_defaults, sizeof(*DISPLAY_RUNTIME_INFO(i915))); - if (info->has_gmd_id) { + if (HAS_GMD_ID(i915)) { DISPLAY_RUNTIME_INFO(i915)->ip.ver = ver; DISPLAY_RUNTIME_INFO(i915)->ip.rel = rel; DISPLAY_RUNTIME_INFO(i915)->ip.step = step; diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 069291b3bd37..dbfe6443457b 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -29,8 +29,6 @@ #include "intel_step.h" -#include "display/intel_display_device.h" - #include "gt/intel_engine_types.h" #include "gt/intel_context_types.h" #include "gt/intel_sseu.h" @@ -212,8 +210,6 @@ struct intel_runtime_info { u16 device_id; - intel_engine_mask_t platform_engine_mask; /* Engines supported by the HW */ - u32 rawclk_freq; struct intel_step_info step; @@ -223,8 +219,6 @@ struct intel_runtime_info { enum intel_ppgtt_type ppgtt_type; unsigned int ppgtt_size; /* log2, e.g. 31/32/48 bits */ - u32 memory_regions; /* regions supported by the HW */ - bool has_pooled_eu; }; @@ -237,12 +231,13 @@ struct intel_device_info { u8 gt; /* GT number, 0 if undefined */ + intel_engine_mask_t platform_engine_mask; /* Engines supported by the HW */ + u32 memory_regions; /* regions supported by the HW */ + #define DEFINE_FLAG(name) u8 name:1 DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG); #undef DEFINE_FLAG - const struct intel_display_device_info *display; - /* * Initial runtime info. Do not access outside of i915_driver_create(). */ diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c index 8a9ff6227e53..c02a6f156a00 100644 --- a/drivers/gpu/drm/i915/intel_step.c +++ b/drivers/gpu/drm/i915/intel_step.c @@ -192,16 +192,16 @@ void intel_step_init(struct drm_i915_private *i915) } else if (IS_XEHPSDV(i915)) { revids = xehpsdv_revids; size = ARRAY_SIZE(xehpsdv_revids); - } else if (IS_ADLP_N(i915)) { + } else if (IS_ALDERLAKE_P_N(i915)) { revids = adlp_n_revids; size = ARRAY_SIZE(adlp_n_revids); - } else if (IS_ADLP_RPLP(i915)) { + } else if (IS_RAPTORLAKE_P(i915)) { revids = adlp_rplp_revids; size = ARRAY_SIZE(adlp_rplp_revids); } else if (IS_ALDERLAKE_P(i915)) { revids = adlp_revids; size = ARRAY_SIZE(adlp_revids); - } else if (IS_ADLS_RPLS(i915)) { + } else if (IS_RAPTORLAKE_S(i915)) { revids = adls_rpls_revids; size = ARRAY_SIZE(adls_rpls_revids); } else if (IS_ALDERLAKE_S(i915)) { @@ -213,13 +213,13 @@ void intel_step_init(struct drm_i915_private *i915) } else if (IS_ROCKETLAKE(i915)) { revids = rkl_revids; size = ARRAY_SIZE(rkl_revids); - } else if (IS_TGL_UY(i915)) { + } else if (IS_TIGERLAKE_UY(i915)) { revids = tgl_uy_revids; size = ARRAY_SIZE(tgl_uy_revids); } else if (IS_TIGERLAKE(i915)) { revids = tgl_revids; size = ARRAY_SIZE(tgl_revids); - } else if (IS_JSL_EHL(i915)) { + } else if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { revids = jsl_ehl_revids; size = ARRAY_SIZE(jsl_ehl_revids); } else if (IS_ICELAKE(i915)) { diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 796ebfe6c550..dfefad5a5fec 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1925,25 +1925,31 @@ __unclaimed_previous_reg_debug(struct intel_uncore *uncore, i915_mmio_reg_offset(reg)); } -static inline void -unclaimed_reg_debug(struct intel_uncore *uncore, - const i915_reg_t reg, - const bool read, - const bool before) +static inline bool __must_check +unclaimed_reg_debug_header(struct intel_uncore *uncore, + const i915_reg_t reg, const bool read) { if (likely(!uncore->i915->params.mmio_debug) || !uncore->debug) - return; + return false; /* interrupts are disabled and re-enabled around uncore->lock usage */ lockdep_assert_held(&uncore->lock); - if (before) { - spin_lock(&uncore->debug->lock); - __unclaimed_previous_reg_debug(uncore, reg, read); - } else { - __unclaimed_reg_debug(uncore, reg, read); - spin_unlock(&uncore->debug->lock); - } + spin_lock(&uncore->debug->lock); + __unclaimed_previous_reg_debug(uncore, reg, read); + + return true; +} + +static inline void +unclaimed_reg_debug_footer(struct intel_uncore *uncore, + const i915_reg_t reg, const bool read) +{ + /* interrupts are disabled and re-enabled around uncore->lock usage */ + lockdep_assert_held(&uncore->lock); + + __unclaimed_reg_debug(uncore, reg, read); + spin_unlock(&uncore->debug->lock); } #define __vgpu_read(x) \ @@ -2001,13 +2007,15 @@ __gen2_read(64) #define GEN6_READ_HEADER(x) \ u32 offset = i915_mmio_reg_offset(reg); \ unsigned long irqflags; \ + bool unclaimed_reg_debug; \ u##x val = 0; \ assert_rpm_wakelock_held(uncore->rpm); \ spin_lock_irqsave(&uncore->lock, irqflags); \ - unclaimed_reg_debug(uncore, reg, true, true) + unclaimed_reg_debug = unclaimed_reg_debug_header(uncore, reg, true) #define GEN6_READ_FOOTER \ - unclaimed_reg_debug(uncore, reg, true, false); \ + if (unclaimed_reg_debug) \ + unclaimed_reg_debug_footer(uncore, reg, true); \ spin_unlock_irqrestore(&uncore->lock, irqflags); \ trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ return val @@ -2105,13 +2113,15 @@ __gen2_write(32) #define GEN6_WRITE_HEADER \ u32 offset = i915_mmio_reg_offset(reg); \ unsigned long irqflags; \ + bool unclaimed_reg_debug; \ trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ assert_rpm_wakelock_held(uncore->rpm); \ spin_lock_irqsave(&uncore->lock, irqflags); \ - unclaimed_reg_debug(uncore, reg, false, true) + unclaimed_reg_debug = unclaimed_reg_debug_header(uncore, reg, false) #define GEN6_WRITE_FOOTER \ - unclaimed_reg_debug(uncore, reg, false, false); \ + if (unclaimed_reg_debug) \ + unclaimed_reg_debug_footer(uncore, reg, false); \ spin_unlock_irqrestore(&uncore->lock, irqflags) #define __gen6_write(x) \ diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 9ea1f4864a3a..f419c311a0de 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -496,6 +496,11 @@ static inline int intel_uncore_write_and_verify(struct intel_uncore *uncore, return (reg_val & mask) != expected_val ? -EINVAL : 0; } +static inline void __iomem *intel_uncore_regs(struct intel_uncore *uncore) +{ + return uncore->regs; +} + /* * The raw_reg_{read,write} macros are intended as a micro-optimization for * interrupt handlers so that the pointer indirection on uncore->regs can diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c index bb2e15329f34..38ec754d0ec8 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c @@ -162,8 +162,8 @@ static struct intel_gt *find_gt_for_required_teelink(struct drm_i915_private *i9 * for HuC authentication. For now, its limited to DG2. */ if (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && IS_ENABLED(CONFIG_INTEL_MEI_GSC) && - intel_huc_is_loaded_by_gsc(&i915->gt0.uc.huc) && intel_uc_uses_huc(&i915->gt0.uc)) - return &i915->gt0; + intel_huc_is_loaded_by_gsc(&to_gt(i915)->uc.huc) && intel_uc_uses_huc(&to_gt(i915)->uc)) + return to_gt(i915); return NULL; } @@ -188,8 +188,8 @@ static struct intel_gt *find_gt_for_required_protected_content(struct drm_i915_p * Else we rely on mei-pxp module but only on legacy platforms * prior to having separate media GTs and has a valid VDBOX. */ - if (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && !i915->media_gt && VDBOX_MASK(&i915->gt0)) - return &i915->gt0; + if (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && !i915->media_gt && VDBOX_MASK(to_gt(i915))) + return to_gt(i915); return NULL; } diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c index f13890ec7db1..2a600184a077 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c @@ -6,6 +6,7 @@ #include "gem/i915_gem_internal.h" #include "gt/intel_context.h" +#include "gt/intel_gt.h" #include "gt/uc/intel_gsc_fw.h" #include "gt/uc/intel_gsc_uc_heci_cmd_submit.h" @@ -197,7 +198,7 @@ bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp) * are out of order) will suffice. */ if (intel_huc_is_authenticated(&pxp->ctrl_gt->uc.huc, INTEL_HUC_AUTH_BY_GSC) && - intel_gsc_uc_fw_proxy_init_done(&pxp->ctrl_gt->uc.gsc)) + intel_gsc_uc_fw_proxy_init_done(&pxp->ctrl_gt->uc.gsc, true)) return true; return false; @@ -336,7 +337,7 @@ gsccs_create_buffer(struct intel_gt *gt, } /* return a virtual pointer */ - *map = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(i915, obj, true)); + *map = i915_gem_object_pin_map_unlocked(obj, intel_gt_coherent_map_type(gt, obj, true)); if (IS_ERR(*map)) { drm_err(&i915->drm, "Failed to map gsccs backend %s.\n", bufname); err = PTR_ERR(*map); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index 1ce07d7e8769..80bb00189865 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -11,6 +11,7 @@ #include "gem/i915_gem_lmem.h" #include "i915_drv.h" +#include "gt/intel_gt.h" #include "intel_pxp.h" #include "intel_pxp_cmd_interface_42.h" @@ -245,7 +246,9 @@ static int alloc_streaming_command(struct intel_pxp *pxp) } /* map the lmem into the virtual memory pointer */ - cmd = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(i915, obj, true)); + cmd = i915_gem_object_pin_map_unlocked(obj, + intel_gt_coherent_map_type(pxp->ctrl_gt, + obj, true)); if (IS_ERR(cmd)) { drm_err(&i915->drm, "Failed to map gsc message page!\n"); err = PTR_ERR(cmd); diff --git a/drivers/gpu/drm/i915/selftests/i915_perf.c b/drivers/gpu/drm/i915/selftests/i915_perf.c index d4608b220123..403134a7acec 100644 --- a/drivers/gpu/drm/i915/selftests/i915_perf.c +++ b/drivers/gpu/drm/i915/selftests/i915_perf.c @@ -168,7 +168,7 @@ static int write_timestamp(struct i915_request *rq, int slot) return PTR_ERR(cs); len = 5; - if (GRAPHICS_VER(rq->engine->i915) >= 8) + if (GRAPHICS_VER(rq->i915) >= 8) len++; *cs++ = GFX_OP_PIPE_CONTROL(len); diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c index 39da0fb0d6d2..ee79e0809a6d 100644 --- a/drivers/gpu/drm/i915/selftests/i915_selftest.c +++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c @@ -24,6 +24,8 @@ #include <linux/random.h> #include "gt/intel_gt_pm.h" +#include "gt/uc/intel_gsc_fw.h" + #include "i915_driver.h" #include "i915_drv.h" #include "i915_selftest.h" @@ -127,6 +129,31 @@ static void set_default_test_all(struct selftest *st, unsigned int count) st[i].enabled = true; } +static bool +__gsc_proxy_init_progressing(struct intel_gsc_uc *gsc) +{ + return intel_gsc_uc_fw_proxy_get_status(gsc) == -EAGAIN; +} + +static void +__wait_gsc_proxy_completed(struct drm_i915_private *i915) +{ + bool need_to_wait = (IS_ENABLED(CONFIG_INTEL_MEI_GSC_PROXY) && + i915->media_gt && + HAS_ENGINE(i915->media_gt, GSC0) && + intel_uc_fw_is_loadable(&i915->media_gt->uc.gsc.fw)); + /* + * The gsc proxy component depends on the kernel component driver load ordering + * and in corner cases (the first time after an IFWI flash), init-completion + * firmware flows take longer. + */ + unsigned long timeout_ms = 8000; + + if (need_to_wait && wait_for(!__gsc_proxy_init_progressing(&i915->media_gt->uc.gsc), + timeout_ms)) + pr_warn(DRIVER_NAME "Timed out waiting for gsc_proxy_completion!\n"); +} + static int __run_selftests(const char *name, struct selftest *st, unsigned int count, @@ -206,6 +233,8 @@ int i915_live_selftests(struct pci_dev *pdev) if (!i915_selftest.live) return 0; + __wait_gsc_proxy_completed(pdev_to_i915(pdev)); + err = run_selftests(live, pdev_to_i915(pdev)); if (err) { i915_selftest.live = err; @@ -227,6 +256,8 @@ int i915_perf_selftests(struct pci_dev *pdev) if (!i915_selftest.perf) return 0; + __wait_gsc_proxy_completed(pdev_to_i915(pdev)); + err = run_selftests(perf, pdev_to_i915(pdev)); if (err) { i915_selftest.perf = err; diff --git a/drivers/gpu/drm/i915/selftests/igt_spinner.c b/drivers/gpu/drm/i915/selftests/igt_spinner.c index 618d9386d554..0f064930ef11 100644 --- a/drivers/gpu/drm/i915/selftests/igt_spinner.c +++ b/drivers/gpu/drm/i915/selftests/igt_spinner.c @@ -97,7 +97,7 @@ int igt_spinner_pin(struct igt_spinner *spin, if (!spin->batch) { unsigned int mode; - mode = i915_coherent_map_type(spin->gt->i915, spin->obj, false); + mode = intel_gt_coherent_map_type(spin->gt, spin->obj, false); vaddr = igt_spinner_pin_obj(ce, ww, spin->obj, mode, &spin->batch_vma); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -159,15 +159,15 @@ igt_spinner_create_request(struct igt_spinner *spin, batch = spin->batch; - if (GRAPHICS_VER(rq->engine->i915) >= 8) { + if (GRAPHICS_VER(rq->i915) >= 8) { *batch++ = MI_STORE_DWORD_IMM_GEN4; *batch++ = lower_32_bits(hws_address(hws, rq)); *batch++ = upper_32_bits(hws_address(hws, rq)); - } else if (GRAPHICS_VER(rq->engine->i915) >= 6) { + } else if (GRAPHICS_VER(rq->i915) >= 6) { *batch++ = MI_STORE_DWORD_IMM_GEN4; *batch++ = 0; *batch++ = hws_address(hws, rq); - } else if (GRAPHICS_VER(rq->engine->i915) >= 4) { + } else if (GRAPHICS_VER(rq->i915) >= 4) { *batch++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; *batch++ = 0; *batch++ = hws_address(hws, rq); @@ -179,11 +179,11 @@ igt_spinner_create_request(struct igt_spinner *spin, *batch++ = arbitration_command; - if (GRAPHICS_VER(rq->engine->i915) >= 8) + if (GRAPHICS_VER(rq->i915) >= 8) *batch++ = MI_BATCH_BUFFER_START | BIT(8) | 1; - else if (IS_HASWELL(rq->engine->i915)) + else if (IS_HASWELL(rq->i915)) *batch++ = MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW; - else if (GRAPHICS_VER(rq->engine->i915) >= 6) + else if (GRAPHICS_VER(rq->i915) >= 6) *batch++ = MI_BATCH_BUFFER_START; else *batch++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; @@ -201,7 +201,7 @@ igt_spinner_create_request(struct igt_spinner *spin, } flags = 0; - if (GRAPHICS_VER(rq->engine->i915) <= 5) + if (GRAPHICS_VER(rq->i915) <= 5) flags |= I915_DISPATCH_SECURE; err = engine->emit_bb_start(rq, i915_vma_offset(vma), PAGE_SIZE, flags); diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c index e4281508d580..03ea75cd84dd 100644 --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -210,7 +210,7 @@ static int live_forcewake_ops(void *arg) for_each_engine(engine, gt, id) { i915_reg_t mmio = _MMIO(engine->mmio_base + r->offset); - u32 __iomem *reg = uncore->regs + engine->mmio_base + r->offset; + u32 __iomem *reg = intel_uncore_regs(uncore) + engine->mmio_base + r->offset; enum forcewake_domains fw_domains; u32 val; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 4de6a4e8280d..da0b269606c5 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -114,7 +114,7 @@ static struct dev_pm_domain pm_domain = { static void mock_gt_probe(struct drm_i915_private *i915) { - i915->gt[0] = &i915->gt0; + i915->gt[0] = to_gt(i915); i915->gt[0]->name = "Mock GT"; } @@ -123,8 +123,8 @@ static const struct intel_device_info mock_info = { .__runtime.page_sizes = (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M), - .__runtime.memory_regions = REGION_SMEM, - .__runtime.platform_engine_mask = BIT(0), + .memory_regions = REGION_SMEM, + .platform_engine_mask = BIT(0), /* simply use legacy cache level for mock device */ .max_pat_index = 3, diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 9f0651d48d41..15492b69f698 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -704,7 +704,7 @@ void intel_dram_edram_detect(struct drm_i915_private *i915) if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) return; - edram_cap = __raw_uncore_read32(&i915->uncore, HSW_EDRAM_CAP); + edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP); /* NB: We can't write IDICR yet because we don't have gt funcs set up */ diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 6d0204942f7a..49c7fb16e934 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -47,11 +47,9 @@ intel_alloc_mchbar_resource(struct drm_i915_private *i915) mchbar_addr = ((u64)temp_hi << 32) | temp_lo; /* If ACPI doesn't have it, assume we need to allocate it ourselves */ -#ifdef CONFIG_PNP - if (mchbar_addr && + if (IS_ENABLED(CONFIG_PNP) && mchbar_addr && pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) return 0; -#endif /* Get some space for it */ i915->gmch.mch_res.name = "i915 MCHBAR"; diff --git a/drivers/gpu/drm/i915/soc/intel_pch.c b/drivers/gpu/drm/i915/soc/intel_pch.c index ba9843cb1b13..19a8f27c404e 100644 --- a/drivers/gpu/drm/i915/soc/intel_pch.c +++ b/drivers/gpu/drm/i915/soc/intel_pch.c @@ -32,21 +32,21 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) drm_WARN_ON(&dev_priv->drm, !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); drm_WARN_ON(&dev_priv->drm, - IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv)); return PCH_LPT; case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); drm_WARN_ON(&dev_priv->drm, - !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + !IS_HASWELL_ULT(dev_priv) && !IS_BROADWELL_ULT(dev_priv)); return PCH_LPT; case INTEL_PCH_WPT_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); drm_WARN_ON(&dev_priv->drm, - IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv)); /* WPT is LPT compatible */ return PCH_LPT; case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: @@ -54,7 +54,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) drm_WARN_ON(&dev_priv->drm, !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); drm_WARN_ON(&dev_priv->drm, - !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + !IS_HASWELL_ULT(dev_priv) && !IS_BROADWELL_ULT(dev_priv)); /* WPT is LPT compatible */ return PCH_LPT; case INTEL_PCH_SPT_DEVICE_ID_TYPE: @@ -115,7 +115,8 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) return PCH_ICP; case INTEL_PCH_MCC_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); + drm_WARN_ON(&dev_priv->drm, !(IS_JASPERLAKE(dev_priv) || + IS_ELKHARTLAKE(dev_priv))); /* MCC is TGP compatible */ return PCH_TGP; case INTEL_PCH_TGP_DEVICE_ID_TYPE: @@ -127,7 +128,8 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) return PCH_TGP; case INTEL_PCH_JSP_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); - drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); + drm_WARN_ON(&dev_priv->drm, !(IS_JASPERLAKE(dev_priv) || + IS_ELKHARTLAKE(dev_priv))); /* JSP is ICP compatible */ return PCH_ICP; case INTEL_PCH_ADP_DEVICE_ID_TYPE: @@ -177,7 +179,7 @@ intel_virt_detect_pch(const struct drm_i915_private *dev_priv, id = INTEL_PCH_ADP_DEVICE_ID_TYPE; else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) id = INTEL_PCH_TGP_DEVICE_ID_TYPE; - else if (IS_JSL_EHL(dev_priv)) + else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) id = INTEL_PCH_MCC_DEVICE_ID_TYPE; else if (IS_ICELAKE(dev_priv)) id = INTEL_PCH_ICP_DEVICE_ID_TYPE; @@ -186,7 +188,7 @@ intel_virt_detect_pch(const struct drm_i915_private *dev_priv, id = INTEL_PCH_CNP_DEVICE_ID_TYPE; else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv)) id = INTEL_PCH_SPT_DEVICE_ID_TYPE; - else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) + else if (IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv)) id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) id = INTEL_PCH_LPT_DEVICE_ID_TYPE; |