1  /*
2   * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
3   *
4   * Permission to use, copy, modify, and/or distribute this software for
5   * any purpose with or without fee is hereby granted, provided that the
6   * above copyright notice and this permission notice appear in all
7   * copies.
8   *
9   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16   * PERFORMANCE OF THIS SOFTWARE.
17   */
18  /**
19   * DOC: Implements low power heart beat offload feature API's
20   */
21  
22  #include "wlan_pmo_main.h"
23  #include "wlan_pmo_lphb.h"
24  #include "wlan_pmo_tgt_api.h"
25  #include "wlan_pmo_obj_mgmt_public_struct.h"
26  
27  #ifdef FEATURE_WLAN_LPHB
28  /**
29   * pmo_core_send_lphb_enable() - enable command of LPHB configuration requests
30   * @psoc: objmgr psoc handle
31   * @psoc_ctx: pmo private psoc ctx
32   * @lphb_conf_req: lphb request which need s to configure in fwr
33   * @by_user: whether this call is from user or cached resent
34   *
35   * Return: QDF status
36   */
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)37  static QDF_STATUS pmo_core_send_lphb_enable(struct wlan_objmgr_psoc *psoc,
38  			struct pmo_psoc_priv_obj *psoc_ctx,
39  			struct pmo_lphb_req *lphb_conf_req, bool by_user)
40  {
41  	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
42  	struct pmo_lphb_enable_req *ts_lphb_enable;
43  	int i;
44  
45  	if (!lphb_conf_req) {
46  		pmo_err("LPHB configuration is NULL");
47  		return QDF_STATUS_E_FAILURE;
48  	}
49  
50  	ts_lphb_enable = &(lphb_conf_req->params.lphb_enable_req);
51  	qdf_status = pmo_tgt_send_lphb_enable(psoc, ts_lphb_enable);
52  	if (qdf_status != QDF_STATUS_SUCCESS)
53  		goto out;
54  
55  	/* No need to cache non user request */
56  	if (!by_user) {
57  		qdf_status = QDF_STATUS_SUCCESS;
58  		goto out;
59  	}
60  
61  	/* target already configured, now cache command status */
62  	if (ts_lphb_enable->enable && ts_lphb_enable->item > 0) {
63  		i = ts_lphb_enable->item - 1;
64  		qdf_spin_lock_bh(&psoc_ctx->lock);
65  		psoc_ctx->wow.lphb_cache[i].cmd
66  			= pmo_lphb_set_en_param_indid;
67  		psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.enable =
68  			ts_lphb_enable->enable;
69  		psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.item =
70  			ts_lphb_enable->item;
71  		psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.session =
72  			ts_lphb_enable->session;
73  		qdf_spin_unlock_bh(&psoc_ctx->lock);
74  		pmo_debug("cached LPHB status in WMA context for item %d", i);
75  	} else {
76  		qdf_spin_lock_bh(&psoc_ctx->lock);
77  		qdf_mem_zero((void *)&psoc_ctx->wow.lphb_cache,
78  				sizeof(psoc_ctx->wow.lphb_cache));
79  		qdf_spin_unlock_bh(&psoc_ctx->lock);
80  		pmo_debug("cleared all cached LPHB status in WMA context");
81  	}
82  
83  out:
84  	return qdf_status;
85  }
86  
87  /**
88   * pmo_core_send_lphb_tcp_params() - Send tcp params of LPHB requests
89   * @psoc: objmgr psoc handle
90   * @lphb_conf_req: lphb request which needs to be configured in fwr
91   *
92   * Return: QDF status
93   */
94  static
pmo_core_send_lphb_tcp_params(struct wlan_objmgr_psoc * psoc,struct pmo_lphb_req * lphb_conf_req)95  QDF_STATUS pmo_core_send_lphb_tcp_params(struct wlan_objmgr_psoc *psoc,
96  			struct pmo_lphb_req *lphb_conf_req)
97  {
98  	return pmo_tgt_send_lphb_tcp_params(psoc,
99  			&lphb_conf_req->params.lphb_tcp_params);
100  
101  }
102  
103  /**
104   * pmo_core_send_lphb_tcp_pkt_filter() - Send tcp packet filter command of LPHB
105   * @psoc: objmgr psoc handle
106   * @lphb_conf_req: lphb request which needs to be configured in fwr
107   *
108   * Return: QDF status
109   */
110  static
pmo_core_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc * psoc,struct pmo_lphb_req * lphb_conf_req)111  QDF_STATUS pmo_core_send_lphb_tcp_pkt_filter(struct wlan_objmgr_psoc *psoc,
112  			struct pmo_lphb_req *lphb_conf_req)
113  {
114  	return pmo_tgt_send_lphb_tcp_pkt_filter(psoc,
115  			&lphb_conf_req->params.lphb_tcp_filter_req);
116  }
117  
118  /**
119   * pmo_core_send_lphb_udp_params() - Send udp param command of LPHB
120   * @psoc: objmgr psoc handle
121   * @lphb_conf_req: lphb request which needs to be configured in fwr
122   *
123   * Return: QDF status
124   */
125  static
pmo_core_send_lphb_udp_params(struct wlan_objmgr_psoc * psoc,struct pmo_lphb_req * lphb_conf_req)126  QDF_STATUS pmo_core_send_lphb_udp_params(struct wlan_objmgr_psoc *psoc,
127  			struct pmo_lphb_req *lphb_conf_req)
128  {
129  	return pmo_tgt_send_lphb_udp_params(psoc,
130  			&lphb_conf_req->params.lphb_udp_params);
131  }
132  
133  /**
134   * pmo_core_send_lphb_udp_pkt_filter() - Send udp pkt filter command of LPHB
135   * @psoc: objmgr psoc handle
136   * @lphb_conf_req: lphb request which need s to configure in fwr
137   *
138   * Return: QDF status
139   */
140  static
pmo_core_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc * psoc,struct pmo_lphb_req * lphb_conf_req)141  QDF_STATUS pmo_core_send_lphb_udp_pkt_filter(struct wlan_objmgr_psoc *psoc,
142  			struct pmo_lphb_req *lphb_conf_req)
143  {
144  	return pmo_tgt_send_lphb_udp_pkt_filter(psoc,
145  			&lphb_conf_req->params.lphb_udp_filter_req);
146  }
147  
148  /**
149   * pmo_process_lphb_conf_req() - handle LPHB configuration requests
150   * @psoc: objmgr psoc handle
151   * @psoc_ctx: pmo private psoc ctx
152   * @lphb_conf_req: lphb request which needs to be configured in fwr
153   *
154   * Return: QDF status
155   */
pmo_process_lphb_conf_req(struct wlan_objmgr_psoc * psoc,struct pmo_psoc_priv_obj * psoc_ctx,struct pmo_lphb_req * lphb_conf_req)156  static QDF_STATUS pmo_process_lphb_conf_req(struct wlan_objmgr_psoc *psoc,
157  		struct pmo_psoc_priv_obj *psoc_ctx,
158  		struct pmo_lphb_req *lphb_conf_req)
159  {
160  	QDF_STATUS status = QDF_STATUS_SUCCESS;
161  
162  	pmo_debug("LPHB configuration cmd id is %d", lphb_conf_req->cmd);
163  	switch (lphb_conf_req->cmd) {
164  	case pmo_lphb_set_en_param_indid:
165  		status = pmo_core_send_lphb_enable(psoc, psoc_ctx,
166  					lphb_conf_req, true);
167  		break;
168  
169  	case pmo_lphb_set_tcp_pararm_indid:
170  		status = pmo_core_send_lphb_tcp_params(psoc, lphb_conf_req);
171  		break;
172  
173  	case pmo_lphb_set_tcp_pkt_filter_indid:
174  		status = pmo_core_send_lphb_tcp_pkt_filter(psoc, lphb_conf_req);
175  		break;
176  
177  	case pmo_lphb_set_udp_pararm_indid:
178  		status = pmo_core_send_lphb_udp_params(psoc, lphb_conf_req);
179  		break;
180  
181  	case pmo_lphb_set_udp_pkt_filter_indid:
182  		status = pmo_core_send_lphb_udp_pkt_filter(psoc, lphb_conf_req);
183  		break;
184  
185  	case pmo_lphb_set_network_info_indid:
186  	default:
187  		break;
188  	}
189  
190  	return status;
191  }
192  
pmo_core_apply_lphb(struct wlan_objmgr_psoc * psoc)193  void pmo_core_apply_lphb(struct wlan_objmgr_psoc *psoc)
194  {
195  	int i;
196  	struct pmo_psoc_priv_obj *psoc_ctx;
197  
198  	psoc_ctx = pmo_psoc_get_priv(psoc);
199  
200  	pmo_debug("checking LPHB cache");
201  	for (i = 0; i < 2; i++) {
202  		if (psoc_ctx->wow.lphb_cache[i].params.lphb_enable_req.enable) {
203  			pmo_debug("LPHB cache for item %d is marked as enable",
204  				i + 1);
205  			pmo_core_send_lphb_enable(psoc, psoc_ctx,
206  				&(psoc_ctx->wow.lphb_cache[i]), false);
207  		}
208  	}
209  }
210  
pmo_core_lphb_config_req(struct wlan_objmgr_psoc * psoc,struct pmo_lphb_req * lphb_req,void * lphb_cb_ctx,pmo_lphb_callback callback)211  QDF_STATUS pmo_core_lphb_config_req(struct wlan_objmgr_psoc *psoc,
212  		struct pmo_lphb_req *lphb_req, void *lphb_cb_ctx,
213  		pmo_lphb_callback callback)
214  {
215  	struct pmo_psoc_priv_obj *psoc_ctx;
216  
217  	if (!lphb_req) {
218  		pmo_err("LPHB configuration is NULL");
219  		return QDF_STATUS_E_NULL_VALUE;
220  	}
221  
222  	psoc_ctx = pmo_psoc_get_priv(psoc);
223  
224  	if (pmo_lphb_set_en_param_indid == lphb_req->cmd) {
225  		if (!lphb_cb_ctx) {
226  			pmo_err("lphb callback context is null");
227  			return QDF_STATUS_E_NULL_VALUE;
228  		}
229  		if (!callback) {
230  			pmo_err("lphb callback function is null");
231  			return QDF_STATUS_E_NULL_VALUE;
232  		}
233  		qdf_spin_lock_bh(&psoc_ctx->lock);
234  		psoc_ctx->wow.lphb_cb_ctx = lphb_cb_ctx;
235  		psoc_ctx->wow.lphb_cb = callback;
236  		qdf_spin_unlock_bh(&psoc_ctx->lock);
237  	}
238  
239  	return pmo_process_lphb_conf_req(psoc, psoc_ctx, lphb_req);
240  }
241  
242  #endif /* FEATURE_WLAN_LPHB */
243  
244