blob: 1c7b28b6f596ebd84c8f2e29ac17defa6997a092 [file] [log] [blame]
Mukul Sharmad75a6672017-06-22 15:40:53 +05301/*
Jeff Johnsonb4c29962017-10-07 19:35:14 -07002 * Copyright (c) 2017 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 */
Mukul Sharmad75a6672017-06-22 15:40:53 +053018/**
19 * DOC: Implements arp offload feature API's
20 */
21
22#include "wlan_pmo_arp.h"
23#include "wlan_pmo_tgt_api.h"
24#include "wlan_pmo_main.h"
25#include "wlan_pmo_obj_mgmt_public_struct.h"
26
27static QDF_STATUS pmo_core_cache_arp_in_vdev_priv(
28 struct pmo_arp_req *arp_req,
29 struct wlan_objmgr_vdev *vdev)
30{
31 QDF_STATUS status = QDF_STATUS_SUCCESS;
32 struct pmo_arp_offload_params *request = NULL;
33 struct pmo_psoc_priv_obj *psoc_ctx;
34 struct pmo_vdev_priv_obj *vdev_ctx;
35 int index;
36 struct qdf_mac_addr peer_bssid;
37
38 PMO_ENTER();
39 psoc_ctx = pmo_psoc_get_priv(arp_req->psoc);
40
41 vdev_ctx = pmo_vdev_get_priv(vdev);
42
43 request = qdf_mem_malloc(sizeof(*request));
44 if (!request) {
45 pmo_err("cannot allocate arp request");
46 status = QDF_STATUS_E_NOMEM;
47 goto out;
48 }
49
50 status = pmo_get_vdev_bss_peer_mac_addr(vdev,
51 &peer_bssid);
52 if (status != QDF_STATUS_SUCCESS)
53 goto out;
54
55 qdf_mem_copy(&request->bssid.bytes, &peer_bssid.bytes,
56 QDF_MAC_ADDR_SIZE);
Rajeev Kumar6f5fc882017-09-25 16:59:44 -070057 pmo_debug("vdev self mac addr: %pM bss peer mac addr: %pM",
Mukul Sharmad75a6672017-06-22 15:40:53 +053058 wlan_vdev_mlme_get_macaddr(vdev),
59 peer_bssid.bytes);
60
61 request->enable = PMO_OFFLOAD_ENABLE;
62 /* converting u32 to IPV4 address */
63 for (index = 0; index < PMO_IPV4_ADDR_LEN; index++)
64 request->host_ipv4_addr[index] =
65 (arp_req->ipv4_addr >> (index * 8)) & 0xFF;
66
67 /* cache arp request */
68 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
69 qdf_mem_copy(&vdev_ctx->vdev_arp_req, request,
70 sizeof(vdev_ctx->vdev_arp_req));
71 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
Rajeev Kumar6f5fc882017-09-25 16:59:44 -070072 pmo_debug("arp offload ipv4 addr: %d.%d.%d.%d enable: %d",
Mukul Sharmad75a6672017-06-22 15:40:53 +053073 request->host_ipv4_addr[0],
74 request->host_ipv4_addr[1],
75 request->host_ipv4_addr[2],
76 request->host_ipv4_addr[3],
77 request->enable);
78out:
79 if (request)
80 qdf_mem_free(request);
81 PMO_EXIT();
82
83 return status;
84}
85
86static QDF_STATUS pmo_core_flush_arp_from_vdev_priv(
87 struct wlan_objmgr_vdev *vdev)
88{
89 struct pmo_vdev_priv_obj *vdev_ctx;
90
91 PMO_ENTER();
92
93 vdev_ctx = pmo_vdev_get_priv(vdev);
94
95 /* clear arp request */
96 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
97 qdf_mem_zero(&vdev_ctx->vdev_arp_req, sizeof(vdev_ctx->vdev_arp_req));
98 vdev_ctx->vdev_arp_req.enable = PMO_OFFLOAD_DISABLE;
99 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
100
101 PMO_EXIT();
102
103 return QDF_STATUS_SUCCESS;
104}
105
106static QDF_STATUS pmo_core_do_enable_arp_offload(struct wlan_objmgr_vdev *vdev,
107 uint8_t vdev_id, enum pmo_offload_trigger trigger)
108{
109 QDF_STATUS status = QDF_STATUS_SUCCESS;
110 struct pmo_psoc_priv_obj *psoc_ctx;
111 struct pmo_vdev_priv_obj *vdev_ctx;
112
113 PMO_ENTER();
114
115 vdev_ctx = pmo_vdev_get_priv(vdev);
116
117 psoc_ctx = vdev_ctx->pmo_psoc_ctx;
118 if (!psoc_ctx) {
119 pmo_err("psoc_ctx is NULL");
120 status = QDF_STATUS_E_NULL_VALUE;
121 goto out;
122 }
123
124 switch (trigger) {
125 case pmo_ipv4_change_notify:
126 if (!psoc_ctx->psoc_cfg.active_mode_offload) {
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700127 pmo_debug("active offload is disabled, skip in mode:%d",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530128 trigger);
129 status = QDF_STATUS_E_INVAL;
130 goto out;
131 }
132 /* enable arp when active offload is true (ipv4 notifier) */
133 status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id);
134 break;
135 case pmo_apps_suspend:
136 if (psoc_ctx->psoc_cfg.active_mode_offload) {
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700137 pmo_debug("active offload is enabled, skip in mode: %d",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530138 trigger);
139 status = QDF_STATUS_E_INVAL;
140 goto out;
141 }
142 /* enable arp when active offload is false (apps suspend) */
143 status = pmo_tgt_enable_arp_offload_req(vdev, vdev_id);
144 break;
145 default:
146 status = QDF_STATUS_E_INVAL;
147 pmo_err("invalid pmo trigger");
148 break;
149 }
150out:
151 PMO_EXIT();
152
153 return status;
154}
155
156static QDF_STATUS pmo_core_do_disable_arp_offload(struct wlan_objmgr_vdev *vdev,
157 uint8_t vdev_id, enum pmo_offload_trigger trigger)
158{
159 QDF_STATUS status = QDF_STATUS_SUCCESS;
160 struct pmo_psoc_priv_obj *psoc_ctx;
161 struct pmo_vdev_priv_obj *vdev_ctx;
162
163 PMO_ENTER();
164
165 vdev_ctx = pmo_vdev_get_priv(vdev);
166
167 psoc_ctx = vdev_ctx->pmo_psoc_ctx;
168 if (!psoc_ctx) {
169 pmo_err("psoc_ctx is NULL");
170 status = QDF_STATUS_E_NULL_VALUE;
171 goto out;
172 }
173
174 switch (trigger) {
175 case pmo_apps_resume:
176 if (psoc_ctx->psoc_cfg.active_mode_offload) {
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700177 pmo_debug("active offload is enabled, skip in mode: %d",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530178 trigger);
179 status = QDF_STATUS_E_INVAL;
180 goto out;
181 }
182 /* disable arp on apps resume when active offload is disable */
183 status = pmo_tgt_disable_arp_offload_req(vdev, vdev_id);
184 break;
185 default:
186 status = QDF_STATUS_E_INVAL;
187 pmo_err("invalid pmo trigger");
188 break;
189 }
190out:
191 PMO_EXIT();
192
193 return status;
194}
195
196static QDF_STATUS pmo_core_arp_offload_sanity(
197 struct wlan_objmgr_vdev *vdev)
198{
199 struct pmo_vdev_priv_obj *vdev_ctx;
200
201 if (!vdev) {
202 pmo_err("vdev is NULL");
203 return QDF_STATUS_E_NULL_VALUE;
204 }
205
206 vdev_ctx = pmo_vdev_get_priv(vdev);
207 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.arp_offload_enable) {
208 pmo_err("user disabled arp offload using ini");
209 return QDF_STATUS_E_INVAL;
210 }
211
212 if (!pmo_core_is_vdev_supports_offload(vdev)) {
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700213 pmo_debug("vdev in invalid opmode for arp offload %d",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530214 pmo_get_vdev_opmode(vdev));
215 return QDF_STATUS_E_INVAL;
216 }
217
218 if (!pmo_core_is_vdev_connected(vdev))
219 return QDF_STATUS_E_INVAL;
220
221 return QDF_STATUS_SUCCESS;
222}
223
224QDF_STATUS pmo_core_cache_arp_offload_req(struct pmo_arp_req *arp_req)
225{
226 QDF_STATUS status;
227 struct wlan_objmgr_vdev *vdev;
228
229 PMO_ENTER();
230 if (!arp_req) {
231 pmo_err("arp_req is NULL");
232 status = QDF_STATUS_E_INVAL;
233 goto out;
234 }
235
236 if (!arp_req->psoc) {
237 pmo_err("psoc is NULL");
238 status = QDF_STATUS_E_INVAL;
239 goto out;
240 }
241
242 vdev = pmo_psoc_get_vdev(arp_req->psoc, arp_req->vdev_id);
243 if (!vdev) {
244 pmo_err("vdev is NULL");
245 status = QDF_STATUS_E_INVAL;
246 goto out;
247 }
248
249 status = pmo_vdev_get_ref(vdev);
250 if (QDF_IS_STATUS_ERROR(status))
251 goto out;
252
253 status = pmo_core_arp_offload_sanity(vdev);
254 if (status != QDF_STATUS_SUCCESS)
255 goto dec_ref;
256
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700257 pmo_debug("Cache arp for vdev id: %d psoc: %pK vdev: %pK",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530258 arp_req->vdev_id, arp_req->psoc, vdev);
259
260 status = pmo_core_cache_arp_in_vdev_priv(arp_req, vdev);
261dec_ref:
262 pmo_vdev_put_ref(vdev);
263out:
264 PMO_EXIT();
265
266 return status;
267}
268
269QDF_STATUS pmo_core_flush_arp_offload_req(struct wlan_objmgr_vdev *vdev)
270{
271 QDF_STATUS status;
272 uint8_t vdev_id;
273
274 PMO_ENTER();
275 if (!vdev) {
276 pmo_err("vdev is NULL");
277 status = QDF_STATUS_E_NULL_VALUE;
278 goto out;
279 }
280
281 status = pmo_vdev_get_ref(vdev);
282 if (status != QDF_STATUS_SUCCESS)
283 goto out;
284
285 status = pmo_core_arp_offload_sanity(vdev);
286 if (status != QDF_STATUS_SUCCESS)
287 goto def_ref;
288
289 vdev_id = pmo_vdev_get_id(vdev);
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700290 pmo_debug("Flush arp for vdev id: %d vdev: %pK", vdev_id, vdev);
Mukul Sharmad75a6672017-06-22 15:40:53 +0530291
292 status = pmo_core_flush_arp_from_vdev_priv(vdev);
293def_ref:
294 pmo_vdev_put_ref(vdev);
295out:
296 PMO_EXIT();
297
298 return status;
299}
300
301QDF_STATUS pmo_core_enable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev,
302 enum pmo_offload_trigger trigger)
303{
304 QDF_STATUS status;
305 uint8_t vdev_id;
306
307 PMO_ENTER();
308 if (!vdev) {
309 pmo_err("vdev is NULL");
310 status = QDF_STATUS_E_NULL_VALUE;
311 goto out;
312 }
313
314 status = pmo_vdev_get_ref(vdev);
315 if (status != QDF_STATUS_SUCCESS)
316 goto out;
317
318 status = pmo_core_arp_offload_sanity(vdev);
319 if (status != QDF_STATUS_SUCCESS)
320 goto def_ref;
321
322 vdev_id = pmo_vdev_get_id(vdev);
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700323 pmo_debug("Enable arp offload in fwr vdev id: %d vdev: %pK",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530324 vdev_id, vdev);
325
326 status = pmo_core_do_enable_arp_offload(vdev, vdev_id, trigger);
327def_ref:
328 pmo_vdev_put_ref(vdev);
329out:
330 PMO_EXIT();
331
332 return status;
333}
334
335QDF_STATUS pmo_core_disable_arp_offload_in_fwr(struct wlan_objmgr_vdev *vdev,
336 enum pmo_offload_trigger trigger)
337{
338 QDF_STATUS status;
339 uint8_t vdev_id;
340
341 PMO_ENTER();
342 if (!vdev) {
343 pmo_err("vdev is NULL");
344 status = QDF_STATUS_E_NULL_VALUE;
345 goto out;
346 }
347
348 status = pmo_vdev_get_ref(vdev);
349 if (status != QDF_STATUS_SUCCESS)
350 goto out;
351
352 status = pmo_core_arp_offload_sanity(vdev);
353 if (status != QDF_STATUS_SUCCESS)
354 goto def_ref;
355
356 vdev_id = pmo_vdev_get_id(vdev);
Rajeev Kumar6f5fc882017-09-25 16:59:44 -0700357 pmo_debug("Disable arp offload in fwr vdev id: %d vdev: %pK",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530358 vdev_id, vdev);
359
360 status = pmo_core_do_disable_arp_offload(vdev, vdev_id, trigger);
361def_ref:
362 pmo_vdev_put_ref(vdev);
363out:
364 PMO_EXIT();
365
366 return status;
367}
368