diff --git a/components/target_if/tdls/inc/target_if_tdls.h b/components/target_if/tdls/inc/target_if_tdls.h new file mode 100644 index 000000000000..7fe21cdf0c4e --- /dev/null +++ b/components/target_if/tdls/inc/target_if_tdls.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017 The Linux Foundation. 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 copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: offload lmac interface APIs for tdls + * + */ + +#ifndef __TARGET_IF_TDLS_H__ +#define __TARGET_IF_TDLS_H__ + +struct tdls_info; +struct wlan_objmgr_psoc; +struct tdls_peer_update_state; +struct tdls_channel_switch_params; +struct sta_uapsd_trig_params; + +/** + * target_if_tdls_update_fw_state() - lmac handler to update tdls fw state + * @psoc: psoc object + * @param: tdls state parameter + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc, + struct tdls_info *param); + +/** + * target_if_tdls_update_peer_state() - lmac handler to update tdls peer state + * @psoc: psoc object + * @peer_params: tdls peer state params + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_update_peer_state(struct wlan_objmgr_psoc *psoc, + struct tdls_peer_update_state *peer_params); + +/** + * target_if_tdls_set_offchan_mode() - lmac handler to set tdls off channel mode + * @psoc: psoc object + * @params: tdls channel swithc params + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc, + struct tdls_channel_switch_params *params); + +/** + * target_if_tdls_set_uapsd() - lmac handler to set uapsd auto trigger cmd + * @psoc: psoc object + * @params: upasd parameters + * + * This function sets the trigger + * uapsd params such as service interval, delay interval + * and suspend interval which will be used by the firmware + * to send trigger frames periodically when there is no + * traffic on the transmit side. + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc, + struct sta_uapsd_trig_params *params); + +/** + * target_if_tdls_register_event_handler() - lmac handler to register tdls event + * handler + * @psoc : psoc object + * @arg: argument passed to lmac + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_register_event_handler(struct wlan_objmgr_psoc *psoc, + void *arg); + +/** + * target_if_tdls_unregister_event_handler() - lmac handler to unregister tdls + * event handler + * @psoc : psoc object + * @arg: argument passed to lmac + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_unregister_event_handler(struct wlan_objmgr_psoc *psoc, + void *arg); + +/** + * target_if_tdls_register_tx_ops() - lmac handler to register tdls tx ops + * callback functions + * @tx_ops: wlan_lmac_if_tx_ops object + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_tdls_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); +#endif diff --git a/components/target_if/tdls/src/target_if_tdls.c b/components/target_if/tdls/src/target_if_tdls.c new file mode 100644 index 000000000000..6adb2622319e --- /dev/null +++ b/components/target_if/tdls/src/target_if_tdls.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2017-2018 The Linux Foundation. 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 copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: offload lmac interface APIs for tdls + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline struct wlan_lmac_if_tdls_rx_ops * +target_if_tdls_get_rx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &psoc->soc_cb.rx_ops.tdls_rx_ops; +} + +static int +target_if_tdls_event_handler(ol_scn_t scn, uint8_t *data, uint32_t datalen) +{ + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_tdls_rx_ops *tdls_rx_ops; + struct tdls_event_info info; + QDF_STATUS status; + + if (!scn || !data) { + target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + target_if_err("null psoc"); + return -EINVAL; + } + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + + if (!wmi_handle) { + target_if_err("null wmi_handle"); + return -EINVAL; + } + + if (wmi_extract_vdev_tdls_ev_param(wmi_handle, data, &info)) { + target_if_err("Failed to extract wmi tdls event"); + return -EINVAL; + } + + tdls_rx_ops = target_if_tdls_get_rx_ops(psoc); + if (tdls_rx_ops && tdls_rx_ops->tdls_ev_handler) { + status = tdls_rx_ops->tdls_ev_handler(psoc, &info); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("fail to handle tdls event"); + return -EINVAL; + } + } + + return 0; +} + +QDF_STATUS +target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc, + struct tdls_info *param) +{ + QDF_STATUS status; + uint8_t tdls_state; + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + + if (TDLS_SUPPORT_EXP_TRIG_ONLY == param->tdls_state) + tdls_state = WMI_TDLS_ENABLE_PASSIVE; + else if (TDLS_SUPPORT_IMP_MODE == param->tdls_state || + TDLS_SUPPORT_EXT_CONTROL == param->tdls_state) + tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST; + else + tdls_state = WMI_TDLS_DISABLE; + + status = wmi_unified_update_fw_tdls_state_cmd(wmi_handle, + param, tdls_state); + + target_if_debug("vdev_id %d", param->vdev_id); + return status; +} + +QDF_STATUS +target_if_tdls_update_peer_state(struct wlan_objmgr_psoc *psoc, + struct tdls_peer_update_state *peer_params) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +target_if_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc, + struct tdls_channel_switch_params *params) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + status = wmi_unified_set_tdls_offchan_mode_cmd(wmi_handle, + params); + + return status; +} + +QDF_STATUS +target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc, + struct sta_uapsd_trig_params *params) +{ + QDF_STATUS ret; + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("Invalid WMI handle"); + return QDF_STATUS_E_FAILURE; + } + if (!wmi_service_enabled(wmi_handle, + wmi_sta_uapsd_basic_auto_trig) || + !wmi_service_enabled(wmi_handle, + wmi_sta_uapsd_var_auto_trig)) { + target_if_debug("Trigger uapsd is not supported vdev id %d", + params->vdevid); + return QDF_STATUS_SUCCESS; + } + ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_handle, + params); + + if (QDF_IS_STATUS_ERROR(ret)) + target_if_err("Failed to send set uapsd param ret = %d", ret); + + return ret; +} + +QDF_STATUS +target_if_tdls_register_event_handler(struct wlan_objmgr_psoc *psoc, + void *arg) +{ + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("null wmi_handle"); + return QDF_STATUS_E_INVAL; + } + return wmi_unified_register_event(wmi_handle, + wmi_tdls_peer_event_id, + target_if_tdls_event_handler); +} + +QDF_STATUS +target_if_tdls_unregister_event_handler(struct wlan_objmgr_psoc *psoc, + void *arg) +{ + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("null wmi_handle"); + return QDF_STATUS_E_INVAL; + } + return wmi_unified_unregister_event(wmi_handle, + wmi_tdls_peer_event_id); +} + +QDF_STATUS +target_if_tdls_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_tdls_tx_ops *tdls_txops; + + tdls_txops = &tx_ops->tdls_tx_ops; + + tdls_txops->update_fw_state = target_if_tdls_update_fw_state; + tdls_txops->update_peer_state = target_if_tdls_update_peer_state; + tdls_txops->set_offchan_mode = target_if_tdls_set_offchan_mode; + tdls_txops->tdls_reg_ev_handler = target_if_tdls_register_event_handler; + tdls_txops->tdls_unreg_ev_handler = + target_if_tdls_unregister_event_handler; + tdls_txops->tdls_set_uapsd = target_if_tdls_set_uapsd; + + return QDF_STATUS_SUCCESS; +}