blob: f366f0785f9e412bb5a8936cb88ce2e0f823fb24 [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 mc addr filtering offload feature API's
20 */
21
22#include "wlan_pmo_mc_addr_filtering.h"
23#include "wlan_pmo_tgt_api.h"
24#include "wlan_pmo_main.h"
25#include "wlan_pmo_obj_mgmt_public_struct.h"
26
27
28#define PMO_INVALID_MC_ADDR_COUNT (-1)
29
30static void pmo_core_fill_mc_list(struct pmo_vdev_priv_obj **vdev_ctx,
31 struct pmo_mc_addr_list_params *ip)
32{
33 struct pmo_mc_addr_list *op_list;
34 int i;
35 static const uint8_t ipv6_rs[] = {
36 0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
37 struct pmo_vdev_priv_obj *temp_ctx;
38 uint8_t addr_fp;
39
40 temp_ctx = *vdev_ctx;
41 addr_fp = temp_ctx->addr_filter_pattern;
42 op_list = &temp_ctx->vdev_mc_list_req;
43
44 qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock);
45 op_list->mc_cnt = ip->count;
46 qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock);
47
48 for (i = 0; i < ip->count; i++) {
49 pmo_debug("%pM", ip->mc_addr[i].bytes);
50 /*
51 * Skip following addresses:
52 * 1)IPv6 router solicitation address
53 * 2)Any other address pattern if its set during
54 * RXFILTER REMOVE driver command based on
55 * addr_filter_pattern
56 */
57 if ((!qdf_mem_cmp(ip->mc_addr[i].bytes, ipv6_rs,
58 QDF_MAC_ADDR_SIZE)) ||
59 (addr_fp &&
60 (!qdf_mem_cmp(ip->mc_addr[i].bytes, &addr_fp, 1)))) {
61 pmo_debug("MC/BC filtering Skip addr %pM",
62 ip->mc_addr[i].bytes);
63 qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock);
64 op_list->mc_cnt--;
65 qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock);
66 continue;
67 }
68 qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock);
69 qdf_mem_set(&(op_list->mc_addr[i].bytes), 0,
70 QDF_MAC_ADDR_SIZE);
71 qdf_mem_copy(&(op_list->mc_addr[i].bytes),
72 ip->mc_addr[i].bytes, QDF_MAC_ADDR_SIZE);
73 qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock);
74 pmo_debug("mlist[%pM] = ", op_list->mc_addr[i].bytes);
75 }
76}
77
78static QDF_STATUS pmo_core_cache_mc_addr_list_in_vdev_priv(
79 struct pmo_mc_addr_list_params *mc_list_config,
80 struct wlan_objmgr_vdev *vdev)
81{
82 struct pmo_vdev_priv_obj *vdev_ctx;
83
84 vdev_ctx = pmo_vdev_get_priv(vdev);
85 pmo_core_fill_mc_list(&vdev_ctx, mc_list_config);
86
87 return QDF_STATUS_SUCCESS;
88}
89
90static QDF_STATUS pmo_core_flush_mc_addr_list_from_vdev_priv(
91 struct wlan_objmgr_vdev *vdev)
92{
93 struct pmo_vdev_priv_obj *vdev_ctx;
94
95 vdev_ctx = pmo_vdev_get_priv(vdev);
96
97 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
98 qdf_mem_zero(&vdev_ctx->vdev_mc_list_req,
99 sizeof(vdev_ctx->vdev_mc_list_req));
100 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
101
102 return QDF_STATUS_SUCCESS;
103}
104
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700105QDF_STATUS pmo_core_enhanced_mc_filter_enable(struct wlan_objmgr_vdev *vdev)
106{
107 QDF_STATUS status;
108
109 PMO_ENTER();
110
111 status = pmo_vdev_get_ref(vdev);
112 if (QDF_IS_STATUS_ERROR(status))
113 goto exit_with_status;
114
115 pmo_tgt_send_enhance_multicast_offload_req(vdev, true);
116
117 pmo_vdev_put_ref(vdev);
118
119exit_with_status:
120 PMO_EXIT();
121
122 return status;
123}
124
125QDF_STATUS pmo_core_enhanced_mc_filter_disable(struct wlan_objmgr_vdev *vdev)
126{
127 QDF_STATUS status;
128
129 PMO_ENTER();
130
131 status = pmo_vdev_get_ref(vdev);
132 if (QDF_IS_STATUS_ERROR(status))
133 goto exit_with_status;
134
135 pmo_tgt_send_enhance_multicast_offload_req(vdev, false);
136
137 pmo_vdev_put_ref(vdev);
138
139exit_with_status:
140 PMO_EXIT();
141
142 return status;
143}
144
Mukul Sharmad75a6672017-06-22 15:40:53 +0530145QDF_STATUS pmo_core_set_mc_filter_req(struct wlan_objmgr_vdev *vdev,
146 struct pmo_mc_addr_list *mc_list)
147{
Mukul Sharmad75a6672017-06-22 15:40:53 +0530148 int i;
149
150 PMO_ENTER();
151
Poddar, Siddarthf7c49e72017-09-28 17:13:25 +0530152 if (pmo_tgt_get_multiple_mc_filter_support(vdev)) {
153 pmo_debug("FW supports multiple mcast filter");
154 pmo_tgt_set_multiple_mc_filter_req(vdev, mc_list);
155 } else {
156 pmo_debug("FW does not support multiple mcast filter");
157 for (i = 0; i < mc_list->mc_cnt; i++)
158 pmo_tgt_set_mc_filter_req(vdev, mc_list->mc_addr[i]);
Mukul Sharmad75a6672017-06-22 15:40:53 +0530159 }
160
161 PMO_EXIT();
162
163 return QDF_STATUS_SUCCESS;
164}
165
166QDF_STATUS pmo_core_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev,
167 struct pmo_mc_addr_list *mc_list)
168{
Mukul Sharmad75a6672017-06-22 15:40:53 +0530169 int i;
170
171 PMO_ENTER();
Poddar, Siddarthf7c49e72017-09-28 17:13:25 +0530172 if (pmo_tgt_get_multiple_mc_filter_support(vdev)) {
173 pmo_debug("FW supports multiple mcast filter");
174 pmo_tgt_clear_multiple_mc_filter_req(vdev, mc_list);
175 } else {
176 pmo_debug("FW does not support multiple mcast filter");
177 for (i = 0; i < mc_list->mc_cnt; i++)
178 pmo_tgt_clear_mc_filter_req(vdev, mc_list->mc_addr[i]);
Mukul Sharmad75a6672017-06-22 15:40:53 +0530179 }
180
181 PMO_EXIT();
182
183 return QDF_STATUS_SUCCESS;
184}
185
186static QDF_STATUS pmo_core_do_enable_mc_addr_list(struct wlan_objmgr_vdev *vdev,
187 struct pmo_vdev_priv_obj *vdev_ctx,
188 struct pmo_mc_addr_list *op_mc_list_req)
189{
190 QDF_STATUS status;
191
192 PMO_ENTER();
193 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
194 if (!vdev_ctx->vdev_mc_list_req.mc_cnt) {
195 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
196 pmo_err("mc_cnt is zero so skip to add mc list");
197 status = QDF_STATUS_E_INVAL;
198 goto out;
199 }
200 qdf_mem_copy(op_mc_list_req, &vdev_ctx->vdev_mc_list_req,
201 sizeof(*op_mc_list_req));
202 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
203
204 status = pmo_core_set_mc_filter_req(vdev, op_mc_list_req);
205 if (status != QDF_STATUS_SUCCESS) {
206 pmo_err("cannot apply mc filter request");
207 status = QDF_STATUS_E_INVAL;
208 goto out;
209 }
210
211 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
212 vdev_ctx->vdev_mc_list_req.is_filter_applied = true;
213 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
214out:
215 PMO_EXIT();
216
217 return status;
218}
219
220static QDF_STATUS pmo_core_do_disable_mc_addr_list(
221 struct wlan_objmgr_vdev *vdev,
222 struct pmo_vdev_priv_obj *vdev_ctx,
223 struct pmo_mc_addr_list *op_mc_list_req)
224{
225 QDF_STATUS status;
226
227 PMO_ENTER();
228 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
229 /* validate filter is applied before clearing in fwr */
230 if (!vdev_ctx->vdev_mc_list_req.is_filter_applied) {
231 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
232 pmo_err("mc filter is not applied in fwr");
233 status = QDF_STATUS_E_INVAL;
234 goto out;
235 }
236 qdf_mem_copy(op_mc_list_req, &vdev_ctx->vdev_mc_list_req,
237 sizeof(*op_mc_list_req));
238 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
239
240 status = pmo_core_clear_mc_filter_req(vdev, op_mc_list_req);
241 if (status != QDF_STATUS_SUCCESS) {
242 pmo_err("cannot apply mc filter request");
243 status = QDF_STATUS_E_INVAL;
244 goto out;
245 }
246
247 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
248 vdev_ctx->vdev_mc_list_req.is_filter_applied = false;
249 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
250out:
251 PMO_EXIT();
252
253 return status;
254}
255
256uint8_t pmo_core_max_mc_addr_supported(struct wlan_objmgr_psoc *psoc)
257{
258 return PMO_MAX_MC_ADDR_LIST;
259}
260
261int pmo_core_get_mc_addr_list_count(struct wlan_objmgr_psoc *psoc,
262 uint8_t vdev_id)
263{
264 QDF_STATUS status;
265 struct wlan_objmgr_vdev *vdev;
266 struct pmo_vdev_priv_obj *vdev_ctx;
267 uint8_t mc_cnt;
268
269 vdev = pmo_psoc_get_vdev(psoc, vdev_id);
270 if (!vdev) {
271 pmo_err("vdev is NULL");
272 return PMO_INVALID_MC_ADDR_COUNT;
273 }
274
275 status = pmo_vdev_get_ref(vdev);
276 if (QDF_IS_STATUS_ERROR(status)) {
277 pmo_warn("failed to get vdev reference");
278 return PMO_INVALID_MC_ADDR_COUNT;
279 }
280
281 vdev_ctx = pmo_vdev_get_priv(vdev);
282 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
283 mc_cnt = vdev_ctx->vdev_mc_list_req.mc_cnt;
284 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
285
286 pmo_vdev_put_ref(vdev);
287
288 return mc_cnt;
289}
290
291void pmo_core_set_mc_addr_list_count(struct wlan_objmgr_psoc *psoc,
292 uint8_t vdev_id, uint8_t count)
293{
294 QDF_STATUS status;
295 struct pmo_vdev_priv_obj *vdev_ctx;
296 struct wlan_objmgr_vdev *vdev;
297
298 vdev = pmo_psoc_get_vdev(psoc, vdev_id);
299 if (!vdev) {
300 pmo_err("vdev is NULL");
301 return;
302 }
303
304 status = pmo_vdev_get_ref(vdev);
305 if (QDF_IS_STATUS_ERROR(status)) {
306 pmo_warn("failed to get vdev reference");
307 return;
308 }
309
310 vdev_ctx = pmo_vdev_get_priv(vdev);
311 qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
312 vdev_ctx->vdev_mc_list_req.mc_cnt = count;
313 qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
314
315 pmo_vdev_put_ref(vdev);
316}
317
318static QDF_STATUS pmo_core_mc_addr_flitering_sanity(
319 struct wlan_objmgr_vdev *vdev)
320{
321 struct pmo_vdev_priv_obj *vdev_ctx;
322
323 if (!vdev) {
324 pmo_err("vdev is NULL");
325 return QDF_STATUS_E_NULL_VALUE;
326 }
327
328 vdev_ctx = pmo_vdev_get_priv(vdev);
329
330 /* Check if INI is enabled or not, otherwise just return */
331 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list) {
332 pmo_info("user disabled mc_addr_list using INI");
333 return QDF_STATUS_E_INVAL;
334 }
335
336 if (!pmo_core_is_vdev_supports_offload(vdev)) {
337 pmo_info("vdev in invalid opmode for mc addr filtering %d",
338 pmo_get_vdev_opmode(vdev));
339 return QDF_STATUS_E_INVAL;
340 }
341
342 if (!pmo_core_is_vdev_connected(vdev))
343 return QDF_STATUS_E_INVAL;
344
345 return QDF_STATUS_SUCCESS;
346}
347QDF_STATUS pmo_core_cache_mc_addr_list(
348 struct pmo_mc_addr_list_params *mc_list_config)
349{
350 struct wlan_objmgr_vdev *vdev;
351 QDF_STATUS status;
352
353 PMO_ENTER();
354
355 if (!mc_list_config->psoc) {
356 pmo_err("psoc is NULL");
357 status = QDF_STATUS_E_NULL_VALUE;
358 goto out;
359 }
360
361 vdev = pmo_psoc_get_vdev(mc_list_config->psoc, mc_list_config->vdev_id);
362 if (!vdev) {
363 pmo_err("vdev is NULL");
364 status = QDF_STATUS_E_NULL_VALUE;
365 goto out;
366 }
367
368 status = pmo_vdev_get_ref(vdev);
369 if (QDF_IS_STATUS_ERROR(status)) {
370 pmo_warn("failed to get vdev reference");
371 status = QDF_STATUS_E_INVAL;
372 goto out;
373 }
374
375 status = pmo_core_mc_addr_flitering_sanity(vdev);
376 if (status != QDF_STATUS_SUCCESS)
377 goto dec_ref;
378
Jeff Johnson0a645382017-09-18 08:17:59 -0700379 pmo_info("Cache mc addr list for vdev id: %d psoc: %pK vdev: %pK",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530380 mc_list_config->vdev_id, mc_list_config->psoc, vdev);
381
382 status = pmo_core_cache_mc_addr_list_in_vdev_priv(mc_list_config, vdev);
383dec_ref:
384 pmo_vdev_put_ref(vdev);
385out:
386 PMO_EXIT();
387
388 return status;
389}
390
391QDF_STATUS pmo_core_flush_mc_addr_list(struct wlan_objmgr_psoc *psoc,
392 uint8_t vdev_id)
393{
394 struct wlan_objmgr_vdev *vdev;
395 QDF_STATUS status = QDF_STATUS_SUCCESS;
396
397 PMO_ENTER();
398 if (!psoc) {
399 pmo_err("psoc is NULL");
400 status = QDF_STATUS_E_NULL_VALUE;
401 goto out;
402 }
403
404 vdev = pmo_psoc_get_vdev(psoc, vdev_id);
405 if (!vdev) {
406 pmo_err("vdev is NULL");
407 status = QDF_STATUS_E_NULL_VALUE;
408 goto out;
409 }
410
411 status = pmo_vdev_get_ref(vdev);
412 if (QDF_IS_STATUS_ERROR(status)) {
413 pmo_warn("failed to get vdev reference");
414 status = QDF_STATUS_E_INVAL;
415 goto out;
416 }
417
418 status = pmo_core_mc_addr_flitering_sanity(vdev);
419 if (status != QDF_STATUS_SUCCESS)
420 goto dec_ref;
421
Jeff Johnson0a645382017-09-18 08:17:59 -0700422 pmo_info("Flush mc addr list for vdev id: %d psoc: %pK vdev: %pK",
Mukul Sharmad75a6672017-06-22 15:40:53 +0530423 vdev_id, psoc, vdev);
424
425 status = pmo_core_flush_mc_addr_list_from_vdev_priv(vdev);
426
427dec_ref:
428 pmo_vdev_put_ref(vdev);
429out:
430 PMO_EXIT();
431
432 return status;
433}
434
435static QDF_STATUS pmo_core_handle_enable_mc_list_trigger(
436 struct wlan_objmgr_vdev *vdev,
437 enum pmo_offload_trigger trigger)
438{
439 struct pmo_vdev_priv_obj *vdev_ctx;
440 QDF_STATUS status;
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700441 struct pmo_mc_addr_list *op_mc_list_req;
442
443 PMO_ENTER();
Mukul Sharmad75a6672017-06-22 15:40:53 +0530444
445 vdev_ctx = pmo_vdev_get_priv(vdev);
446
447 op_mc_list_req = qdf_mem_malloc(sizeof(*op_mc_list_req));
448 if (!op_mc_list_req) {
449 pmo_err("op_mc_list_req is NULL");
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700450 status = QDF_STATUS_E_NOMEM;
451 goto exit_with_status;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530452 }
453
454 switch (trigger) {
455 case pmo_mc_list_change_notify:
456 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
457 pmo_info("active offload is disabled, skip in mode: %d",
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700458 trigger);
Mukul Sharmad75a6672017-06-22 15:40:53 +0530459 status = QDF_STATUS_E_INVAL;
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700460 goto free_req;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530461 }
462 status = pmo_core_do_enable_mc_addr_list(vdev, vdev_ctx,
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700463 op_mc_list_req);
Mukul Sharmad75a6672017-06-22 15:40:53 +0530464 break;
465 case pmo_apps_suspend:
466 if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
467 pmo_info("active offload is enabled, skip in mode: %d",
468 trigger);
469 status = QDF_STATUS_E_INVAL;
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700470 goto free_req;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530471 }
472 status = pmo_core_do_enable_mc_addr_list(vdev, vdev_ctx,
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700473 op_mc_list_req);
Mukul Sharmad75a6672017-06-22 15:40:53 +0530474 break;
475 default:
476 status = QDF_STATUS_E_INVAL;
477 pmo_err("invalid pmo trigger for enable mc list");
478 break;
479 }
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700480
481free_req:
482 qdf_mem_free(op_mc_list_req);
483
484exit_with_status:
485 PMO_EXIT();
Mukul Sharmad75a6672017-06-22 15:40:53 +0530486
487 return status;
488}
489
490QDF_STATUS pmo_core_enable_mc_addr_filtering_in_fwr(
491 struct wlan_objmgr_psoc *psoc,
492 uint8_t vdev_id,
493 enum pmo_offload_trigger trigger)
494{
495 QDF_STATUS status;
496 struct wlan_objmgr_vdev *vdev;
497
498 PMO_ENTER();
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700499
500 status = pmo_psoc_get_ref(psoc);
501 if (QDF_IS_STATUS_ERROR(status))
502 goto exit_with_status;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530503
504 vdev = pmo_psoc_get_vdev(psoc, vdev_id);
505 if (!vdev) {
506 pmo_err("vdev is NULL");
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700507 status = QDF_STATUS_E_INVAL;
508 goto put_psoc;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530509 }
510
511 status = pmo_vdev_get_ref(vdev);
512 if (QDF_IS_STATUS_ERROR(status))
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700513 goto put_psoc;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530514
515 status = pmo_core_mc_addr_flitering_sanity(vdev);
516 if (status != QDF_STATUS_SUCCESS)
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700517 goto put_vdev;
Mukul Sharmad75a6672017-06-22 15:40:53 +0530518
519 pmo_info("enable mclist trigger: %d", trigger);
520 status = pmo_core_handle_enable_mc_list_trigger(vdev, trigger);
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700521
522put_vdev:
Mukul Sharmad75a6672017-06-22 15:40:53 +0530523 pmo_vdev_put_ref(vdev);
Dustin Brown8d8d9fe2017-07-18 16:01:25 -0700524
525put_psoc:
526 pmo_psoc_put_ref(psoc);
527
528exit_with_status:
Mukul Sharmad75a6672017-06-22 15:40:53 +0530529 PMO_EXIT();
530
531 return status;
532}
533
534static QDF_STATUS pmo_core_handle_disable_mc_list_trigger(
535 struct wlan_objmgr_vdev *vdev,
536 enum pmo_offload_trigger trigger)
537{
538 struct pmo_vdev_priv_obj *vdev_ctx;
539 QDF_STATUS status;
540 struct pmo_mc_addr_list *op_mc_list_req = NULL;
541
542 vdev_ctx = pmo_vdev_get_priv(vdev);
543
544 op_mc_list_req = qdf_mem_malloc(sizeof(*op_mc_list_req));
545 if (!op_mc_list_req) {
546 pmo_err("op_mc_list_req is NULL");
547 status = QDF_STATUS_E_NULL_VALUE;
548 goto out;
549 }
550
551 switch (trigger) {
552 case pmo_peer_disconnect:
553 case pmo_mc_list_change_notify:
554 if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
555 pmo_info("active offload is disabled, skip in mode: %d",
556 trigger);
557 status = QDF_STATUS_E_INVAL;
558 goto out;
559 }
560 status = pmo_core_do_disable_mc_addr_list(vdev, vdev_ctx,
561 op_mc_list_req);
562 break;
563 case pmo_apps_resume:
564 if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
565 pmo_info("active offload is enabled, skip in mode: %d",
566 trigger);
567 status = QDF_STATUS_E_INVAL;
568 goto out;
569 }
570 status = pmo_core_do_disable_mc_addr_list(vdev, vdev_ctx,
571 op_mc_list_req);
572 break;
573 default:
574 status = QDF_STATUS_E_INVAL;
575 pmo_err("invalid pmo trigger for disable mc list");
576 break;
577 }
578out:
579 if (op_mc_list_req)
580 qdf_mem_free(op_mc_list_req);
581
582 return status;
583}
584
585QDF_STATUS pmo_core_disable_mc_addr_filtering_in_fwr(
586 struct wlan_objmgr_psoc *psoc,
587 uint8_t vdev_id,
588 enum pmo_offload_trigger trigger)
589{
590 QDF_STATUS status;
591 struct wlan_objmgr_vdev *vdev;
592
593 PMO_ENTER();
594 if (!psoc) {
595 pmo_err("psoc is NULL");
596 status = QDF_STATUS_E_NULL_VALUE;
597 goto out;
598 }
599
600 vdev = pmo_psoc_get_vdev(psoc, vdev_id);
601 if (!vdev) {
602 pmo_err("vdev is NULL");
603 status = QDF_STATUS_E_NULL_VALUE;
604 goto out;
605 }
606
607 status = pmo_vdev_get_ref(vdev);
608 if (QDF_IS_STATUS_ERROR(status))
609 goto out;
610
611 status = pmo_core_mc_addr_flitering_sanity(vdev);
612 if (status != QDF_STATUS_SUCCESS)
613 goto dec_ref;
614
615 pmo_info("disable mclist trigger: %d", trigger);
616 status = pmo_core_handle_disable_mc_list_trigger(vdev, trigger);
617dec_ref:
618 pmo_vdev_put_ref(vdev);
619out:
620 PMO_EXIT();
621
622 return status;
623}
624