diff mbox series

[v2,04/11] drm/i915: Shove the PHY test into the hotplug work

Message ID 20200929233449.32323-5-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Plumb crtc state to link training code | expand

Commit Message

Ville Syrjala Sept. 29, 2020, 11:34 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Doing nay kind modeset stuff from the short hpd handler is
verboten. The ad-hoc PHY test modeset code violates this. And
by calling various link training related functions it's now
blocking further work to plumb the crtc state down into the
link training code.

Let's hack around that by pushing the PHY test stuff into the
hotplug work where it's less of a problem. Still not great but
at least acceptable. We take a few pages from the link retraining
handbook to handle the locking and whatnot.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 154 ++++++++++++++++++++----
 1 file changed, 128 insertions(+), 26 deletions(-)

Comments

kernel test robot Sept. 30, 2020, 8:10 a.m. UTC | #1
Hi Ville,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on drm-tip/drm-tip v5.9-rc7 next-20200929]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Ville-Syrjala/drm-i915-Plumb-crtc-state-to-link-training-code/20200930-073629
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-s021-20200930 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.2-201-g24bdaac6-dirty
        # https://github.com/0day-ci/linux/commit/a504af17c918ba91652d9c0c5ed45d9e0ca98dfd
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Ville-Syrjala/drm-i915-Plumb-crtc-state-to-link-training-code/20200930-073629
        git checkout a504af17c918ba91652d9c0c5ed45d9e0ca98dfd
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

	echo
	echo "sparse warnings: (new ones prefixed by >>)"
	echo
>> drivers/gpu/drm/i915/display/intel_dp.c:5977:39: sparse: sparse: mixing different enum types:
>> drivers/gpu/drm/i915/display/intel_dp.c:5977:39: sparse:    unsigned int enum drm_connector_status
>> drivers/gpu/drm/i915/display/intel_dp.c:5977:39: sparse:    unsigned int enum intel_hotplug_state

vim +5977 drivers/gpu/drm/i915/display/intel_dp.c

  5951	
  5952	/*
  5953	 * If display is now connected check links status,
  5954	 * there has been known issues of link loss triggering
  5955	 * long pulse.
  5956	 *
  5957	 * Some sinks (eg. ASUS PB287Q) seem to perform some
  5958	 * weird HPD ping pong during modesets. So we can apparently
  5959	 * end up with HPD going low during a modeset, and then
  5960	 * going back up soon after. And once that happens we must
  5961	 * retrain the link to get a picture. That's in case no
  5962	 * userspace component reacted to intermittent HPD dip.
  5963	 */
  5964	static enum intel_hotplug_state
  5965	intel_dp_hotplug(struct intel_encoder *encoder,
  5966			 struct intel_connector *connector)
  5967	{
  5968		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
  5969		struct drm_modeset_acquire_ctx ctx;
  5970		enum intel_hotplug_state state;
  5971		int ret;
  5972	
  5973		if (intel_dp->compliance.test_active &&
  5974		    intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
  5975			intel_dp_phy_test(encoder);
  5976			/* just do the PHY test and nothing else */
> 5977			return connector->base.status;
  5978		}
  5979	
  5980		state = intel_encoder_hotplug(encoder, connector);
  5981	
  5982		drm_modeset_acquire_init(&ctx, 0);
  5983	
  5984		for (;;) {
  5985			ret = intel_dp_retrain_link(encoder, &ctx);
  5986	
  5987			if (ret == -EDEADLK) {
  5988				drm_modeset_backoff(&ctx);
  5989				continue;
  5990			}
  5991	
  5992			break;
  5993		}
  5994	
  5995		drm_modeset_drop_locks(&ctx);
  5996		drm_modeset_acquire_fini(&ctx);
  5997		drm_WARN(encoder->base.dev, ret,
  5998			 "Acquiring modeset locks failed with %i\n", ret);
  5999	
  6000		/*
  6001		 * Keeping it consistent with intel_ddi_hotplug() and
  6002		 * intel_hdmi_hotplug().
  6003		 */
  6004		if (state == INTEL_HOTPLUG_UNCHANGED && !connector->hotplug_retries)
  6005			state = INTEL_HOTPLUG_RETRY;
  6006	
  6007		return state;
  6008	}
  6009	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 5c673080ecb1..6718e01909cd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5424,25 +5424,6 @@  static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp)
 	return test_result;
 }
 
-static u8 intel_dp_prepare_phytest(struct intel_dp *intel_dp)
-{
-	struct drm_dp_phy_test_params *data =
-		&intel_dp->compliance.test_data.phytest;
-
-	if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) {
-		DRM_DEBUG_KMS("DP Phy Test pattern AUX read failure\n");
-		return DP_TEST_NAK;
-	}
-
-	/*
-	 * link_mst is set to false to avoid executing mst related code
-	 * during compliance testing.
-	 */
-	intel_dp->link_mst = false;
-
-	return DP_TEST_ACK;
-}
-
 static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv =
@@ -5590,15 +5571,18 @@  static void intel_dp_process_phy_request(struct intel_dp *intel_dp)
 
 static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
 {
-	u8 test_result;
+	struct drm_dp_phy_test_params *data =
+		&intel_dp->compliance.test_data.phytest;
 
-	test_result = intel_dp_prepare_phytest(intel_dp);
-	if (test_result != DP_TEST_ACK)
-		DRM_ERROR("Phy test preparation failed\n");
+	if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) {
+		DRM_DEBUG_KMS("DP Phy Test pattern AUX read failure\n");
+		return DP_TEST_NAK;
+	}
 
-	intel_dp_process_phy_request(intel_dp);
+	/* Set test active flag here so userspace doesn't interrupt things */
+	intel_dp->compliance.test_active = true;
 
-	return test_result;
+	return DP_TEST_ACK;
 }
 
 static void intel_dp_handle_test_request(struct intel_dp *intel_dp)
@@ -5887,6 +5871,104 @@  int intel_dp_retrain_link(struct intel_encoder *encoder,
 	return 0;
 }
 
+static int intel_dp_prep_phy_test(struct intel_dp *intel_dp,
+				  struct drm_modeset_acquire_ctx *ctx,
+				  u32 *crtc_mask)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	struct drm_connector_list_iter conn_iter;
+	struct intel_connector *connector;
+	int ret = 0;
+
+	*crtc_mask = 0;
+
+	drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+	for_each_intel_connector_iter(connector, &conn_iter) {
+		struct drm_connector_state *conn_state =
+			connector->base.state;
+		struct intel_crtc_state *crtc_state;
+		struct intel_crtc *crtc;
+
+		if (!intel_dp_has_connector(intel_dp, conn_state))
+			continue;
+
+		crtc = to_intel_crtc(conn_state->crtc);
+		if (!crtc)
+			continue;
+
+		ret = drm_modeset_lock(&crtc->base.mutex, ctx);
+		if (ret)
+			break;
+
+		crtc_state = to_intel_crtc_state(crtc->base.state);
+
+		drm_WARN_ON(&i915->drm, !intel_crtc_has_dp_encoder(crtc_state));
+
+		if (!crtc_state->hw.active)
+			continue;
+
+		if (conn_state->commit &&
+		    !try_wait_for_completion(&conn_state->commit->hw_done))
+			continue;
+
+		*crtc_mask |= drm_crtc_mask(&crtc->base);
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	return ret;
+}
+
+static int intel_dp_do_phy_test(struct intel_encoder *encoder,
+				struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	u32 crtc_mask;
+	int ret;
+
+	ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex,
+			       ctx);
+	if (ret)
+		return ret;
+
+	ret = intel_dp_prep_phy_test(intel_dp, ctx, &crtc_mask);
+	if (ret)
+		return ret;
+
+	if (crtc_mask == 0)
+		return 0;
+
+	drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] PHY test\n",
+		    encoder->base.base.id, encoder->base.name);
+	intel_dp_process_phy_request(intel_dp);
+
+	return 0;
+}
+
+static void intel_dp_phy_test(struct intel_encoder *encoder)
+{
+	struct drm_modeset_acquire_ctx ctx;
+	int ret;
+
+	drm_modeset_acquire_init(&ctx, 0);
+
+	for (;;) {
+		ret = intel_dp_do_phy_test(encoder, &ctx);
+
+		if (ret == -EDEADLK) {
+			drm_modeset_backoff(&ctx);
+			continue;
+		}
+
+		break;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+	drm_WARN(encoder->base.dev, ret,
+		 "Acquiring modeset locks failed with %i\n", ret);
+}
+
 /*
  * If display is now connected check links status,
  * there has been known issues of link loss triggering
@@ -5903,10 +5985,18 @@  static enum intel_hotplug_state
 intel_dp_hotplug(struct intel_encoder *encoder,
 		 struct intel_connector *connector)
 {
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_modeset_acquire_ctx ctx;
 	enum intel_hotplug_state state;
 	int ret;
 
+	if (intel_dp->compliance.test_active &&
+	    intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
+		intel_dp_phy_test(encoder);
+		/* just do the PHY test and nothing else */
+		return connector->base.status;
+	}
+
 	state = intel_encoder_hotplug(encoder, connector);
 
 	drm_modeset_acquire_init(&ctx, 0);
@@ -6011,11 +6101,23 @@  intel_dp_short_pulse(struct intel_dp *intel_dp)
 
 	intel_psr_short_pulse(intel_dp);
 
-	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
+	switch (intel_dp->compliance.test_type) {
+	case DP_TEST_LINK_TRAINING:
 		drm_dbg_kms(&dev_priv->drm,
 			    "Link Training Compliance Test requested\n");
 		/* Send a Hotplug Uevent to userspace to start modeset */
 		drm_kms_helper_hotplug_event(&dev_priv->drm);
+		break;
+	case DP_TEST_LINK_PHY_TEST_PATTERN:
+		drm_dbg_kms(&dev_priv->drm,
+			    "PHY test pattern Compliance Test requested\n");
+		/*
+		 * Schedule long hpd to do the test
+		 *
+		 * FIXME get rid of the ad-hoc phy test modeset code
+		 * and properly incorporate it into the normal modeset.
+		 */
+		return false;
 	}
 
 	return true;