| /* |
| * 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: Implements low power heart beat offload feature API's |
| */ |
| |
| #include "wlan_pmo_main.h" |
| #include "wlan_pmo_lphb.h" |
| #include "wlan_pmo_tgt_api.h" |
| #include "wlan_pmo_obj_mgmt_public_struct.h" |
| |
| #ifdef FEATURE_WLAN_LPHB |
| /** |
| * pmo_core_send_lphb_enable() - enable command of LPHB configuration requests |
| * @psoc: objmgr psoc handle |
| * @psoc_ctx: pmo private psoc ctx |
| * @lphb_conf_req: lphb request which need s to configure in fwr |
| * @by_user: whether this call is from user or cached resent |
| * |
| * Return: QDF status |
| */ |
| static QDF_STATUS pmo_core_send_lphb_enable(struct wlan_objmgr_psoc *psoc, |
| struct pmo_psoc_priv_obj *psoc_ctx, |
| struct pmo_lphb_req *lphb_conf_req, bool by_user) |
| { |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| struct pmo_lphb_enable_req *ts_lphb_enable; |
| int i; |
| |
| if (lphb_conf_req == NULL) { |
| pmo_err("LPHB configuration is NULL"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| ts_lphb_enable = &(lphb_conf_req->params.lphb_enable_req); |
| qdf_status = pmo_tgt_send_lphb_enable(psoc, ts_lphb_enable); |
| if (qdf_status != QDF_STATUS_SUCCESS) |
| goto out; |
| |
| /* No need to cache non user request */ |
| if (!by_user) { |
| qdf_status = QDF_STATUS_SUCCESS; |
| goto out; |
| } |
| |
| /* target already configured, now cache command status */ |
| if (ts_lphb_enable->enable) { |
| i = ts_lphb_enable->item - 1; |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| psoc_ctx->wow.lphb_cache[i].cmd |
| = pmo_lphb_set_en_param_indid; |
| psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.enable = |
| ts_lphb_enable->enable; |
| psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.item = |
| ts_lphb_enable->item; |
| psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.session = |
| ts_lphb_enable->session; |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| pmo_info("cached LPHB status in WMA context for item %d", i); |
| } else { |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| qdf_mem_zero((void *)&psoc_ctx->wow.lphb_cache, |
| sizeof(psoc_ctx->wow.lphb_cache)); |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| pmo_info("cleared all cached LPHB status in WMA context"); |
| } |
| |
| out: |
| return qdf_status; |
| } |
| |
| /** |
| * pmo_core_send_lphb_tcp_params() - Send tcp params of LPHB requests |
| * @psoc: objmgr psoc handle |
| * @lphb_conf_req: lphb request which needs to be configured in fwr |
| * |
| * Return: QDF status |
| */ |
| static |
| QDF_STATUS pmo_core_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc, |
| struct pmo_lphb_req *lphb_conf_req) |
| { |
| return pmo_tgt_send_lphb_tcp_params(psoc, |
| &lphb_conf_req->params.lphb_tcp_params); |
| |
| } |
| |
| /** |
| * pmo_core_send_lphb_tcp_pkt_filter() - Send tcp packet filter command of LPHB |
| * @psoc: objmgr psoc handle |
| * @lphb_conf_req: lphb request which needs to be configured in fwr |
| * |
| * Return: QDF status |
| */ |
| static |
| QDF_STATUS pmo_core_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc, |
| struct pmo_lphb_req *lphb_conf_req) |
| { |
| return pmo_tgt_send_lphb_tcp_pkt_filter(psoc, |
| &lphb_conf_req->params.lphb_tcp_filter_req); |
| } |
| |
| /** |
| * pmo_core_send_lphb_udp_params() - Send udp param command of LPHB |
| * @psoc: objmgr psoc handle |
| * @lphb_conf_req: lphb request which needs to be configured in fwr |
| * |
| * Return: QDF status |
| */ |
| static |
| QDF_STATUS pmo_core_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc, |
| struct pmo_lphb_req *lphb_conf_req) |
| { |
| return pmo_tgt_send_lphb_udp_params(psoc, |
| &lphb_conf_req->params.lphb_udp_params); |
| } |
| |
| /** |
| * pmo_core_send_lphb_udp_pkt_filter() - Send udp pkt filter command of LPHB |
| * @psoc: objmgr psoc handle |
| * @lphb_conf_req: lphb request which need s to configure in fwr |
| * |
| * Return: QDF status |
| */ |
| static |
| QDF_STATUS pmo_core_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc, |
| struct pmo_lphb_req *lphb_conf_req) |
| { |
| return pmo_tgt_send_lphb_udp_pkt_filter(psoc, |
| &lphb_conf_req->params.lphb_udp_filter_req); |
| } |
| |
| /** |
| * pmo_process_lphb_conf_req() - handle LPHB configuration requests |
| * @psoc: objmgr psoc handle |
| * @psoc_ctx: pmo private psoc ctx |
| * @lphb_conf_req: lphb request which needs to be configured in fwr |
| * |
| * Return: QDF status |
| */ |
| static QDF_STATUS pmo_process_lphb_conf_req(struct wlan_objmgr_psoc *psoc, |
| struct pmo_psoc_priv_obj *psoc_ctx, |
| struct pmo_lphb_req *lphb_conf_req) |
| { |
| QDF_STATUS status = QDF_STATUS_SUCCESS; |
| |
| pmo_info("LPHB configuration cmd id is %d", lphb_conf_req->cmd); |
| switch (lphb_conf_req->cmd) { |
| case pmo_lphb_set_en_param_indid: |
| status = pmo_core_send_lphb_enable(psoc, psoc_ctx, |
| lphb_conf_req, true); |
| break; |
| |
| case pmo_lphb_set_tcp_pararm_indid: |
| status = pmo_core_send_lphb_tcp_params(psoc, lphb_conf_req); |
| break; |
| |
| case pmo_lphb_set_tcp_pkt_filter_indid: |
| status = pmo_core_send_lphb_tcp_pkt_filter(psoc, lphb_conf_req); |
| break; |
| |
| case pmo_lphb_set_udp_pararm_indid: |
| status = pmo_core_send_lphb_udp_params(psoc, lphb_conf_req); |
| break; |
| |
| case pmo_lphb_set_udp_pkt_filter_indid: |
| status = pmo_core_send_lphb_udp_pkt_filter(psoc, lphb_conf_req); |
| break; |
| |
| case pmo_lphb_set_network_info_indid: |
| default: |
| break; |
| } |
| |
| return status; |
| } |
| |
| void pmo_core_apply_lphb(struct wlan_objmgr_psoc *psoc) |
| { |
| int i; |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| |
| pmo_debug("checking LPHB cache"); |
| for (i = 0; i < 2; i++) { |
| if (psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.enable) { |
| pmo_debug("LPHB cache for item %d is marked as enable", |
| i + 1); |
| pmo_core_send_lphb_enable(psoc, psoc_ctx, |
| &(psoc_ctx->wow.lphb_cache[i]), false); |
| } |
| } |
| } |
| |
| QDF_STATUS pmo_core_lphb_config_req(struct wlan_objmgr_psoc *psoc, |
| struct pmo_lphb_req *lphb_req, void *lphb_cb_ctx, |
| pmo_lphb_callback callback) |
| { |
| struct pmo_psoc_priv_obj *psoc_ctx; |
| |
| if (lphb_req == NULL) { |
| pmo_err("LPHB configuration is NULL"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| |
| psoc_ctx = pmo_psoc_get_priv(psoc); |
| |
| if (pmo_lphb_set_en_param_indid == lphb_req->cmd) { |
| if (!lphb_cb_ctx) { |
| pmo_err("lphb callback context is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| if (!callback) { |
| pmo_err("lphb callback function is null"); |
| return QDF_STATUS_E_NULL_VALUE; |
| } |
| qdf_spin_lock_bh(&psoc_ctx->lock); |
| psoc_ctx->wow.lphb_cb_ctx = lphb_cb_ctx; |
| psoc_ctx->wow.lphb_cb = callback; |
| qdf_spin_unlock_bh(&psoc_ctx->lock); |
| } |
| |
| return pmo_process_lphb_conf_req(psoc, psoc_ctx, lphb_req); |
| } |
| |
| #endif /* FEATURE_WLAN_LPHB */ |
| |