diff --git a/components/target_if/twt/src/target_if_ext_twt_evt.c b/components/target_if/twt/src/target_if_ext_twt_evt.c index 55c330633a..5cc5fdf1e5 100644 --- a/components/target_if/twt/src/target_if_ext_twt_evt.c +++ b/components/target_if/twt/src/target_if_ext_twt_evt.c @@ -158,7 +158,49 @@ static int target_if_twt_notify_event_handler(ol_scn_t scn, uint8_t *event, uint32_t len) { - return 0; + QDF_STATUS qdf_status; + struct wmi_unified *wmi_handle; + struct wlan_objmgr_psoc *psoc; + struct twt_notify_event_param *data; + struct wlan_lmac_if_twt_rx_ops *twt_rx_ops; + + TARGET_IF_ENTER(); + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + target_if_err("psoc is null"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("wmi_handle is null"); + return -EINVAL; + } + + twt_rx_ops = wlan_twt_get_rx_ops(psoc); + if (!twt_rx_ops || !twt_rx_ops->twt_notify_comp_cb) { + target_if_err("No valid twt notify rx ops"); + return -EINVAL; + } + + data = qdf_mem_malloc(sizeof(*data)); + if (!data) + return -ENOMEM; + + qdf_status = wmi_extract_twt_notify_event(wmi_handle, event, data); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + target_if_err("extract twt notify event failed (status=%d)", + qdf_status); + goto done; + } + + qdf_status = twt_rx_ops->twt_notify_comp_cb(psoc, data); + +done: + qdf_mem_free(data); + return qdf_status_to_os_return(qdf_status); + } static int diff --git a/components/umac/twt/core/src/wlan_twt_main.c b/components/umac/twt/core/src/wlan_twt_main.c index 4832497297..d8d50d3806 100644 --- a/components/umac/twt/core/src/wlan_twt_main.c +++ b/components/umac/twt/core/src/wlan_twt_main.c @@ -173,7 +173,30 @@ wlan_twt_init_context(struct wlan_objmgr_psoc *psoc, static bool wlan_is_twt_notify_in_progress(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id) { - return false; + struct wlan_objmgr_vdev *vdev; + struct twt_vdev_priv_obj *twt_vdev_priv; + bool is_twt_notify_in_progress; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_TWT_ID); + if (!vdev) { + twt_err("vdev object not found"); + return false; + } + + twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(vdev, + WLAN_UMAC_COMP_TWT); + if (!twt_vdev_priv) { + wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID); + twt_err("twt vdev private object is NULL"); + return false; + } + + is_twt_notify_in_progress = twt_vdev_priv->twt_wait_for_notify; + wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID); + + twt_debug("is_twt_notify_in_progress: %d", is_twt_notify_in_progress); + return is_twt_notify_in_progress; } /** @@ -188,6 +211,27 @@ static QDF_STATUS wlan_twt_set_wait_for_notify(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id, bool is_set) { + struct wlan_objmgr_vdev *vdev; + struct twt_vdev_priv_obj *twt_vdev_priv; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_TWT_ID); + if (!vdev) { + twt_err("vdev object not found"); + return QDF_STATUS_E_INVAL; + } + + twt_vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(vdev, + WLAN_UMAC_COMP_TWT); + if (!twt_vdev_priv) { + wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID); + twt_err("twt vdev private object is NULL"); + return QDF_STATUS_E_INVAL; + } + + twt_vdev_priv->twt_wait_for_notify = is_set; + twt_debug("twt_wait_for_notify: %d", is_set); + wlan_objmgr_vdev_release_ref(vdev, WLAN_TWT_ID); return QDF_STATUS_SUCCESS; } @@ -1336,5 +1380,8 @@ QDF_STATUS wlan_twt_notify_event_handler(struct wlan_objmgr_psoc *psoc, struct twt_notify_event_param *event) { + wlan_twt_set_wait_for_notify(psoc, event->vdev_id, false); + mlme_twt_osif_notify_complete_ind(psoc, event); + return QDF_STATUS_SUCCESS; } diff --git a/components/umac/twt/dispatcher/src/wlan_twt_tgt_if_ext_rx_api.c b/components/umac/twt/dispatcher/src/wlan_twt_tgt_if_ext_rx_api.c index c1079c01ab..54415c209a 100644 --- a/components/umac/twt/dispatcher/src/wlan_twt_tgt_if_ext_rx_api.c +++ b/components/umac/twt/dispatcher/src/wlan_twt_tgt_if_ext_rx_api.c @@ -65,7 +65,7 @@ static QDF_STATUS tgt_twt_notify_complete_resp_handler(struct wlan_objmgr_psoc *psoc, struct twt_notify_event_param *event) { - return QDF_STATUS_SUCCESS; + return wlan_twt_notify_event_handler(psoc, event); } static QDF_STATUS diff --git a/os_if/twt/src/osif_twt_ext_rsp.c b/os_if/twt/src/osif_twt_ext_rsp.c index f5ed2d323f..48e8b8a1d1 100644 --- a/os_if/twt/src/osif_twt_ext_rsp.c +++ b/os_if/twt/src/osif_twt_ext_rsp.c @@ -383,6 +383,18 @@ osif_twt_setup_pack_resp_nlmsg(struct sk_buff *reply_skb, * Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes * on failure */ +static QDF_STATUS +osif_twt_notify_pack_nlmsg(struct sk_buff *reply_skb) +{ + if (nla_put_u8(reply_skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION, + QCA_WLAN_TWT_SETUP_READY_NOTIFY)) { + osif_err("Failed to put TWT notify operation"); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS osif_twt_teardown_pack_resp_nlmsg(struct sk_buff *reply_skb, struct twt_del_dialog_complete_event_param *event) @@ -624,6 +636,54 @@ QDF_STATUS osif_twt_notify_complete_cb(struct wlan_objmgr_psoc *psoc, struct twt_notify_event_param *event) { + struct wireless_dev *wdev; + struct sk_buff *twt_vendor_event; + size_t data_len; + QDF_STATUS status; + struct vdev_osif_priv *osif_priv; + struct wlan_objmgr_vdev *vdev; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id, + WLAN_TWT_ID); + if (!vdev) { + osif_err("vdev is null"); + return QDF_STATUS_E_INVAL; + } + + osif_priv = wlan_vdev_get_ospriv(vdev); + if (!osif_priv) { + osif_err("osif_priv is null"); + return QDF_STATUS_E_INVAL; + } + + wdev = osif_priv->wdev; + if (!wdev) { + osif_err("wireless dev is null"); + return QDF_STATUS_E_INVAL; + } + + data_len = NLA_HDRLEN; + data_len += nla_total_size(sizeof(u8)); + + twt_vendor_event = wlan_cfg80211_vendor_event_alloc( + wdev->wiphy, wdev, data_len, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT_INDEX, + GFP_KERNEL); + if (!twt_vendor_event) { + osif_err("Notify skb alloc failed"); + return QDF_STATUS_E_INVAL; + } + + osif_debug("twt Notify vdev_id %d", event->vdev_id); + + status = osif_twt_notify_pack_nlmsg(twt_vendor_event); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to pack nl notify event"); + wlan_cfg80211_vendor_free_skb(twt_vendor_event); + return QDF_STATUS_E_INVAL; + } + + wlan_cfg80211_vendor_event(twt_vendor_event, GFP_KERNEL); return QDF_STATUS_SUCCESS; }