瀏覽代碼

Merge "disp: msm: sde: trigger pm_qos vote with irq enable"

qctecmdr 5 年之前
父節點
當前提交
048211256b
共有 3 個文件被更改,包括 36 次插入5 次删除
  1. 14 0
      msm/sde/sde_core_irq.c
  2. 11 5
      msm/sde/sde_kms.c
  3. 11 0
      msm/sde/sde_kms.h

+ 14 - 0
msm/sde/sde_core_irq.c

@@ -97,6 +97,7 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx)
 {
 	unsigned long irq_flags;
 	int ret = 0;
+	bool update_vote = false;
 
 	if (!sde_kms || !sde_kms->hw_intr ||
 			!sde_kms->irq_obj.enable_counts ||
@@ -127,11 +128,16 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx)
 		spin_lock_irqsave(&sde_kms->hw_intr->irq_lock, irq_flags);
 		ret = sde_kms->hw_intr->ops.enable_irq_nolock(
 				sde_kms->hw_intr, irq_idx);
+		if (atomic_inc_return(&sde_kms->irq_obj.curr_irq_enable_count)
+				== 1)
+			update_vote = true;
 		spin_unlock_irqrestore(&sde_kms->hw_intr->irq_lock, irq_flags);
 	}
 
 	if (ret)
 		SDE_ERROR("Fail to enable IRQ for irq_idx:%d\n", irq_idx);
+	else if (update_vote)
+		sde_kms_irq_enable_notify(sde_kms, true);
 
 	SDE_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret);
 
@@ -162,6 +168,7 @@ static int _sde_core_irq_disable(struct sde_kms *sde_kms, int irq_idx)
 {
 	int ret = 0;
 	unsigned long irq_flags;
+	bool update_vote = false;
 
 	if (!sde_kms || !sde_kms->hw_intr || !sde_kms->irq_obj.enable_counts) {
 		SDE_ERROR("invalid params\n");
@@ -184,10 +191,16 @@ static int _sde_core_irq_disable(struct sde_kms *sde_kms, int irq_idx)
 		&& atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]) == 0)
 		ret = sde_kms->hw_intr->ops.disable_irq_nolock(
 				sde_kms->hw_intr, irq_idx);
+
+	if (atomic_add_unless(&sde_kms->irq_obj.curr_irq_enable_count, -1, 0)
+		&& atomic_read(&sde_kms->irq_obj.curr_irq_enable_count) == 0)
+		update_vote = true;
 	spin_unlock_irqrestore(&sde_kms->hw_intr->irq_lock, irq_flags);
 
 	if (ret)
 		SDE_ERROR("Fail to disable IRQ for irq_idx:%d\n", irq_idx);
+	else if (update_vote)
+		sde_kms_irq_enable_notify(sde_kms, false);
 	SDE_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret);
 
 	return ret;
@@ -484,6 +497,7 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms)
 		if (sde_kms->irq_obj.irq_counts)
 			atomic_set(&sde_kms->irq_obj.irq_counts[i], 0);
 	}
+	atomic_set(&sde_kms->irq_obj.curr_irq_enable_count, 0);
 }
 
 int sde_core_irq_postinstall(struct sde_kms *sde_kms)

+ 11 - 5
msm/sde/sde_kms.c

@@ -3004,7 +3004,7 @@ static int _sde_kms_active_override(struct sde_kms *sde_kms, bool enable)
 	return 0;
 }
 
-static void sde_kms_update_pm_qos_irq_request(struct sde_kms *sde_kms)
+static void _sde_kms_update_pm_qos_irq_request(struct sde_kms *sde_kms)
 {
 	struct device *cpu_dev;
 	int cpu = 0;
@@ -3033,7 +3033,7 @@ static void sde_kms_update_pm_qos_irq_request(struct sde_kms *sde_kms)
 	}
 }
 
-static void sde_kms_remove_pm_qos_irq_request(struct sde_kms *sde_kms)
+static void _sde_kms_remove_pm_qos_irq_request(struct sde_kms *sde_kms)
 {
 	struct device *cpu_dev;
 	int cpu = 0;
@@ -3057,6 +3057,14 @@ static void sde_kms_remove_pm_qos_irq_request(struct sde_kms *sde_kms)
 	}
 }
 
+void sde_kms_irq_enable_notify(struct sde_kms *sde_kms, bool enable)
+{
+	if (enable)
+		_sde_kms_update_pm_qos_irq_request(sde_kms);
+	else
+		_sde_kms_remove_pm_qos_irq_request(sde_kms);
+}
+
 static void sde_kms_irq_affinity_notify(
 		struct irq_affinity_notify *affinity_notify,
 		const cpumask_t *mask)
@@ -3077,7 +3085,7 @@ static void sde_kms_irq_affinity_notify(
 
 	// request vote with updated irq cpu mask
 	if (sde_kms->irq_enabled)
-		sde_kms_update_pm_qos_irq_request(sde_kms);
+		_sde_kms_update_pm_qos_irq_request(sde_kms);
 
 	mutex_unlock(&priv->phandle.phandle_lock);
 }
@@ -3104,9 +3112,7 @@ static void sde_kms_handle_power_event(u32 event_type, void *usr)
 		sde_kms_init_shared_hw(sde_kms);
 		_sde_kms_set_lutdma_vbif_remap(sde_kms);
 		sde_kms->first_kickoff = true;
-		sde_kms_update_pm_qos_irq_request(sde_kms);
 	} else if (event_type == SDE_POWER_EVENT_PRE_DISABLE) {
-		sde_kms_remove_pm_qos_irq_request(sde_kms);
 		sde_irq_update(msm_kms, false);
 		sde_kms->first_kickoff = false;
 		_sde_kms_active_override(sde_kms, true);

+ 11 - 0
msm/sde/sde_kms.h

@@ -222,6 +222,8 @@ struct sde_irq_callback {
  * @enable_counts array of IRQ enable counts
  * @cb_lock:      callback lock
  * @debugfs_file: debugfs file for irq statistics
+ * @curr_irq_enable_count: Atomic counter keep track of total current irq enable
+ *                         It is used to keep pm_qos vote on CPU.
  */
 struct sde_irq {
 	u32 total_irqs;
@@ -230,6 +232,7 @@ struct sde_irq {
 	atomic_t *irq_counts;
 	spinlock_t cb_lock;
 	struct dentry *debugfs_file;
+	atomic_t curr_irq_enable_count;
 };
 
 /**
@@ -667,4 +670,12 @@ void sde_kms_timeline_status(struct drm_device *dev);
  */
 int sde_kms_handle_recovery(struct drm_encoder *encoder);
 
+/**
+ * Notifies the irq enable on first interrupt enable and irq disable
+ * on last interrupt disable.
+ * @sde_kms: poiner to sde_kms structure
+ * @enable: true if irq enabled, false for disabled state.
+ */
+void sde_kms_irq_enable_notify(struct sde_kms *sde_kms, bool enable);
+
 #endif /* __sde_kms_H__ */