|
@@ -1936,6 +1936,161 @@ static QDF_STATUS sme_process_antenna_mode_resp(struct mac_context *mac,
|
|
|
}
|
|
|
|
|
|
#ifdef WLAN_SUPPORT_TWT
|
|
|
+/**
|
|
|
+ * sme_sap_twt_is_command_in_progress() - Based on the input peer mac address
|
|
|
+ * invoke the appropriate function to check if the given command is in progress
|
|
|
+ * @psoc: Pointer to psoc object
|
|
|
+ * @vdev_id: Vdev id
|
|
|
+ * @peer_mac: Peer MAC address
|
|
|
+ * @dialog_id: Dialog id
|
|
|
+ * @cmd: command
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a broadcast MAC address then the expectation is
|
|
|
+ * to iterate through the list of all peers and check for any given @dialog_id
|
|
|
+ * if the command @cmd is in progress.
|
|
|
+ * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
|
|
|
+ * be WLAN_ALL_SESSIONS_DIALOG_ID.
|
|
|
+ * For ex: If TWT teardown command is issued on a particular @dialog_id and
|
|
|
+ * non-broadcast peer mac and FW response is not yet received then for that
|
|
|
+ * particular @dialog_id and @peer_mac, TWT teardown is the active command,
|
|
|
+ * then if the driver receives another TWT teardown request with broadcast
|
|
|
+ * peer mac, then API mlme_twt_any_peer_cmd_in_progress() shall iterate
|
|
|
+ * through the list of all peers and returns command in progress as true.
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a non-broadcast MAC address then
|
|
|
+ * mlme_sap_twt_peer_is_cmd_in_progress() shall check only for that
|
|
|
+ * particular @peer_mac and @dialog_id.
|
|
|
+ *
|
|
|
+ * Return: true if command is in progress, false otherwise
|
|
|
+ */
|
|
|
+static bool
|
|
|
+sme_sap_twt_is_command_in_progress(struct wlan_objmgr_psoc *psoc,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ struct qdf_mac_addr *peer_mac,
|
|
|
+ uint8_t dialog_id,
|
|
|
+ enum wlan_twt_commands cmd)
|
|
|
+{
|
|
|
+ if (qdf_is_macaddr_broadcast(peer_mac)) {
|
|
|
+ return mlme_twt_any_peer_cmd_in_progress(psoc, vdev_id,
|
|
|
+ dialog_id, cmd);
|
|
|
+ } else {
|
|
|
+ return mlme_sap_twt_peer_is_cmd_in_progress(psoc, peer_mac,
|
|
|
+ dialog_id, cmd);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * sme_sap_add_twt_session() - Based on the input peer mac address
|
|
|
+ * invoke the appropriate function to add dialog_id to the TWT session context
|
|
|
+ * @psoc: Pointer to psoc object
|
|
|
+ * @vdev_id: Vdev id
|
|
|
+ * @peer_mac: Peer MAC address
|
|
|
+ * @dialog_id: Dialog id
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a broadcast MAC address then there is nothing
|
|
|
+ * to do, because the initialized structure is already in the expected format
|
|
|
+ * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
|
|
|
+ * be WLAN_ALL_SESSIONS_DIALOG_ID.
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a non-broadcast MAC address then
|
|
|
+ * mlme_add_twt_session() shall add the @dialog_id to the @peer_mac
|
|
|
+ * TWT session context.
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void
|
|
|
+sme_sap_add_twt_session(struct wlan_objmgr_psoc *psoc,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ struct qdf_mac_addr *peer_mac,
|
|
|
+ uint8_t dialog_id)
|
|
|
+{
|
|
|
+ if (!qdf_is_macaddr_broadcast(peer_mac))
|
|
|
+ mlme_add_twt_session(psoc, peer_mac, dialog_id);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * sme_sap_set_twt_command_in_progress() - Based on the input peer mac address
|
|
|
+ * invoke the appropriate function to set the command is in progress
|
|
|
+ * @psoc: Pointer to psoc object
|
|
|
+ * @vdev_id: Vdev id
|
|
|
+ * @peer_mac: Peer MAC address
|
|
|
+ * @dialog_id: Dialog id
|
|
|
+ * @cmd: command
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a broadcast MAC address then the expectation is
|
|
|
+ * to iterate through the list of all peers and set the active command to @cmd
|
|
|
+ * for the given @dialog_id
|
|
|
+ * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
|
|
|
+ * be WLAN_ALL_SESSIONS_DIALOG_ID.
|
|
|
+ * For ex: If TWT teardown command is issued on broadcast @peer_mac, then
|
|
|
+ * it is same as issuing TWT teardown for all the peers (all TWT sessions).
|
|
|
+ * Invoking mlme_sap_set_twt_all_peers_cmd_in_progress() shall iterate through
|
|
|
+ * all the peers and set the active command to @cmd.
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a non-broadcast MAC address then
|
|
|
+ * mlme_set_twt_command_in_progress() shall set the active command to @cmd
|
|
|
+ * only for that particular @peer_mac and @dialog_id.
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+sme_sap_set_twt_command_in_progress(struct wlan_objmgr_psoc *psoc,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ struct qdf_mac_addr *peer_mac,
|
|
|
+ uint8_t dialog_id,
|
|
|
+ enum wlan_twt_commands cmd)
|
|
|
+{
|
|
|
+ if (qdf_is_macaddr_broadcast(peer_mac)) {
|
|
|
+ return mlme_sap_set_twt_all_peers_cmd_in_progress(psoc,
|
|
|
+ vdev_id,
|
|
|
+ dialog_id,
|
|
|
+ cmd);
|
|
|
+ } else {
|
|
|
+ return mlme_set_twt_command_in_progress(psoc, peer_mac,
|
|
|
+ dialog_id, cmd);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * sme_sap_init_twt_context() - Based on the input peer mac address
|
|
|
+ * invoke the appropriate function to initialize the TWT session context
|
|
|
+ * @psoc: Pointer to psoc object
|
|
|
+ * @vdev_id: Vdev id
|
|
|
+ * @peer_mac: Peer MAC address
|
|
|
+ * @dialog_id: Dialog id
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a broadcast MAC address then the expectation is
|
|
|
+ * to iterate through the list of all peers and initialize the TWT session
|
|
|
+ * context
|
|
|
+ * Note: If @peer_mac is broadcast MAC address then @dialog_id shall always
|
|
|
+ * be WLAN_ALL_SESSIONS_DIALOG_ID.
|
|
|
+ * For ex: If TWT teardown command is issued on broadcast @peer_mac, then
|
|
|
+ * it is same as issuing TWT teardown for all the peers (all TWT sessions).
|
|
|
+ * Then active command for all the peers is set to @WLAN_TWT_TERMINATE.
|
|
|
+ * Upon receiving the TWT teardown WMI event, mlme_init_all_peers_twt_context()
|
|
|
+ * shall iterate through the list of all peers and initializes the TWT session
|
|
|
+ * context back to its initial state.
|
|
|
+ *
|
|
|
+ * If the input @peer_mac is a non-broadcast MAC address then
|
|
|
+ * mlme_init_twt_context() shall initialize the TWT session context
|
|
|
+ * only for that particular @peer_mac and @dialog_id.
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+sme_sap_init_twt_context(struct wlan_objmgr_psoc *psoc,
|
|
|
+ uint8_t vdev_id,
|
|
|
+ struct qdf_mac_addr *peer_mac,
|
|
|
+ uint8_t dialog_id)
|
|
|
+{
|
|
|
+ if (qdf_is_macaddr_broadcast(peer_mac)) {
|
|
|
+ return mlme_init_all_peers_twt_context(psoc, vdev_id,
|
|
|
+ dialog_id);
|
|
|
+ } else {
|
|
|
+ return mlme_init_twt_context(psoc, peer_mac, dialog_id);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* sme_process_twt_add_renego_failure() - Process TWT re-negotiation failure
|
|
|
*
|
|
@@ -2176,6 +2331,22 @@ sme_process_twt_del_dialog_event(
|
|
|
callback = mac->sme.twt_del_dialog_cb;
|
|
|
if (callback)
|
|
|
callback(mac->psoc, param);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If this is an unsolicited TWT del event initiated from the
|
|
|
+ * peer, then no need to clear the active command in progress
|
|
|
+ */
|
|
|
+ if (param->status !=
|
|
|
+ WMI_HOST_DEL_TWT_STATUS_PEER_INIT_TEARDOWN) {
|
|
|
+ /* Reset the active TWT command to none */
|
|
|
+ sme_sap_set_twt_command_in_progress(mac->psoc,
|
|
|
+ param->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)param->peer_macaddr,
|
|
|
+ param->dialog_id, WLAN_TWT_NONE);
|
|
|
+ sme_sap_init_twt_context(mac->psoc, param->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)
|
|
|
+ param->peer_macaddr, param->dialog_id);
|
|
|
+ }
|
|
|
break;
|
|
|
case QDF_STA_MODE:
|
|
|
sme_process_sta_twt_del_dialog_event(mac, param);
|
|
@@ -14105,7 +14276,7 @@ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle,
|
|
|
|
|
|
status = sme_acquire_global_lock(&mac->sme);
|
|
|
if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
- sme_err("failed to register del dialog callback");
|
|
|
+ sme_err("Failed to acquire SME global lock");
|
|
|
qdf_mem_free(cmd_params);
|
|
|
return status;
|
|
|
}
|
|
@@ -14138,6 +14309,88 @@ QDF_STATUS sme_del_dialog_cmd(mac_handle_t mac_handle,
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+QDF_STATUS sme_sap_del_dialog_cmd(mac_handle_t mac_handle,
|
|
|
+ twt_del_dialog_cb del_dialog_cb,
|
|
|
+ struct wmi_twt_del_dialog_param *twt_params)
|
|
|
+{
|
|
|
+ struct mac_context *mac = MAC_CONTEXT(mac_handle);
|
|
|
+ struct scheduler_msg twt_msg = {0};
|
|
|
+ bool is_twt_cmd_in_progress;
|
|
|
+ QDF_STATUS status;
|
|
|
+ void *wma_handle;
|
|
|
+ struct wmi_twt_del_dialog_param *cmd_params;
|
|
|
+
|
|
|
+ SME_ENTER();
|
|
|
+
|
|
|
+ is_twt_cmd_in_progress =
|
|
|
+ sme_sap_twt_is_command_in_progress(mac->psoc,
|
|
|
+ twt_params->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)twt_params->peer_macaddr,
|
|
|
+ twt_params->dialog_id, WLAN_TWT_TERMINATE);
|
|
|
+
|
|
|
+ if (is_twt_cmd_in_progress) {
|
|
|
+ sme_debug("Already TWT teardown command is in progress");
|
|
|
+ return QDF_STATUS_E_PENDING;
|
|
|
+ }
|
|
|
+
|
|
|
+ wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
|
|
|
+ if (!wma_handle)
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+
|
|
|
+ /* bodyptr should be freeable */
|
|
|
+ cmd_params = qdf_mem_malloc(sizeof(*cmd_params));
|
|
|
+ if (!cmd_params)
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+
|
|
|
+ qdf_mem_copy(cmd_params, twt_params, sizeof(*cmd_params));
|
|
|
+
|
|
|
+ status = sme_acquire_global_lock(&mac->sme);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ qdf_mem_free(cmd_params);
|
|
|
+ sme_err("Failed to acquire SME global lock");
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Add the dialog id to TWT context to drop back to back
|
|
|
+ * commands
|
|
|
+ */
|
|
|
+ sme_sap_add_twt_session(mac->psoc, twt_params->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)twt_params->peer_macaddr,
|
|
|
+ twt_params->dialog_id);
|
|
|
+
|
|
|
+ sme_sap_set_twt_command_in_progress(mac->psoc, twt_params->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)twt_params->peer_macaddr,
|
|
|
+ twt_params->dialog_id, WLAN_TWT_TERMINATE);
|
|
|
+
|
|
|
+ /* Serialize the req through MC thread */
|
|
|
+ mac->sme.twt_del_dialog_cb = del_dialog_cb;
|
|
|
+ twt_msg.bodyptr = cmd_params;
|
|
|
+ twt_msg.type = WMA_TWT_DEL_DIALOG_REQUEST;
|
|
|
+ sme_release_global_lock(&mac->sme);
|
|
|
+
|
|
|
+ status = scheduler_post_message(QDF_MODULE_ID_SME,
|
|
|
+ QDF_MODULE_ID_WMA,
|
|
|
+ QDF_MODULE_ID_WMA, &twt_msg);
|
|
|
+
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
|
|
|
+ FL("Post twt del dialog msg fail"));
|
|
|
+ sme_sap_set_twt_command_in_progress(mac->psoc,
|
|
|
+ twt_params->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)twt_params->peer_macaddr,
|
|
|
+ twt_params->dialog_id, WLAN_TWT_NONE);
|
|
|
+ sme_sap_init_twt_context(mac->psoc,
|
|
|
+ twt_params->vdev_id,
|
|
|
+ (struct qdf_mac_addr *)twt_params->peer_macaddr,
|
|
|
+ twt_params->dialog_id);
|
|
|
+ qdf_mem_free(cmd_params);
|
|
|
+ }
|
|
|
+
|
|
|
+ SME_EXIT();
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
QDF_STATUS
|
|
|
sme_pause_dialog_cmd(mac_handle_t mac_handle,
|
|
|
struct wmi_twt_pause_dialog_cmd_param *twt_params)
|