diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 877f9aa0f4..1cb5785a70 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -32,6 +33,7 @@ #include #include "../../core/src/wlan_cp_stats_defs.h" #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h" +#include "son_api.h" static bool tgt_mc_cp_stats_is_last_event(struct stats_event *ev, enum stats_req_type stats_type) @@ -165,6 +167,10 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc, wlan_cp_stats_pdev_obj_lock(pdev_cp_stats_priv); pdev_mc_stats = pdev_cp_stats_priv->pdev_stats; + if (!is_station_stats && + pdev_mc_stats->max_pwr != ev->pdev_stats[pdev_id].max_pwr) + wlan_son_deliver_tx_power(vdev, + ev->pdev_stats[pdev_id].max_pwr); max_pwr = pdev_mc_stats->max_pwr = ev->pdev_stats[pdev_id].max_pwr; wlan_cp_stats_pdev_obj_unlock(pdev_cp_stats_priv); if (is_station_stats) diff --git a/components/son/dispatcher/inc/son_api.h b/components/son/dispatcher/inc/son_api.h index 4c37cca302..f67cd53fcb 100644 --- a/components/son/dispatcher/inc/son_api.h +++ b/components/son/dispatcher/inc/son_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -77,6 +78,36 @@ void wlan_son_ind_assoc_req_frm(struct wlan_objmgr_vdev *vdev, uint8_t *macaddr, bool is_reassoc, uint8_t *frame, uint16_t frame_len, QDF_STATUS status); +/** + * wlan_son_deliver_tx_power() - notify son module of tx power + * @vdev: vdev + * @max_pwr: max power in dBm unit + * + * Return: 0 if event is sent successfully + */ +int wlan_son_deliver_tx_power(struct wlan_objmgr_vdev *vdev, + int32_t max_pwr); + +/** + * wlan_son_deliver_vdev_stop() - notify son module of vdev stop + * @vdev: vdev + * + * Return: 0 if event is sent successfully + */ +int wlan_son_deliver_vdev_stop(struct wlan_objmgr_vdev *vdev); + +/** + * wlan_son_deliver_inst_rssi() - notify son module of inst rssi + * @vdev: vdev + * @peer: peer device + * @irssi: inst rssi above the noise floor in dB unit + * + * Return: 0 if event is sent successfully + */ +int wlan_son_deliver_inst_rssi(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + uint32_t irssi); + #else static inline bool wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev *vdev, @@ -92,5 +123,26 @@ void wlan_son_ind_assoc_req_frm(struct wlan_objmgr_vdev *vdev, QDF_STATUS status) { } + +static inline +int wlan_son_deliver_tx_power(struct wlan_objmgr_vdev *vdev, + int32_t max_pwr) +{ + return -EINVAL; +} + +static inline +int wlan_son_deliver_vdev_stop(struct wlan_objmgr_vdev *vdev) +{ + return -EINVAL; +} + +static inline +int wlan_son_deliver_inst_rssi(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + uint32_t irssi) +{ + return -EINVAL; +} #endif /*WLAN_FEATURE_SON*/ #endif diff --git a/components/son/dispatcher/src/son_api.c b/components/son/dispatcher/src/son_api.c index 31909260d5..0ccd9119a7 100644 --- a/components/son/dispatcher/src/son_api.c +++ b/components/son/dispatcher/src/son_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -312,3 +313,87 @@ void wlan_son_ind_assoc_req_frm(struct wlan_objmgr_vdev *vdev, &assocstatus); wlan_objmgr_peer_release_ref(peer, WLAN_SON_ID); } + +static int wlan_son_deliver_mlme_event(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + uint32_t event, + void *event_data) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_rx_ops *rx_ops; + int ret; + + if (!vdev) + return -EINVAL; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) + return -EINVAL; + + rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); + if (rx_ops && rx_ops->son_rx_ops.deliver_event) { + qdf_debug("deliver mlme event %d", event); + ret = rx_ops->son_rx_ops.deliver_event(vdev, + peer, + event, + event_data); + } else { + return -EINVAL; + } + + return ret; +} + +int wlan_son_deliver_tx_power(struct wlan_objmgr_vdev *vdev, + int32_t max_pwr) +{ + int ret; + + qdf_debug("tx power %d", max_pwr); + ret = wlan_son_deliver_mlme_event(vdev, + NULL, + MLME_EVENT_TX_PWR_CHANGE, + &max_pwr); + + return ret; +} + +int wlan_son_deliver_vdev_stop(struct wlan_objmgr_vdev *vdev) +{ + int ret; + + struct wlan_vdev_state_event event; + + event.state = VDEV_STATE_STOPPED; + qdf_debug("state %d", event.state); + ret = wlan_son_deliver_mlme_event(vdev, + NULL, + MLME_EVENT_VDEV_STATE, + &event); + + return ret; +} + +int wlan_son_deliver_inst_rssi(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + uint32_t irssi) +{ + struct wlan_peer_inst_rssi event; + int ret; + + if (irssi > 0 && irssi <= 127) { + event.iRSSI = irssi; + event.valid = true; + qdf_debug("irssi %d", event.iRSSI); + } else { + event.valid = false; + qdf_debug("irssi invalid"); + } + + ret = wlan_son_deliver_mlme_event(vdev, + peer, + MLME_EVENT_INST_RSSI, + &event); + + return ret; +} diff --git a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c index 7c0b3381a0..1eb92edc84 100644 --- a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -40,6 +41,9 @@ #include #include #include +#ifdef WLAN_FEATURE_SON +#include "son_api.h" +#endif #ifdef WLAN_SUPPORT_TWT @@ -1251,6 +1255,85 @@ target_if_big_data_stats_unregister_tx_ops(struct wlan_lmac_if_cp_stats_tx_ops {} #endif +#ifdef WLAN_FEATURE_SON +static int +target_if_mc_cp_stats_inst_rssi_stats_event_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wmi_host_inst_rssi_stats_resp ev = {0}; + + if (!scn || !data) { + cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + cp_stats_err("null psoc"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + cp_stats_err("wmi_handle is null"); + return -EINVAL; + } + + status = wmi_extract_inst_rssi_stats_resp(wmi_handle, data, &ev); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("extract event failed"); + return qdf_status_to_os_return(status); + } + + peer = wlan_objmgr_get_peer_by_mac(psoc, ev.peer_macaddr.bytes, + WLAN_CP_STATS_ID); + if (!peer) { + cp_stats_err("null peer"); + return -EINVAL; + } + + wlan_son_deliver_inst_rssi(wlan_peer_get_vdev(peer), + peer, + ev.inst_rssi); + + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + + return 0; +} + +static QDF_STATUS +target_if_register_inst_rssi_event_handler(struct wmi_unified *wmi_handle) +{ + return wmi_unified_register_event_handler(wmi_handle, + wmi_inst_rssi_stats_event_id, + target_if_mc_cp_stats_inst_rssi_stats_event_handler, + WMI_RX_SERIALIZER_CTX); +} + +static void +target_if_unregister_inst_rssi_event_handler(struct wmi_unified *wmi_handle) +{ + wmi_unified_unregister_event_handler(wmi_handle, + wmi_inst_rssi_stats_event_id); +} +#else +static QDF_STATUS +target_if_register_inst_rssi_event_handler(struct wmi_unified *wmi_handle) +{ + return QDF_STATUS_SUCCESS; +} + +static void +target_if_unregister_inst_rssi_event_handler(struct wmi_unified *wmi_handle) +{ +} +#endif + static QDF_STATUS target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc) { @@ -1287,6 +1370,10 @@ target_if_mc_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc) if (QDF_IS_STATUS_ERROR(ret_val)) cp_stats_err("Failed to register big data stats info event cb"); + ret_val = target_if_register_inst_rssi_event_handler(wmi_handle); + if (QDF_IS_STATUS_ERROR(ret_val)) + cp_stats_err("Failed to register inst rssi stats event cb"); + return ret_val; } @@ -1306,6 +1393,7 @@ target_if_mc_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_E_INVAL; } + target_if_unregister_inst_rssi_event_handler(wmi_handle); target_if_unregister_big_data_event_handler(wmi_handle); wmi_unified_unregister_event_handler(wmi_handle, diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 838267a473..7cf4fcb28d 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -102,6 +103,8 @@ #include "wlan_ipa_ucfg_api.h" #endif +#include "son_api.h" + /* * FW only supports 8 clients in SAP/GO mode for D3 WoW feature * and hence host needs to hold a wake lock after 9th client connects @@ -2494,6 +2497,8 @@ __wma_handle_vdev_stop_rsp(struct vdev_stop_response *resp_event) } /* initiate CM to delete bss peer */ return wlan_cm_bss_peer_delete_ind(iface->vdev, &bssid); + } else if (mode == QDF_SAP_MODE) { + wlan_son_deliver_vdev_stop(iface->vdev); } return wma_delete_peer_on_vdev_stop(wma, resp_event->vdev_id);