Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754953AbcD0AO2 (ORCPT ); Tue, 26 Apr 2016 20:14:28 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:40113 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753976AbcDZXN6 (ORCPT ); Tue, 26 Apr 2016 19:13:58 -0400 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Dave Airlie" , "Dave Wysochanski" , "Ville =?UTF-8?Q?Syrj=C3=A4l=C3=A4?=" , "Rob Clark" , "Daniel Vetter" Date: Wed, 27 Apr 2016 01:02:21 +0200 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 159/217] drm/dp: move hw_mutex up the call stack In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8426:ae4:c500:9cba:69ae:962d:6167 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3358 Lines: 124 3.16.35-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Rob Clark commit 7779c5e23c5132c22a219f1f5554ef81dd15ee91 upstream. 1) don't let other threads trying to bang on aux channel interrupt the defer timeout/logic 2) don't let other threads interrupt the i2c over aux logic Technically, according to people who actually have the DP spec, this should not be required. In practice, it makes some troublesome Dell monitor (and perhaps others) work, so probably a case of "It's compliant if it works with windows" on the hw vendor's part.. v2: rebased to come before DPCD/AUX logging patch for easier backport to stable branches. Reported-by: Dave Wysochanski Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1274157 Signed-off-by: Rob Clark Reviewed-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie [bwh: Backported to 3.16: adjust context] Signed-off-by: Ben Hutchings --- drivers/gpu/drm/drm_dp_helper.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -368,7 +368,7 @@ static int drm_dp_dpcd_access(struct drm { struct drm_dp_aux_msg msg; unsigned int retry; - int err; + int err = 0; memset(&msg, 0, sizeof(msg)); msg.address = offset; @@ -376,6 +376,8 @@ static int drm_dp_dpcd_access(struct drm msg.buffer = buffer; msg.size = size; + mutex_lock(&aux->hw_mutex); + /* * The specification doesn't give any recommendation on how often to * retry native transactions. We used to retry 7 times like for @@ -384,25 +386,24 @@ static int drm_dp_dpcd_access(struct drm */ for (retry = 0; retry < 32; retry++) { - mutex_lock(&aux->hw_mutex); err = aux->transfer(aux, &msg); - mutex_unlock(&aux->hw_mutex); if (err < 0) { if (err == -EBUSY) continue; - return err; + goto unlock; } switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { case DP_AUX_NATIVE_REPLY_ACK: if (err < size) - return -EPROTO; - return err; + err = -EPROTO; + goto unlock; case DP_AUX_NATIVE_REPLY_NACK: - return -EIO; + err = -EIO; + goto unlock; case DP_AUX_NATIVE_REPLY_DEFER: usleep_range(400, 500); @@ -411,7 +412,11 @@ static int drm_dp_dpcd_access(struct drm } DRM_DEBUG_KMS("too many retries, giving up\n"); - return -EIO; + err = -EIO; + +unlock: + mutex_unlock(&aux->hw_mutex); + return err; } /** @@ -600,9 +605,7 @@ static int drm_dp_i2c_do_msg(struct drm_ * before giving up the AUX transaction. */ for (retry = 0; retry < 7; retry++) { - mutex_lock(&aux->hw_mutex); err = aux->transfer(aux, msg); - mutex_unlock(&aux->hw_mutex); if (err < 0) { if (err == -EBUSY) continue; @@ -682,6 +685,8 @@ static int drm_dp_i2c_xfer(struct i2c_ad memset(&msg, 0, sizeof(msg)); + mutex_lock(&aux->hw_mutex); + for (i = 0; i < num; i++) { msg.address = msgs[i].addr; msg.request = (msgs[i].flags & I2C_M_RD) ? @@ -726,6 +731,8 @@ static int drm_dp_i2c_xfer(struct i2c_ad msg.size = 0; (void)drm_dp_i2c_do_msg(aux, &msg); + mutex_unlock(&aux->hw_mutex); + return err; }