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