Selaa lähdekoodia

qcacmn: Use disable_irq_nosync for ce srng msi mode

Implement interrupt mitigation for copy engines.
Implementation is not good if the CE msi vectors are shared,
since disable_irq_nosync will block all users of the given msi
vector.

When processing multiple CE interrupts while the tasklet is scheduled,
the the interrupts will increments the active_tasklet_cnt without
schduleing the tasklet (since it is allready scheduled).  This leads
to an imballance between the number of irq's processed and the number
of tasklets run.  This imballance leaks active_tasklet_cnt, and prevents
suspend from succeding.

interrupt mitigation fixes this problem by preventing the interrupt
from being processed untill its tasklet is finishing runing.

Change-Id: Idb3168d543481843b92327d302e7536e994e341e
CRs-Fixed: 1104481
Houston Hoffman 8 vuotta sitten
vanhempi
sitoutus
5caa32f957
2 muutettua tiedostoa jossa 26 lisäystä ja 18 poistoa
  1. 25 17
      hif/src/pcie/if_pci.c
  2. 1 1
      hif/src/pcie/if_pci.h

+ 25 - 17
hif/src/pcie/if_pci.c

@@ -3585,10 +3585,18 @@ extern const char *ce_name[];
  * added here for better system performance.
  * added here for better system performance.
  */
  */
 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
-{}
+{
+	struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(hif_sc);
+
+	disable_irq_nosync(pci_sc->ce_msi_irq_num[ce_id]);
+}
 
 
 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id)
 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id)
-{}
+{
+	struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(hif_sc);
+
+	enable_irq(pci_sc->ce_msi_irq_num[ce_id]);
+}
 
 
 static void hif_ce_legacy_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
 static void hif_ce_legacy_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
 {}
 {}
@@ -3604,14 +3612,26 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn)
 	uint32_t msi_data_count;
 	uint32_t msi_data_count;
 	uint32_t msi_irq_start;
 	uint32_t msi_irq_start;
 	struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
 	struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
+	struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(scn);
 
 
 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
 					    &msi_data_count, &msi_data_start,
 					    &msi_data_count, &msi_data_start,
 					    &msi_irq_start);
 					    &msi_irq_start);
-
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	if (ce_srng_based(scn)) {
+		scn->bus_ops.hif_irq_disable =
+			&hif_ce_srng_msi_irq_disable;
+		scn->bus_ops.hif_irq_enable =
+			&hif_ce_srng_msi_irq_enable;
+	} else {
+		scn->bus_ops.hif_irq_disable =
+			&hif_ce_legacy_msi_irq_disable;
+		scn->bus_ops.hif_irq_enable =
+			&hif_ce_legacy_msi_irq_enable;
+	}
+
 	/* needs to match the ce_id -> irq data mapping
 	/* needs to match the ce_id -> irq data mapping
 	 * used in the srng parameter configuration
 	 * used in the srng parameter configuration
 	 */
 	 */
@@ -3623,6 +3643,8 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn)
 		HIF_INFO("%s: (ce_id %d, msi_data %d, irq %d tasklet %p)",
 		HIF_INFO("%s: (ce_id %d, msi_data %d, irq %d tasklet %p)",
 			 __func__, ce_id, msi_data, irq,
 			 __func__, ce_id, msi_data, irq,
 			 &ce_sc->tasklets[ce_id]);
 			 &ce_sc->tasklets[ce_id]);
+
+		pci_sc->ce_msi_irq_num[ce_id] = irq;
 		ret = request_irq(irq, hif_ce_interrupt_handler,
 		ret = request_irq(irq, hif_ce_interrupt_handler,
 				  IRQF_SHARED,
 				  IRQF_SHARED,
 				  ce_name[ce_id],
 				  ce_name[ce_id],
@@ -3631,20 +3653,6 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn)
 			goto free_irq;
 			goto free_irq;
 	}
 	}
 
 
-	if (ce_srng_based(scn)) {
-		scn->bus_ops.hif_irq_disable =
-			&hif_ce_srng_msi_irq_disable;
-		scn->bus_ops.hif_irq_enable =
-			&hif_ce_srng_msi_irq_enable;
-	} else {
-		scn->bus_ops.hif_irq_disable =
-			&hif_ce_legacy_msi_irq_disable;
-		scn->bus_ops.hif_irq_enable =
-			&hif_ce_legacy_msi_irq_enable;
-	}
-
-
-
 	return ret;
 	return ret;
 
 
 free_irq:
 free_irq:

+ 1 - 1
hif/src/pcie/if_pci.h

@@ -116,8 +116,8 @@ struct hif_pci_softc {
 	int num_msi_intrs;      /* number of MSI interrupts granted */
 	int num_msi_intrs;      /* number of MSI interrupts granted */
 	/* 0 --> using legacy PCI line interrupts */
 	/* 0 --> using legacy PCI line interrupts */
 	struct tasklet_struct intr_tq;  /* tasklet */
 	struct tasklet_struct intr_tq;  /* tasklet */
-
 	struct hif_msi_info msi_info;
 	struct hif_msi_info msi_info;
+	int ce_msi_irq_num[CE_COUNT_MAX];
 	int irq;
 	int irq;
 	int irq_event;
 	int irq_event;
 	int cacheline_sz;
 	int cacheline_sz;