|
@@ -246,6 +246,85 @@ static void p2p_roc_timeout(void *pdata)
|
|
|
p2p_execute_cancel_roc_req(roc_ctx);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * p2p_send_roc_event() - Send roc event
|
|
|
+ * @roc_ctx: remain on channel request
|
|
|
+ * @evt: roc event information
|
|
|
+ *
|
|
|
+ * This function send out roc event to up layer.
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS_SUCCESS - in case of success
|
|
|
+ */
|
|
|
+static QDF_STATUS p2p_send_roc_event(
|
|
|
+ struct p2p_roc_context *roc_ctx, enum p2p_roc_event evt)
|
|
|
+{
|
|
|
+ struct p2p_soc_priv_obj *p2p_soc_obj;
|
|
|
+ struct p2p_event p2p_evt;
|
|
|
+ struct p2p_start_param *start_param;
|
|
|
+
|
|
|
+ p2p_soc_obj = roc_ctx->p2p_soc_obj;
|
|
|
+ if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
|
|
|
+ p2p_err("Invalid p2p soc object or start parameters");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+ start_param = p2p_soc_obj->start_param;
|
|
|
+ if (!(start_param->event_cb)) {
|
|
|
+ p2p_err("Invalid p2p event callback to up layer");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ p2p_evt.vdev_id = roc_ctx->vdev_id;
|
|
|
+ p2p_evt.roc_event = evt;
|
|
|
+ p2p_evt.cookie = (uintptr_t)roc_ctx;
|
|
|
+ p2p_evt.chan = roc_ctx->chan;
|
|
|
+ p2p_evt.duration = roc_ctx->duration;
|
|
|
+
|
|
|
+ p2p_debug("p2p soc_obj:%p, roc_ctx:%p, vdev_id:%d, roc_event:"
|
|
|
+ "%d, cookie:%llx, chan:%d, duration:%d", p2p_soc_obj,
|
|
|
+ roc_ctx, p2p_evt.vdev_id, p2p_evt.roc_event,
|
|
|
+ p2p_evt.cookie, p2p_evt.chan, p2p_evt.duration);
|
|
|
+
|
|
|
+ start_param->event_cb(start_param->event_cb_data, &p2p_evt);
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * p2p_destroy_roc_ctx() - destroy roc ctx
|
|
|
+ * @roc_ctx: remain on channel request
|
|
|
+ * @up_layer_event: if send uplayer event
|
|
|
+ * @in_roc_queue: if roc context in roc queue
|
|
|
+ *
|
|
|
+ * This function destroy roc context.
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS_SUCCESS - in case of success
|
|
|
+ */
|
|
|
+static QDF_STATUS p2p_destroy_roc_ctx(struct p2p_roc_context *roc_ctx,
|
|
|
+ bool up_layer_event, bool in_roc_queue)
|
|
|
+{
|
|
|
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
+ struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
|
|
|
+
|
|
|
+ p2p_debug("p2p_soc_obj:%p, roc_ctx:%p, up_layer_event:%d, in_roc_queue:%d",
|
|
|
+ p2p_soc_obj, roc_ctx, up_layer_event, in_roc_queue);
|
|
|
+
|
|
|
+ if (up_layer_event) {
|
|
|
+ p2p_send_roc_event(roc_ctx, ROC_EVENT_READY_ON_CHAN);
|
|
|
+ p2p_send_roc_event(roc_ctx, ROC_EVENT_COMPLETED);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (in_roc_queue) {
|
|
|
+ status = qdf_list_remove_node(&p2p_soc_obj->roc_q,
|
|
|
+ (qdf_list_node_t *)roc_ctx);
|
|
|
+ if (QDF_STATUS_SUCCESS != status)
|
|
|
+ p2p_err("Failed to remove roc req, status %d", status);
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_mem_free(roc_ctx);
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* p2p_execute_roc_req() - Execute roc request
|
|
|
* @roc_ctx: remain on channel request
|
|
@@ -267,11 +346,16 @@ static QDF_STATUS p2p_execute_roc_req(struct p2p_roc_context *roc_ctx)
|
|
|
roc_ctx->phy_mode, roc_ctx->duration,
|
|
|
roc_ctx->roc_type, roc_ctx->roc_state);
|
|
|
|
|
|
+ /* prevent runtime suspend */
|
|
|
+ qdf_runtime_pm_prevent_suspend(p2p_soc_obj->roc_runtime_lock);
|
|
|
+
|
|
|
status = qdf_mc_timer_init(&roc_ctx->roc_timer,
|
|
|
QDF_TIMER_TYPE_SW, p2p_roc_timeout,
|
|
|
p2p_soc_obj);
|
|
|
- if (status != QDF_STATUS_SUCCESS)
|
|
|
- return status;
|
|
|
+ if (status != QDF_STATUS_SUCCESS) {
|
|
|
+ p2p_err("failed to init roc timer, status:%d", status);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
|
|
|
roc_ctx->roc_state = ROC_STATE_REQUESTED;
|
|
|
go_num = policy_mgr_mode_specific_connection_count(
|
|
@@ -284,8 +368,19 @@ static QDF_STATUS p2p_execute_roc_req(struct p2p_roc_context *roc_ctx)
|
|
|
|
|
|
status = p2p_scan_start(roc_ctx);
|
|
|
if (status != QDF_STATUS_SUCCESS) {
|
|
|
+ qdf_mc_timer_destroy(&roc_ctx->roc_timer);
|
|
|
p2p_err("Failed to start scan, status:%d", status);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+fail:
|
|
|
+ if (status != QDF_STATUS_SUCCESS) {
|
|
|
+ p2p_destroy_roc_ctx(roc_ctx, true, true);
|
|
|
+ qdf_runtime_pm_allow_suspend(
|
|
|
+ p2p_soc_obj->roc_runtime_lock);
|
|
|
+ return status;
|
|
|
}
|
|
|
+
|
|
|
status = p2p_mgmt_rx_ops(roc_ctx->p2p_soc_obj->soc, true);
|
|
|
if (status != QDF_STATUS_SUCCESS)
|
|
|
p2p_err("Failed to register mgmt rx callback, status:%d",
|
|
@@ -323,49 +418,6 @@ static struct p2p_roc_context *p2p_find_roc_ctx(
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * p2p_send_roc_event() - Send roc event
|
|
|
- * @roc_ctx: remain on channel request
|
|
|
- * @evt: roc event information
|
|
|
- *
|
|
|
- * This function send out roc event to up layer.
|
|
|
- *
|
|
|
- * Return: QDF_STATUS_SUCCESS - in case of success
|
|
|
- */
|
|
|
-static QDF_STATUS p2p_send_roc_event(
|
|
|
- struct p2p_roc_context *roc_ctx, enum p2p_roc_event evt)
|
|
|
-{
|
|
|
- struct p2p_soc_priv_obj *p2p_soc_obj;
|
|
|
- struct p2p_event p2p_evt;
|
|
|
- struct p2p_start_param *start_param;
|
|
|
-
|
|
|
- p2p_soc_obj = roc_ctx->p2p_soc_obj;
|
|
|
- if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
|
|
|
- p2p_err("Invalid p2p soc object or start parameters");
|
|
|
- return QDF_STATUS_E_INVAL;
|
|
|
- }
|
|
|
- start_param = p2p_soc_obj->start_param;
|
|
|
- if (!(start_param->event_cb)) {
|
|
|
- p2p_err("Invalid p2p event callback to up layer");
|
|
|
- return QDF_STATUS_E_INVAL;
|
|
|
- }
|
|
|
-
|
|
|
- p2p_evt.vdev_id = roc_ctx->vdev_id;
|
|
|
- p2p_evt.roc_event = evt;
|
|
|
- p2p_evt.cookie = (uintptr_t)roc_ctx;
|
|
|
- p2p_evt.chan = roc_ctx->chan;
|
|
|
- p2p_evt.duration = roc_ctx->duration;
|
|
|
-
|
|
|
- p2p_debug("p2p soc_obj:%p, roc_ctx:%p, vdev_id:%d, roc_event:"
|
|
|
- "%d, cookie:%llx, chan:%d, duration:%d", p2p_soc_obj,
|
|
|
- roc_ctx, p2p_evt.vdev_id, p2p_evt.roc_event,
|
|
|
- p2p_evt.cookie, p2p_evt.chan, p2p_evt.duration);
|
|
|
-
|
|
|
- start_param->event_cb(start_param->event_cb_data, &p2p_evt);
|
|
|
-
|
|
|
- return QDF_STATUS_SUCCESS;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* p2p_process_scan_start_evt() - Process scan start event
|
|
|
* @roc_ctx: remain on channel request
|
|
@@ -450,6 +502,9 @@ static QDF_STATUS p2p_process_scan_complete_evt(
|
|
|
roc_ctx->phy_mode, roc_ctx->duration,
|
|
|
roc_ctx->roc_type, roc_ctx->roc_state);
|
|
|
|
|
|
+ /* allow runtime suspend */
|
|
|
+ qdf_runtime_pm_allow_suspend(p2p_soc_obj->roc_runtime_lock);
|
|
|
+
|
|
|
if (QDF_TIMER_STATE_RUNNING ==
|
|
|
qdf_mc_timer_get_current_state(&roc_ctx->roc_timer)) {
|
|
|
status = qdf_mc_timer_stop(&roc_ctx->roc_timer);
|
|
@@ -469,11 +524,7 @@ static QDF_STATUS p2p_process_scan_complete_evt(
|
|
|
status = p2p_send_roc_event(roc_ctx,
|
|
|
ROC_EVENT_COMPLETED);
|
|
|
|
|
|
- status = qdf_list_remove_node(&p2p_soc_obj->roc_q,
|
|
|
- (qdf_list_node_t *)roc_ctx);
|
|
|
- if (QDF_STATUS_SUCCESS != status)
|
|
|
- p2p_err("Failed to remove roc req, status %d", status);
|
|
|
- qdf_mem_free(roc_ctx);
|
|
|
+ p2p_destroy_roc_ctx(roc_ctx, false, true);
|
|
|
qdf_event_set(&p2p_soc_obj->cancel_roc_done);
|
|
|
|
|
|
size = qdf_list_size(&p2p_soc_obj->roc_q);
|
|
@@ -566,7 +617,8 @@ QDF_STATUS p2p_cleanup_roc_queue(struct p2p_soc_priv_obj *p2p_soc_obj)
|
|
|
&p2p_soc_obj->roc_q,
|
|
|
(qdf_list_node_t *)roc_ctx);
|
|
|
if (status == QDF_STATUS_SUCCESS)
|
|
|
- qdf_mem_free(roc_ctx);
|
|
|
+ p2p_destroy_roc_ctx(roc_ctx,
|
|
|
+ true, false);
|
|
|
else
|
|
|
p2p_err("Failed to remove roc ctx from queue");
|
|
|
}
|
|
@@ -617,7 +669,7 @@ QDF_STATUS p2p_process_roc_req(struct p2p_roc_context *roc_ctx)
|
|
|
status = qdf_list_insert_back(&p2p_soc_obj->roc_q,
|
|
|
&roc_ctx->node);
|
|
|
if (QDF_STATUS_SUCCESS != status) {
|
|
|
- qdf_mem_free(roc_ctx);
|
|
|
+ p2p_destroy_roc_ctx(roc_ctx, true, false);
|
|
|
p2p_debug("Failed to insert roc req, status %d", status);
|
|
|
return status;
|
|
|
}
|