Explorar el Código

qcacmn: modify HIF NAPI blacklist mechanism

The existing HIF NAPI blacklist feature uses irq_blacklist_on(off) APIs
which make a call to the userspace irq_balancer.

Replace these APIs with kernel API irq_modify_status to mark (or unmark) the
individual interrupts with IRQ_NO_BALANCING flag. Once marked, the
msm-irq-balancer will not be able to move the CE interrupts around.

Change-Id: I4d780fa8780b42a668006e13a49eb1299304e633
CRs-Fixed: 1114161
Mohit Khanna hace 8 años
padre
commit
012bfe3098
Se han modificado 2 ficheros con 74 adiciones y 26 borrados
  1. 1 1
      hif/inc/hif_napi.h
  2. 73 25
      hif/src/hif_napi.c

+ 1 - 1
hif/inc/hif_napi.h

@@ -173,7 +173,7 @@ enum qca_blacklist_op {
 	BLACKLIST_ON
 };
 
-int hif_napi_cpu_blacklist(uint8_t flags, enum qca_blacklist_op op);
+int hif_napi_cpu_blacklist(struct qca_napi_data *napid, enum qca_blacklist_op op);
 /**
  * Local interface to HIF implemented functions of NAPI CPU affinity management.
  * Note:

+ 73 - 25
hif/src/hif_napi.c

@@ -39,6 +39,7 @@
 #include <linux/cpu.h>
 #include <linux/topology.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #ifdef HELIUMPLUS
 #include <soc/qcom/irq-helper.h>
 #include <linux/sched/core_ctl.h>
@@ -76,7 +77,11 @@ static int hif_napi_cpu_migrate(struct qca_napi_data *napid, int cpu,
 	return 0;
 }
 
-int hif_napi_cpu_blacklist(enum qca_blacklist_op op) { return 0; }
+int hif_napi_cpu_blacklist(struct qca_napi_data *napid,
+					enum qca_blacklist_op op)
+{
+	return 0;
+}
 #endif /* HELIUMPLUS */
 
 /**
@@ -594,22 +599,21 @@ int hif_napi_event(struct hif_opaque_softc *hif_ctx, enum qca_napi_event event,
 	}; /* switch */
 
 
-	qdf_spin_unlock_bh(&(napid->lock));
-
-	/* Call this API without spin_locks hif_napi_cpu_blacklist */
 	switch (blacklist_pending) {
 	case BLACKLIST_ON_PENDING:
 		/* assume the control of WLAN IRQs */
-		hif_napi_cpu_blacklist(napid->flags, BLACKLIST_ON);
+		hif_napi_cpu_blacklist(napid, BLACKLIST_ON);
 		break;
 	case BLACKLIST_OFF_PENDING:
 		/* yield the control of WLAN IRQs */
-		hif_napi_cpu_blacklist(napid->flags, BLACKLIST_OFF);
+		hif_napi_cpu_blacklist(napid, BLACKLIST_OFF);
 		break;
 	default: /* nothing to do */
 		break;
 	} /* switch blacklist_pending */
 
+	qdf_spin_unlock_bh(&(napid->lock));
+
 	if (prev_state != napid->state) {
 		if (napid->state == ENABLE_NAPI_MASK) {
 			rc = 1;
@@ -724,15 +728,19 @@ bool hif_napi_correct_cpu(struct qca_napi_info *napi_info)
 	if (napid->flags & QCA_NAPI_FEATURE_CPU_CORRECTION) {
 
 		cpu = qdf_get_cpu();
-		if (unlikely((hif_napi_cpu_blacklist(napid->flags,
+		if (unlikely((hif_napi_cpu_blacklist(napid,
 						BLACKLIST_QUERY) > 0) &&
 						(cpu != napi_info->cpu))) {
 			right_cpu = false;
 
 			NAPI_DEBUG("interrupt on wrong CPU, correcting");
 			cpumask.bits[0] = (0x01 << napi_info->cpu);
+
+			irq_modify_status(napi_info->irq, IRQ_NO_BALANCING, 0);
 			rc = irq_set_affinity_hint(napi_info->irq,
 						   &cpumask);
+			irq_modify_status(napi_info->irq, 0, IRQ_NO_BALANCING);
+
 			if (rc)
 				HIF_ERROR("error setting irq affinity hint: %d", rc);
 			else
@@ -907,9 +915,10 @@ void hif_napi_update_yield_stats(struct CE_state *ce_state,
 		return;
 	} else {
 		napi_data = &(hif->napi_data);
-		if (unlikely(NULL == napi_data))
+		if (unlikely(NULL == napi_data)) {
 			QDF_ASSERT(NULL != napi_data);
-		return;
+			return;
+		}
 	}
 
 	ce_id = ce_state->id;
@@ -1330,6 +1339,8 @@ static int hncm_migrate_to(struct qca_napi_data *napid,
 	NAPI_DEBUG("-->%s(napi_cd=%d, didx=%d)", __func__, napi_ce, didx);
 
 	cpumask.bits[0] = (1 << didx);
+
+	irq_modify_status(napid->napis[napi_ce].irq, IRQ_NO_BALANCING, 0);
 	rc = irq_set_affinity_hint(napid->napis[napi_ce].irq, &cpumask);
 
 	/* unmark the napis bitmap in the cpu table */
@@ -1487,20 +1498,56 @@ hncm_return:
 	return rc;
 }
 
+
 /**
- * hif_napi_cpu_blacklist() - calls kernel API to enable/disable blacklisting
- * @flags: NAPI feature flags
+ * hif_napi_bl_irq() - calls irq_modify_status to enable/disable blacklisting
+ * @napid: pointer to qca_napi_data structure
+ * @bl_flag: blacklist flag to enable/disable blacklisting
+ *
+ * The function enables/disables blacklisting for all the copy engine
+ * interrupts on which NAPI is enabled.
+ *
+ * Return: None
+ */
+static inline void hif_napi_bl_irq(struct qca_napi_data *napid, bool bl_flag)
+{
+	int i;
+	for (i = 0; i < CE_COUNT_MAX; i++) {
+		/* check if NAPI is enabled on the CE */
+		if (!(napid->ce_map & (0x01 << i)))
+			continue;
+
+		if (bl_flag == true)
+			irq_modify_status(napid->napis[i].irq,
+					  0, IRQ_NO_BALANCING);
+		else
+			irq_modify_status(napid->napis[i].irq,
+					  IRQ_NO_BALANCING, 0);
+		HIF_INFO("%s: bl_flag %d CE %d", __func__, bl_flag, i);
+	}
+}
+
+/**
+ * hif_napi_cpu_blacklist() - en(dis)ables blacklisting for NAPI RX interrupts.
+ * @napid: pointer to qca_napi_data structure
  * @op: blacklist operation to perform
  *
+ * The function enables/disables/queries blacklisting for all CE RX
+ * interrupts with NAPI enabled. Besides blacklisting, it also enables/disables
+ * core_ctl_set_boost.
+ * Once blacklisting is enabled, the interrupts will not be managed by the IRQ
+ * balancer.
+ *
  * Return: -EINVAL, in case IRQ_BLACKLISTING and CORE_CTL_BOOST is not enabled
  *         for BLACKLIST_QUERY op - blacklist refcount
- *         for BLACKLIST_ON op    - return value from kernel blacklist API
- *         for BLACKLIST_OFF op   - return value from kernel blacklist API
+ *         for BLACKLIST_ON op    - return value from core_ctl_set_boost API
+ *         for BLACKLIST_OFF op   - return value from core_ctl_set_boost API
  */
-int hif_napi_cpu_blacklist(uint8_t flags, enum qca_blacklist_op op)
+int hif_napi_cpu_blacklist(struct qca_napi_data *napid, enum qca_blacklist_op op)
 {
 	int rc = 0;
 	static int ref_count; /* = 0 by the compiler */
+	uint8_t flags = napid->flags;
 	bool bl_en = flags & QCA_NAPI_FEATURE_IRQ_BLACKLISTING;
 	bool ccb_en = flags & QCA_NAPI_FEATURE_CORE_CTL_BOOST;
 
@@ -1517,22 +1564,23 @@ int hif_napi_cpu_blacklist(uint8_t flags, enum qca_blacklist_op op)
 		break;
 	case BLACKLIST_ON:
 		ref_count++;
-		rc = irq_blacklist_on();
-		NAPI_DEBUG("blacklist_on() returns %d", rc);
-
-		rc = core_ctl_set_boost(true);
-		NAPI_DEBUG("boost_on() returns %d - refcnt=%d", rc, ref_count);
+		rc = 0;
+		if (ref_count == 1) {
+			rc = core_ctl_set_boost(true);
+			NAPI_DEBUG("boost_on() returns %d - refcnt=%d",
+				rc, ref_count);
+			hif_napi_bl_irq(napid, true);
+		}
 		break;
-
 	case BLACKLIST_OFF:
-		while (ref_count > 0) {
-			rc = irq_blacklist_off();
-			NAPI_DEBUG("blacklist_off() returns %d", rc);
-
+		if (ref_count)
+			ref_count--;
+		rc = 0;
+		if (ref_count == 0) {
 			rc = core_ctl_set_boost(false);
 			NAPI_DEBUG("boost_off() returns %d - refcnt=%d",
 				   rc, ref_count);
-			ref_count--;
+			hif_napi_bl_irq(napid, false);
 		}
 		break;
 	default: