فهرست منبع

qcacmn: Add APIs to schedule/cancel custom callbacks

Add HIF/CE layer APIs to schedule/cancel custom callbacks.

Change-Id: I9cc7dcf73a726cb1ed2d7945d6ce9e736d42af52
CRs-Fixed: 3408690
Edayilliam Jayadev 2 سال پیش
والد
کامیت
63c5956a01
6فایلهای تغییر یافته به همراه250 افزوده شده و 0 حذف شده
  1. 45 0
      hif/inc/hif.h
  2. 43 0
      hif/src/ce/ce_api.h
  3. 5 0
      hif/src/ce/ce_internal.h
  4. 68 0
      hif/src/ce/ce_main.c
  5. 47 0
      hif/src/ce/ce_service.c
  6. 42 0
      hif/src/ce/ce_tasklet.c

+ 45 - 0
hif/inc/hif.h

@@ -1075,6 +1075,51 @@ struct hif_pipe_addl_info {
 
 struct hif_bus_id;
 
+#ifdef CUSTOM_CB_SCHEDULER_SUPPORT
+/**
+ * hif_register_ce_custom_cb() - Helper API to register the custom callback
+ * @hif_ctx: HIF opaque context
+ * @pipe: Pipe number
+ * @custom_cb: Custom call back function pointer
+ * @custom_cb_context: Custom callback context
+ *
+ * return: QDF_STATUS
+ */
+QDF_STATUS
+hif_register_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe,
+			  void (*custom_cb)(void *), void *custom_cb_context);
+
+/**
+ * hif_unregister_ce_custom_cb() - Helper API to unregister the custom callback
+ * @hif_ctx: HIF opaque context
+ * @pipe: Pipe number
+ *
+ * return: QDF_STATUS
+ */
+QDF_STATUS
+hif_unregister_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe);
+
+/**
+ * hif_enable_ce_custom_cb() - Helper API to enable the custom callback
+ * @hif_ctx: HIF opaque context
+ * @pipe: Pipe number
+ *
+ * return: QDF_STATUS
+ */
+QDF_STATUS
+hif_enable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe);
+
+/**
+ * hif_disable_ce_custom_cb() - Helper API to disable the custom callback
+ * @hif_ctx: HIF opaque context
+ * @pipe: Pipe number
+ *
+ * return: QDF_STATUS
+ */
+QDF_STATUS
+hif_disable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe);
+#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */
+
 void hif_claim_device(struct hif_opaque_softc *hif_ctx);
 QDF_STATUS hif_get_config_item(struct hif_opaque_softc *hif_ctx,
 		     int opcode, void *config, uint32_t config_len);

+ 43 - 0
hif/src/ce/ce_api.h

@@ -375,6 +375,49 @@ QDF_STATUS ce_completed_send_next(struct CE_handle *copyeng,
 				  unsigned int *hw_idx,
 				  uint32_t *toeplitz_hash_result);
 
+#ifdef CUSTOM_CB_SCHEDULER_SUPPORT
+/*==================CE custom callbacks=================================*/
+
+/**
+ * ce_register_custom_cb() - Helper API to register the custom callback
+ * @copyeng: Pointer to CE handle
+ * @custom_cb: Custom call back function pointer
+ * @custom_cb_context: Custom callback context
+ *
+ * return: void
+ */
+void
+ce_register_custom_cb(struct CE_handle *copyeng, void (*custom_cb)(void *),
+		      void *custom_cb_context);
+
+/**
+ * ce_unregister_custom_cb() - Helper API to unregister the custom callback
+ * @copyeng: Pointer to CE handle
+ *
+ * return: void
+ */
+void
+ce_unregister_custom_cb(struct CE_handle *copyeng);
+
+/**
+ * ce_enable_custom_cb() - Helper API to enable the custom callback
+ * @copyeng: Pointer to CE handle
+ *
+ * return: void
+ */
+void
+ce_enable_custom_cb(struct CE_handle *copyeng);
+
+/**
+ * ce_disable_custom_cb() - Helper API to disable the custom callback
+ * @copyeng: Pointer to CE handle
+ *
+ * return: void
+ */
+void
+ce_disable_custom_cb(struct CE_handle *copyeng);
+#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */
+
 /*==================CE Engine Initialization=================================*/
 
 /* Initialize an instance of a CE */

+ 5 - 0
hif/src/ce/ce_internal.h

@@ -151,6 +151,11 @@ struct CE_state {
 	CE_watermark_cb watermark_cb;
 	void *wm_context;
 
+#ifdef CUSTOM_CB_SCHEDULER_SUPPORT
+	qdf_atomic_t custom_cb_pending;
+	void (*custom_cb)(void *arg);
+	void *custom_cb_context;
+#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */
 	/*Record the state of the copy compl interrupt */
 	int disable_copy_compl_intr;
 

+ 68 - 0
hif/src/ce/ce_main.c

@@ -3012,6 +3012,74 @@ void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe,
 #endif
 }
 
+#ifdef CUSTOM_CB_SCHEDULER_SUPPORT
+QDF_STATUS
+hif_register_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe,
+			  void (*custom_cb)(void *), void *custom_cb_context)
+{
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct HIF_CE_pipe_info *pipe_info;
+
+	if (pipe >= CE_COUNT_MAX)
+		return QDF_STATUS_E_INVAL;
+
+	pipe_info = &hif_state->pipe_info[pipe];
+	ce_register_custom_cb(pipe_info->ce_hdl, custom_cb, custom_cb_context);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+hif_unregister_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe)
+{
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct HIF_CE_pipe_info *pipe_info;
+
+	if (pipe >= CE_COUNT_MAX)
+		return QDF_STATUS_E_INVAL;
+
+	pipe_info = &hif_state->pipe_info[pipe];
+	ce_unregister_custom_cb(pipe_info->ce_hdl);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+hif_enable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe)
+{
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct HIF_CE_pipe_info *pipe_info;
+
+	if (pipe >= CE_COUNT_MAX)
+		return QDF_STATUS_E_INVAL;
+
+	pipe_info = &hif_state->pipe_info[pipe];
+	ce_enable_custom_cb(pipe_info->ce_hdl);
+	ce_dispatch_interrupt(pipe, &hif_state->tasklets[pipe]);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+hif_disable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe)
+{
+	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct HIF_CE_pipe_info *pipe_info;
+
+	if (pipe >= CE_COUNT_MAX)
+		return QDF_STATUS_E_INVAL;
+
+	pipe_info = &hif_state->pipe_info[pipe];
+	ce_disable_custom_cb(pipe_info->ce_hdl);
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */
+
 #if defined(CE_TASKLET_SCHEDULE_ON_FULL) && defined(CE_TASKLET_DEBUG_ENABLE)
 #define CE_RING_FULL_THRESHOLD_TIME 3000000
 #define CE_RING_FULL_THRESHOLD 1024

+ 47 - 0
hif/src/ce/ce_service.c

@@ -1481,6 +1481,53 @@ ce_watermark_cb_register(struct CE_handle *copyeng,
 		CE_state->misc_cbs = 1;
 }
 
+#ifdef CUSTOM_CB_SCHEDULER_SUPPORT
+void
+ce_register_custom_cb(struct CE_handle *copyeng, void (*custom_cb)(void *),
+		      void *custom_cb_context)
+{
+	struct CE_state *CE_state = (struct CE_state *)copyeng;
+
+	CE_state->custom_cb = custom_cb;
+	CE_state->custom_cb_context = custom_cb_context;
+	qdf_atomic_init(&CE_state->custom_cb_pending);
+}
+
+void
+ce_unregister_custom_cb(struct CE_handle *copyeng)
+{
+	struct CE_state *CE_state = (struct CE_state *)copyeng;
+
+	qdf_assert_always(!qdf_atomic_read(&CE_state->custom_cb_pending));
+	CE_state->custom_cb = NULL;
+	CE_state->custom_cb_context = NULL;
+}
+
+void
+ce_enable_custom_cb(struct CE_handle *copyeng)
+{
+	struct CE_state *CE_state = (struct CE_state *)copyeng;
+	int32_t custom_cb_pending;
+
+	qdf_assert_always(CE_state->custom_cb);
+	qdf_assert_always(CE_state->custom_cb_context);
+
+	custom_cb_pending = qdf_atomic_inc_return(&CE_state->custom_cb_pending);
+	qdf_assert_always(custom_cb_pending >= 1);
+}
+
+void
+ce_disable_custom_cb(struct CE_handle *copyeng)
+{
+	struct CE_state *CE_state = (struct CE_state *)copyeng;
+
+	qdf_assert_always(CE_state->custom_cb);
+	qdf_assert_always(CE_state->custom_cb_context);
+
+	qdf_atomic_dec_if_positive(&CE_state->custom_cb_pending);
+}
+#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */
+
 bool ce_get_rx_pending(struct hif_softc *scn)
 {
 	int CE_id;

+ 42 - 0
hif/src/ce/ce_tasklet.c

@@ -400,6 +400,46 @@ void hif_latency_detect_tasklet_exec(
 {}
 #endif
 
+#ifdef CUSTOM_CB_SCHEDULER_SUPPORT
+/**
+ * ce_get_custom_cb_pending() - Helper API to check whether the custom
+ * callback is pending
+ * @CE_state: Pointer to CE state
+ *
+ * return: bool
+ */
+static bool
+ce_get_custom_cb_pending(struct CE_state *CE_state)
+{
+	return (qdf_atomic_dec_if_positive(&CE_state->custom_cb_pending) >= 0);
+}
+
+/**
+ * ce_execute_custom_cb() - Helper API to execute custom callback
+ * @CE_state: Pointer to CE state
+ *
+ * return: void
+ */
+static void
+ce_execute_custom_cb(struct CE_state *CE_state)
+{
+	while (ce_get_custom_cb_pending(CE_state) && CE_state->custom_cb &&
+	       CE_state->custom_cb_context)
+		CE_state->custom_cb(CE_state->custom_cb_context);
+}
+#else
+/**
+ * ce_execute_custom_cb() - Helper API to execute custom callback
+ * @CE_state: Pointer to CE state
+ *
+ * return: void
+ */
+static void
+ce_execute_custom_cb(struct CE_state *CE_state)
+{
+}
+#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */
+
 /**
  * ce_tasklet() - ce_tasklet
  * @data: data
@@ -428,6 +468,8 @@ static void ce_tasklet(unsigned long data)
 		QDF_BUG(0);
 	}
 
+	ce_execute_custom_cb(CE_state);
+
 	ce_per_engine_service(scn, tasklet_entry->ce_id);
 
 	if (ce_check_rx_pending(CE_state) && tasklet_entry->inited) {