| /* |
| * 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: Implement various api / helper function which shall be used |
| * PMO user and target interface. |
| */ |
| |
| #include "wlan_pmo_main.h" |
| #include "wlan_pmo_obj_mgmt_public_struct.h" |
| |
| static struct wlan_pmo_ctx *gp_pmo_ctx; |
| |
| QDF_STATUS pmo_allocate_ctx(void) |
| { |
| /* If it is already created, ignore */ |
| if (gp_pmo_ctx != NULL) { |
| pmo_debug("already allocated pmo_ctx"); |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /* allocate offload mgr ctx */ |
| gp_pmo_ctx = (struct wlan_pmo_ctx *)qdf_mem_malloc( |
| sizeof(*gp_pmo_ctx)); |
| if (!gp_pmo_ctx) { |
| pmo_err("unable to allocate pmo_ctx"); |
| QDF_ASSERT(0); |
| return QDF_STATUS_E_NOMEM; |
| } |
| qdf_spinlock_create(&gp_pmo_ctx->lock); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| void pmo_free_ctx(void) |
| { |
| if (!gp_pmo_ctx) { |
| pmo_err("pmo ctx is already freed"); |
| QDF_ASSERT(0); |
| return; |
| } |
| qdf_spinlock_destroy(&gp_pmo_ctx->lock); |
| qdf_mem_free(gp_pmo_ctx); |
| gp_pmo_ctx = NULL; |
| } |
| |
| struct wlan_pmo_ctx *pmo_get_context(void) |
| { |
| return gp_pmo_ctx; |
| } |
| |
| bool pmo_is_vdev_in_beaconning_mode(enum tQDF_ADAPTER_MODE vdev_opmode) |
| { |
| switch (vdev_opmode) { |
| case QDF_SAP_MODE: |
| case QDF_P2P_GO_MODE: |
| case QDF_IBSS_MODE: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| QDF_STATUS pmo_get_vdev_bss_peer_mac_addr(struct wlan_objmgr_vdev *vdev, |
| struct qdf_mac_addr *bss_peer_mac_address) |
| { |
| struct wlan_objmgr_peer *peer; |
| |
| if (!vdev) { |
| pmo_err("vdev is null"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| peer = wlan_vdev_get_bsspeer(vdev); |
| if (!peer) { |
| pmo_err("peer is null"); |
| return QDF_STATUS_E_INVAL; |
| } |
| |
| wlan_peer_obj_lock(peer); |
| qdf_mem_copy(bss_peer_mac_address->bytes, wlan_peer_get_macaddr(peer), |
| QDF_MAC_ADDR_SIZE); |
| wlan_peer_obj_unlock(peer); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| bool pmo_core_is_ap_mode_supports_arp_ns(struct wlan_objmgr_psoc *psoc, |
| enum tQDF_ADAPTER_MODE vdev_opmode) |
| { |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| |
| if ((vdev_opmode == QDF_SAP_MODE || |
| vdev_opmode == QDF_P2P_GO_MODE) && |
| !psoc_ctx->psoc_cfg.ap_arpns_support) { |
| pmo_info("ARP/NS Offload is not supported in SAP/P2PGO mode"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool pmo_core_is_vdev_connected(struct wlan_objmgr_vdev *vdev) |
| { |
| struct wlan_objmgr_peer *peer; |
| enum wlan_peer_state peer_state; |
| |
| peer = wlan_vdev_get_bsspeer(vdev); |
| |
| if (!peer) { |
| pmo_err("peer is null"); |
| return false; |
| } |
| peer_state = wlan_peer_mlme_get_state(peer); |
| |
| if (peer_state != WLAN_ASSOC_STATE) { |
| pmo_err("peer is not associated.peer state: %d", |
| peer_state); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool pmo_core_is_vdev_supports_offload(struct wlan_objmgr_vdev *vdev) |
| { |
| enum tQDF_ADAPTER_MODE opmode; |
| bool val; |
| |
| opmode = pmo_get_vdev_opmode(vdev); |
| pmo_info("vdev opmode: %d", opmode); |
| switch (opmode) { |
| case QDF_STA_MODE: |
| case QDF_P2P_CLIENT_MODE: |
| case QDF_NDI_MODE: |
| val = true; |
| break; |
| default: |
| val = false; |
| break; |
| } |
| |
| return val; |
| } |
| |
| QDF_STATUS pmo_core_get_psoc_config(struct wlan_objmgr_psoc *psoc, |
| struct pmo_psoc_cfg *psoc_cfg) |
| { |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| PMO_ENTER(); |
| if (!psoc || !psoc_cfg) { |
| pmo_err("%s is null", !psoc ? "psoc":"psoc_cfg"); |
| status = QDF_STATUS_E_NULL_VALUE; |
| goto out; |
| } |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| |
| qdf_spin_lock(&psoc_ctx->lock); |
| qdf_mem_copy(psoc_cfg, &psoc_ctx->psoc_cfg, sizeof(*psoc_cfg)); |
| qdf_spin_unlock(&psoc_ctx->lock); |
| out: |
| PMO_EXIT(); |
| |
| return status; |
| } |
| |
| QDF_STATUS pmo_core_update_psoc_config(struct wlan_objmgr_psoc *psoc, |
| struct pmo_psoc_cfg *psoc_cfg) |
| { |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| PMO_ENTER(); |
| if (!psoc || !psoc_cfg) { |
| pmo_err("%s is null", !psoc ? "psoc":"psoc_cfg"); |
| status = QDF_STATUS_E_NULL_VALUE; |
| goto out; |
| } |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| |
| qdf_spin_lock(&psoc_ctx->lock); |
| qdf_mem_copy(&psoc_ctx->psoc_cfg, psoc_cfg, sizeof(*psoc_cfg)); |
| qdf_spin_unlock(&psoc_ctx->lock); |
| out: |
| PMO_EXIT(); |
| |
| return status; |
| } |
| |
| void pmo_core_psoc_set_hif_handle(struct wlan_objmgr_psoc *psoc, |
| void *hif_hdl) |
| { |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| psoc_ctx->hif_hdl = hif_hdl; |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| } |
| |
| void *pmo_core_psoc_get_hif_handle(struct wlan_objmgr_psoc *psoc) |
| { |
| void *hif_hdl; |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| hif_hdl = psoc_ctx->hif_hdl; |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| |
| return hif_hdl; |
| } |
| |
| void pmo_core_psoc_set_txrx_handle(struct wlan_objmgr_psoc *psoc, |
| void *txrx_hdl) |
| { |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| psoc_ctx->txrx_hdl = txrx_hdl; |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| } |
| |
| void *pmo_core_psoc_get_txrx_handle(struct wlan_objmgr_psoc *psoc) |
| { |
| void *txrx_hdl; |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| txrx_hdl = psoc_ctx->txrx_hdl; |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| |
| return txrx_hdl; |
| } |