[Intel-gfx] [PATCH] drm/i915/tc: Implement the TC cold exit sequence
Souza, Jose
jose.souza at intel.com
Tue Oct 22 00:03:18 UTC 2019
On Sat, 2019-10-19 at 13:49 +0300, Imre Deak wrote:
> On Sat, Oct 19, 2019 at 02:59:14AM +0300, Souza, Jose wrote:
> > On Thu, 2019-10-03 at 17:50 +0300, Imre Deak wrote:
> > > On Mon, Sep 30, 2019 at 05:55:36PM -0700, José Roberto de Souza
> > > wrote:
> > > > This is required for legacy/static TC ports as IOM is not aware
> > > > of
> > > > the connection and will not trigger the TC cold exit.
> > > >
> > > > BSpec: 21750
> > > > BSpsc: 49294
> > > > Cc: Imre Deak <imre.deak at intel.com>
> > > > Cc: Lucas De Marchi <lucas.demarchi at intel.com>
> > > > Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
> > > > ---
> > > > drivers/gpu/drm/i915/display/intel_tc.c | 34
> > > > ++++++++++++++++++++-
> > > > ----
> > > > drivers/gpu/drm/i915/i915_reg.h | 1 +
> > > > 2 files changed, 29 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_tc.c
> > > > b/drivers/gpu/drm/i915/display/intel_tc.c
> > > > index 7773169b7331..09b78027bdd5 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_tc.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_tc.c
> > > > @@ -7,6 +7,7 @@
> > > > #include "intel_display.h"
> > > > #include "intel_display_types.h"
> > > > #include "intel_dp_mst.h"
> > > > +#include "intel_sideband.h"
> > > > #include "intel_tc.h"
> > > >
> > > > static const char *tc_port_mode_name(enum tc_port_mode mode)
> > > > @@ -169,6 +170,22 @@ static void
> > > > tc_port_fixup_legacy_flag(struct
> > > > intel_digital_port *dig_port,
> > > > dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> > > > }
> > > >
> > > > +static int tc_cold_exit_request(struct drm_i915_private
> > > > *dev_priv)
> > > > +{
> > > > + int ret;
> > > > +
> > > > + do {
> > > > + ret = sandybridge_pcode_write_timeout(dev_priv,
> > > > + ICL_PCODE
> > > > _EXIT_TC
> > > > COLD, 0,
> > > > + 250, 1);
> > > > +
> > > > + } while (ret == -EAGAIN);
> > > > +
> > > > + DRM_DEBUG_KMS("tccold exit %s\n", ret == 0 ?
> > > > "succeeded" :
> > > > "failed");
> > > > +
> > > > + return ret;
> > > > +}
> > > > +
> > > > static u32 tc_port_live_status_mask(struct intel_digital_port
> > > > *dig_port)
> > > > {
> > > > struct drm_i915_private *i915 = to_i915(dig_port-
> > > > > base.base.dev);
> > > > @@ -177,13 +194,21 @@ static u32
> > > > tc_port_live_status_mask(struct
> > > > intel_digital_port *dig_port)
> > > > u32 mask = 0;
> > > > u32 val;
> > > >
> > > > + if (intel_uncore_read(uncore, SDEISR) &
> > > > SDE_TC_HOTPLUG_ICP(tc_port))
> > > > + mask |= BIT(TC_PORT_LEGACY);
> > > > +
> > > > val = intel_uncore_read(uncore,
> > > > PORT_TX_DFLEXDPSP(dig_port-
> > > > > tc_phy_fia));
> > > >
> > > > if (val == 0xffffffff) {
> > > > - DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, nothing
> > > > connected\n",
> > > > - dig_port->tc_port_name);
> > > > - return mask;
> > > > + if (mask)
> > > > + tc_cold_exit_request(i915);
> >
> > Sorry for the delay, was OOO.
> >
> > > The semantic of the mbox command this needs is inherently racy on
> > > systems with preemption, the instruction to use it is:
> > >
> > > """
> > > Issue GT Driver mailbox command to exit TCCOLD, then complete
> > > steps
> > > b-d
> > > within 500 milliseconds to prevent re-entry.
> > > """
> > >
> > > We'd have to reach the point where we enable the AUX power in
> > > 500ms,
> > > which can't be guaranteed. Moreover TCCOLD could be entered just
> > > after
> > > reading PORT_TX_DFLEXDPSP, so we may not detect it.
> > >
> > > What we can do - after discussing with HW folks - is to first
> > > request
> > > AUX power and then issue the mbox command, which prevents TCCOLD
> > > re-entry until releasing the AUX power request. This also needs
> > > ignoring
> > > the timeout of the AUX power enabling ACK, since it will only be
> > > ACKed
> > > after exiting TCCOLD.
> >
> > Huum looks more robust indeed.
> >
> > > So I think we should block TCCOLD this way in
> > > __intel_tc_port_lock():
> > >
> > > if tc_link_refcount==0:
> > > intel_display_power_get(POWER_DOMAIN_AUX_<port>)
> > > tc_cold_exit_request()
> >
> > So for non-legacy the IOM request to exit TCCOLD could have timed
> > out
> > at this point. But for most cases this will not happen, why not
> > here
> > read one FIA register and check if == 0xffffffff if so we call
> > tc_cold_exit_request().
>
> That would be racy, TCCOLD could be entered right after doing the FIA
> reg check. Getting the AUX power ref alone won't prevent a TCCOLD
> entry
> until the PCODE command has completed.
>
> > > if intel_tc_port_needs_reset():
> > > intel_tc_port_reset_mode()
> > > if tc_mode != LEGACY:
> > > intel_display_power_put(POWER_DOMAIN_AUX_<port>
> >
> > Also why power_put() for non-legacy? a preemption could happen
> > after
> > lock() and cause a TCCOLD before the needed reads/writes to FIA is
> > done.
>
> The new PCODE command was only added for legacy and the AUX power
> reference makes a difference only in that mode. In DP-alt mode the
> DPCSSS.DPPMSTC flag prevents TCCOLD.
>
> In TBT mode the TBT AUX power ref would not prevent TCCOLD. In that
> mode
> we don't access FIA regs afterwards and
> "the TBT controller prevents TCCOLD while it uses the connection".
Makes sense, well the only doubt that I have is if getting
POWER_DOMAIN_AUX_<port>_TBT will prevent TCCOLD for legacy and alt-
mode, as at this point we still don't know if it is alt-mode, TBT or
legacy(we know that is legacy but live status could be reporting
something else tc_port_fixup_legacy_flag())
>
> > Better remove this block and only power_put() when removing the
> > last
> > reference on intel_tc_port_unlock()
> >
> > > )
> > >
> > > then unblock TCCOLD in intel_tc_port_unlock():
> > >
> > > if tc_link_refcount==0 and tc_mode == LEGACY:
> > > intel_display_power_put(POWER_DOMAIN_AUX_<port>)
> > >
> > > > +
> > > > + if (val == 0xffffffff) {
> > > > + DRM_DEBUG_KMS("Port %s: PHY in TCCOLD,
> > > > nothing
> > > > connected\n",
> > > > + dig_port->tc_port_name);
> > > > + return mask;
> > > > + }
> > > > }
> > > >
> > > > if (val & TC_LIVE_STATE_TBT(dig_port->tc_phy_fia_idx))
> > > > @@ -191,9 +216,6 @@ static u32 tc_port_live_status_mask(struct
> > > > intel_digital_port *dig_port)
> > > > if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx))
> > > > mask |= BIT(TC_PORT_DP_ALT);
> > > >
> > > > - if (intel_uncore_read(uncore, SDEISR) &
> > > > SDE_TC_HOTPLUG_ICP(tc_port))
> > > > - mask |= BIT(TC_PORT_LEGACY);
> > > > -
> > > > /* The sink can be connected only in a single mode. */
> > > > if (!WARN_ON(hweight32(mask) > 1))
> > > > tc_port_fixup_legacy_flag(dig_port, mask);
> > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > b/drivers/gpu/drm/i915/i915_reg.h
> > > > index 058aa5ca8b73..35c3724b7fef 100644
> > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > @@ -8860,6 +8860,7 @@ enum {
> > > > #define ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point)
> > > > (((poin
> > > > t) << 16) | (0x1 << 8))
> > > > #define GEN6_PCODE_READ_D_COMP 0x10
> > > > #define GEN6_PCODE_WRITE_D_COMP 0x11
> > > > +#define ICL_PCODE_EXIT_TCCOLD 0x12
> > > > #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17
> > > > #define DISPLAY_IPS_CONTROL 0x19
> > > > /* See also IPS_CTL */
> > > > --
> > > > 2.23.0
> > > >
More information about the Intel-gfx
mailing list