瀏覽代碼

disp: msm: dp: synchronize debug and aux common buffer handling

DP debug module is run by external script for automation testing.
DP aux and debug modules operate on shared buffers. In some race
conditions, aux and debug module can go out of sync resulting in
automation failures. Lock the buffers to make sure there are no
race conditions.

Change-Id: If0ae370c22cf035f3177666bd714221d6b3cd56e
Signed-off-by: Ajay Singh Parmar <[email protected]>
Ajay Singh Parmar 6 年之前
父節點
當前提交
4ca56193c5
共有 3 個文件被更改,包括 40 次插入46 次删除
  1. 21 21
      msm/dp/dp_aux.c
  2. 2 0
      msm/dp/dp_aux.h
  3. 17 25
      msm/dp/dp_debug.c

+ 21 - 21
msm/dp/dp_aux.c

@@ -495,35 +495,33 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
 	}
 	}
 
 
 	if (aux->native) {
 	if (aux->native) {
+		mutex_lock(aux->dp_aux.access_lock);
 		aux->dp_aux.reg = msg->address;
 		aux->dp_aux.reg = msg->address;
 		aux->dp_aux.read = aux->read;
 		aux->dp_aux.read = aux->read;
 		aux->dp_aux.size = msg->size;
 		aux->dp_aux.size = msg->size;
 
 
-		reinit_completion(&aux->comp);
+		if (!aux->read)
+			memcpy(aux->dpcd + msg->address,
+				msg->buffer, msg->size);
 
 
-		if (aux->read) {
-			timeout = wait_for_completion_timeout(&aux->comp, HZ);
-			if (!timeout) {
-				DP_ERR("read timeout: 0x%x\n", msg->address);
-				atomic_set(&aux->aborted, 1);
-				ret = -ETIMEDOUT;
-				goto end;
-			}
+		reinit_completion(&aux->comp);
+		mutex_unlock(aux->dp_aux.access_lock);
+
+		timeout = wait_for_completion_timeout(&aux->comp, HZ * 2);
+		if (!timeout) {
+			DP_ERR("%s timeout: 0x%x\n",
+				aux->read ? "read" : "write",
+				msg->address);
+			atomic_set(&aux->aborted, 1);
+			ret = -ETIMEDOUT;
+			goto end;
+		}
 
 
+		mutex_lock(aux->dp_aux.access_lock);
+		if (aux->read)
 			memcpy(msg->buffer, aux->dpcd + msg->address,
 			memcpy(msg->buffer, aux->dpcd + msg->address,
 				msg->size);
 				msg->size);
-		} else {
-			memcpy(aux->dpcd + msg->address, msg->buffer,
-				msg->size);
-
-			timeout = wait_for_completion_timeout(&aux->comp, HZ);
-			if (!timeout) {
-				DP_ERR("write timeout: 0x%x\n", msg->address);
-				atomic_set(&aux->aborted, 1);
-				ret = -ETIMEDOUT;
-				goto end;
-			}
-		}
+		mutex_unlock(aux->dp_aux.access_lock);
 
 
 		aux->aux_error_num = DP_AUX_ERR_NONE;
 		aux->aux_error_num = DP_AUX_ERR_NONE;
 	} else {
 	} else {
@@ -725,6 +723,8 @@ static void dp_aux_dpcd_updated(struct dp_aux *dp_aux)
 
 
 	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
 	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
 
 
+	/* make sure wait has started */
+	usleep_range(20, 30);
 	complete(&aux->comp);
 	complete(&aux->comp);
 }
 }
 
 

+ 2 - 0
msm/dp/dp_aux.h

@@ -40,6 +40,8 @@ struct dp_aux {
 
 
 	bool read;
 	bool read;
 
 
+	struct mutex *access_lock;
+
 	struct drm_dp_aux *drm_aux;
 	struct drm_dp_aux *drm_aux;
 	int (*drm_aux_register)(struct dp_aux *aux);
 	int (*drm_aux_register)(struct dp_aux *aux);
 	void (*drm_aux_deregister)(struct dp_aux *aux);
 	void (*drm_aux_deregister)(struct dp_aux *aux);

+ 17 - 25
msm/dp/dp_debug.c

@@ -178,7 +178,6 @@ static ssize_t dp_debug_write_dpcd(struct file *file,
 	ssize_t rc = count;
 	ssize_t rc = count;
 	char offset_ch[5];
 	char offset_ch[5];
 	u32 offset, data_len;
 	u32 offset, data_len;
-	u32 extended_capability_bytes = 0;
 	const u32 dp_receiver_cap_size = 16;
 	const u32 dp_receiver_cap_size = 16;
 
 
 	if (!debug)
 	if (!debug)
@@ -252,25 +251,9 @@ static ssize_t dp_debug_write_dpcd(struct file *file,
 bail:
 bail:
 	kfree(buf);
 	kfree(buf);
 
 
-	/*
-	 * If extension bit is set then increase the length
-	 * of user input to account for the extra bytes
-	 */
-	if (dpcd && (dpcd_buf_index > DP_RECEIVER_CAP_SIZE) &&
-			(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
-			 DP_EXT_REC_CAP_FIELD))
-		extended_capability_bytes = 4;
-
-	/*
-	 * Reset panel's dpcd in case of any failure. Also, set the
-	 * panel's dpcd only if a full dpcd is provided with offset as 0.
-	 */
-	if (!dpcd || (!offset &&
-			(data_len == (dp_receiver_cap_size +
-			extended_capability_bytes))) ||
-			(offset == 0xffff)) {
+	if (!dpcd || (size / char_to_nib) >= dp_receiver_cap_size ||
+	    offset == 0xffff) {
 		debug->panel->set_dpcd(debug->panel, dpcd);
 		debug->panel->set_dpcd(debug->panel, dpcd);
-
 		/*
 		/*
 		 * print dpcd status as this code is executed
 		 * print dpcd status as this code is executed
 		 * only while running in debug mode which is manually
 		 * only while running in debug mode which is manually
@@ -280,10 +263,11 @@ bail:
 			DP_INFO("[%s]\n", "CLEAR");
 			DP_INFO("[%s]\n", "CLEAR");
 		else
 		else
 			DP_INFO("[%s]\n", "SET");
 			DP_INFO("[%s]\n", "SET");
-	} else
-		debug->aux->dpcd_updated(debug->aux);
+	}
 
 
 	mutex_unlock(&debug->lock);
 	mutex_unlock(&debug->lock);
+
+	debug->aux->dpcd_updated(debug->aux);
 	return rc;
 	return rc;
 }
 }
 
 
@@ -295,16 +279,18 @@ static ssize_t dp_debug_read_dpcd(struct file *file,
 	int const buf_size = SZ_4K;
 	int const buf_size = SZ_4K;
 	u32 offset = 0;
 	u32 offset = 0;
 	u32 len = 0;
 	u32 len = 0;
+	bool notify = false;
 
 
 	if (!debug || !debug->aux || !debug->dpcd)
 	if (!debug || !debug->aux || !debug->dpcd)
 		return -ENODEV;
 		return -ENODEV;
 
 
+	mutex_lock(&debug->lock);
 	if (*ppos)
 	if (*ppos)
-		return 0;
+		goto end;
 
 
 	buf = kzalloc(buf_size, GFP_KERNEL);
 	buf = kzalloc(buf_size, GFP_KERNEL);
 	if (!buf)
 	if (!buf)
-		return -ENOMEM;
+		goto end;
 
 
 	len += snprintf(buf, buf_size, "0x%x", debug->aux->reg);
 	len += snprintf(buf, buf_size, "0x%x", debug->aux->reg);
 
 
@@ -318,8 +304,7 @@ static ssize_t dp_debug_read_dpcd(struct file *file,
 				debug->dpcd[debug->aux->reg + offset++]);
 				debug->dpcd[debug->aux->reg + offset++]);
 		}
 		}
 
 
-		if (debug->dp_debug.sim_mode && debug->aux->dpcd_updated)
-			debug->aux->dpcd_updated(debug->aux);
+		notify = true;
 	}
 	}
 
 
 	len = min_t(size_t, count, len);
 	len = min_t(size_t, count, len);
@@ -327,6 +312,12 @@ static ssize_t dp_debug_read_dpcd(struct file *file,
 		*ppos += len;
 		*ppos += len;
 
 
 	kfree(buf);
 	kfree(buf);
+end:
+	mutex_unlock(&debug->lock);
+
+	if (notify)
+		debug->aux->dpcd_updated(debug->aux);
+
 	return len;
 	return len;
 }
 }
 
 
@@ -2274,6 +2265,7 @@ struct dp_debug *dp_debug_get(struct dp_debug_in *in)
 		goto error;
 		goto error;
 	}
 	}
 
 
+	debug->aux->access_lock = &debug->lock;
 	dp_debug->get_edid = dp_debug_get_edid;
 	dp_debug->get_edid = dp_debug_get_edid;
 	dp_debug->abort = dp_debug_abort;
 	dp_debug->abort = dp_debug_abort;