Skip to content

Commit 7779c5e

Browse files
robclarkairlied
authored andcommitted
drm/dp: move hw_mutex up the call stack
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 <dwysocha@redhat.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1274157 Cc: stable@vger.kernel.org Signed-off-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com>
1 parent 5456248 commit 7779c5e

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

drivers/gpu/drm/drm_dp_helper.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,16 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
179179
{
180180
struct drm_dp_aux_msg msg;
181181
unsigned int retry;
182-
int err;
182+
int err = 0;
183183

184184
memset(&msg, 0, sizeof(msg));
185185
msg.address = offset;
186186
msg.request = request;
187187
msg.buffer = buffer;
188188
msg.size = size;
189189

190+
mutex_lock(&aux->hw_mutex);
191+
190192
/*
191193
* The specification doesn't give any recommendation on how often to
192194
* retry native transactions. We used to retry 7 times like for
@@ -195,25 +197,24 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
195197
*/
196198
for (retry = 0; retry < 32; retry++) {
197199

198-
mutex_lock(&aux->hw_mutex);
199200
err = aux->transfer(aux, &msg);
200-
mutex_unlock(&aux->hw_mutex);
201201
if (err < 0) {
202202
if (err == -EBUSY)
203203
continue;
204204

205-
return err;
205+
goto unlock;
206206
}
207207

208208

209209
switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
210210
case DP_AUX_NATIVE_REPLY_ACK:
211211
if (err < size)
212-
return -EPROTO;
213-
return err;
212+
err = -EPROTO;
213+
goto unlock;
214214

215215
case DP_AUX_NATIVE_REPLY_NACK:
216-
return -EIO;
216+
err = -EIO;
217+
goto unlock;
217218

218219
case DP_AUX_NATIVE_REPLY_DEFER:
219220
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
@@ -222,7 +223,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
222223
}
223224

224225
DRM_DEBUG_KMS("too many retries, giving up\n");
225-
return -EIO;
226+
err = -EIO;
227+
228+
unlock:
229+
mutex_unlock(&aux->hw_mutex);
230+
return err;
226231
}
227232

228233
/**
@@ -544,9 +549,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
544549
int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz));
545550

546551
for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) {
547-
mutex_lock(&aux->hw_mutex);
548552
ret = aux->transfer(aux, msg);
549-
mutex_unlock(&aux->hw_mutex);
550553
if (ret < 0) {
551554
if (ret == -EBUSY)
552555
continue;
@@ -685,6 +688,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
685688

686689
memset(&msg, 0, sizeof(msg));
687690

691+
mutex_lock(&aux->hw_mutex);
692+
688693
for (i = 0; i < num; i++) {
689694
msg.address = msgs[i].addr;
690695
drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
@@ -739,6 +744,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
739744
msg.size = 0;
740745
(void)drm_dp_i2c_do_msg(aux, &msg);
741746

747+
mutex_unlock(&aux->hw_mutex);
748+
742749
return err;
743750
}
744751

0 commit comments

Comments
 (0)