1 /*
2 * Copyright (c) 2011, 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 *
6 * Permission to use, copy, modify, and/or distribute this software for
7 * any purpose with or without fee is hereby granted, provided that the
8 * above copyright notice and this permission notice appear in all
9 * copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18 * PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 #include <os_if_spectral_netlink.h>
22 #include <wlan_cfg80211_spectral.h>
23 #include <spectral_cmn_api_i.h>
24 #include <spectral_defs_i.h>
25 #include <wlan_nlink_srv.h>
26 #include <wlan_nlink_common.h>
27 #include <qdf_module.h>
28 #ifdef CNSS_GENL
29 #ifdef CONFIG_CNSS_OUT_OF_TREE
30 #include "cnss_nl.h"
31 #else
32 #include <net/cnss_nl.h>
33 #endif
34 #endif
35 #include <wlan_cfg80211.h>
36
37 /**
38 * os_if_spectral_remove_nbuf_debug_entry() - Remove nbuf from nbuf debug table
39 * @nbuf: nbuf to remove from the nbuf debug table
40 *
41 * Remove nbuf from the nbuf debug hash table and decrement the nbuf count
42 *
43 * Return: None
44 */
os_if_spectral_remove_nbuf_debug_entry(qdf_nbuf_t nbuf)45 static inline void os_if_spectral_remove_nbuf_debug_entry(qdf_nbuf_t nbuf)
46 {
47 qdf_nbuf_count_dec(nbuf);
48 qdf_net_buf_debug_release_skb(nbuf);
49 }
50
51 #ifndef CNSS_GENL
52 static struct sock *os_if_spectral_nl_sock;
53 static atomic_t spectral_nl_users = ATOMIC_INIT(0);
54 #endif
55
56 #if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
57 void
os_if_spectral_nl_data_ready(struct sock * sk,int len)58 os_if_spectral_nl_data_ready(struct sock *sk, int len)
59 {
60 spectral_debug("%d", __LINE__);
61 }
62
63 #else
64 void
os_if_spectral_nl_data_ready(struct sk_buff * skb)65 os_if_spectral_nl_data_ready(struct sk_buff *skb)
66 {
67 spectral_debug("%d", __LINE__);
68 }
69 #endif /* VERSION */
70
71 #ifndef CNSS_GENL
72 /**
73 * os_if_spectral_init_nl_cfg() - Initialize netlink kernel
74 * configuration parameters
75 * @cfg : Pointer to netlink_kernel_cfg
76 *
77 * Initialize netlink kernel configuration parameters required
78 * for spectral module
79 *
80 * Return: None
81 */
82 #if KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
83 static void
os_if_spectral_init_nl_cfg(struct netlink_kernel_cfg * cfg)84 os_if_spectral_init_nl_cfg(struct netlink_kernel_cfg *cfg)
85 {
86 cfg->groups = 1;
87 cfg->input = os_if_spectral_nl_data_ready;
88 }
89 #else
90 static void
os_if_spectral_init_nl_cfg(struct netlink_kernel_cfg * cfg)91 os_if_spectral_init_nl_cfg(struct netlink_kernel_cfg *cfg)
92 {
93 }
94 #endif
95 /**
96 * os_if_spectral_create_nl_sock() - Create Netlink socket
97 * @cfg : Pointer to netlink_kernel_cfg
98 *
99 * Create Netlink socket required for spectral module
100 *
101 * Return: None
102 */
103 #if KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE
104 static void
os_if_spectral_create_nl_sock(struct netlink_kernel_cfg * cfg)105 os_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
106 {
107 os_if_spectral_nl_sock =
108 (struct sock *)netlink_kernel_create(&init_net,
109 SPECTRAL_NETLINK, cfg);
110 }
111 #elif KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
112 static void
os_if_spectral_create_nl_sock(struct netlink_kernel_cfg * cfg)113 os_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
114 {
115 os_if_spectral_nl_sock =
116 (struct sock *)netlink_kernel_create(&init_net,
117 SPECTRAL_NETLINK,
118 THIS_MODULE, cfg);
119 }
120 #elif (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
121 static void
os_if_spectral_create_nl_sock(struct netlink_kernel_cfg * cfg)122 os_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
123 {
124 os_if_spectral_nl_sock =
125 (struct sock *)netlink_kernel_create(
126 SPECTRAL_NETLINK, 1,
127 &os_if_spectral_nl_data_ready,
128 THIS_MODULE);
129 }
130 #else
131 #if (KERNEL_VERSION(3, 10, 0) <= LINUX_VERSION_CODE)
132 static void
os_if_spectral_create_nl_sock(struct netlink_kernel_cfg * cfg)133 os_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
134 {
135 memset(cfg, 0, sizeof(*cfg));
136 cfg->groups = 1;
137 cfg->input = &os_if_spectral_nl_data_ready;
138 os_if_spectral_nl_sock =
139 (struct sock *)netlink_kernel_create(&init_net,
140 SPECTRAL_NETLINK, cfg);
141 }
142 #else
143 static void
os_if_spectral_create_nl_sock(struct netlink_kernel_cfg * cfg)144 os_if_spectral_create_nl_sock(struct netlink_kernel_cfg *cfg)
145 {
146 os_if_spectral_nl_sock =
147 (struct sock *)netlink_kernel_create(
148 &init_net,
149 SPECTRAL_NETLINK, 1,
150 &os_if_spectral_nl_data_ready,
151 NULL, THIS_MODULE);
152 }
153 #endif
154 #endif
155
156 /**
157 * os_if_spectral_init_nl() - Initialize netlink data structures for
158 * spectral module
159 * @pdev : Pointer to pdev
160 *
161 * Return: 0 on success else failure
162 */
163 static int
os_if_spectral_init_nl(struct wlan_objmgr_pdev * pdev)164 os_if_spectral_init_nl(struct wlan_objmgr_pdev *pdev)
165 {
166 struct pdev_spectral *ps = NULL;
167 struct netlink_kernel_cfg cfg;
168
169 memset(&cfg, 0, sizeof(cfg));
170 if (!pdev) {
171 osif_err("PDEV is NULL!");
172 return -EINVAL;
173 }
174 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
175 WLAN_UMAC_COMP_SPECTRAL);
176
177 if (!ps) {
178 osif_err("PDEV SPECTRAL object is NULL!");
179 return -EINVAL;
180 }
181 os_if_spectral_init_nl_cfg(&cfg);
182
183 if (!os_if_spectral_nl_sock) {
184 os_if_spectral_create_nl_sock(&cfg);
185
186 if (!os_if_spectral_nl_sock) {
187 osif_err("NETLINK_KERNEL_CREATE FAILED");
188 return -ENODEV;
189 }
190 }
191 ps->spectral_sock = os_if_spectral_nl_sock;
192
193 if (!ps->spectral_sock) {
194 osif_err("ps->spectral_sock is NULL");
195 return -ENODEV;
196 }
197 atomic_inc(&spectral_nl_users);
198
199 return 0;
200 }
201
202 /**
203 * os_if_spectral_destroy_netlink() - De-initialize netlink data structures for
204 * spectral module
205 * @pdev : Pointer to pdev
206 *
207 * Return: Success/Failure
208 */
209 static int
os_if_spectral_destroy_netlink(struct wlan_objmgr_pdev * pdev)210 os_if_spectral_destroy_netlink(struct wlan_objmgr_pdev *pdev)
211 {
212 struct pdev_spectral *ps = NULL;
213
214 if (!pdev) {
215 osif_err("PDEV is NULL!");
216 return -EINVAL;
217 }
218 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
219 WLAN_UMAC_COMP_SPECTRAL);
220
221 if (!ps) {
222 osif_err("PDEV SPECTRAL object is NULL!");
223 return -EINVAL;
224 }
225 ps->spectral_sock = NULL;
226 if (atomic_dec_and_test(&spectral_nl_users)) {
227 sock_release(os_if_spectral_nl_sock->sk_socket);
228 os_if_spectral_nl_sock = NULL;
229 }
230 return 0;
231 }
232 #else
233
234 static int
os_if_spectral_init_nl(struct wlan_objmgr_pdev * pdev)235 os_if_spectral_init_nl(struct wlan_objmgr_pdev *pdev)
236 {
237 return 0;
238 }
239
240 static int
os_if_spectral_destroy_netlink(struct wlan_objmgr_pdev * pdev)241 os_if_spectral_destroy_netlink(struct wlan_objmgr_pdev *pdev)
242 {
243 return 0;
244 }
245 #endif
246
247 void *
os_if_spectral_prep_skb(struct wlan_objmgr_pdev * pdev,enum spectral_msg_type smsg_type,enum spectral_msg_buf_type buf_type)248 os_if_spectral_prep_skb(struct wlan_objmgr_pdev *pdev,
249 enum spectral_msg_type smsg_type,
250 enum spectral_msg_buf_type buf_type)
251 {
252 struct pdev_spectral *ps = NULL;
253 struct nlmsghdr *spectral_nlh = NULL;
254 void *buf = NULL;
255
256 if (!pdev) {
257 osif_err("PDEV is NULL!");
258 return NULL;
259 }
260
261 if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) {
262 osif_err("Invalid Spectral message type %u", smsg_type);
263 return NULL;
264 }
265
266 if (buf_type >= SPECTRAL_MSG_BUF_TYPE_MAX) {
267 osif_err("Invalid Spectral message buffer type %u",
268 buf_type);
269 return NULL;
270 }
271
272 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
273 WLAN_UMAC_COMP_SPECTRAL);
274
275 if (!ps) {
276 osif_err("PDEV SPECTRAL object is NULL!");
277 return NULL;
278 }
279
280 if (buf_type == SPECTRAL_MSG_BUF_NEW) {
281 QDF_ASSERT(!ps->skb[smsg_type]);
282 ps->skb[smsg_type] =
283 qdf_nbuf_alloc(NULL, MAX_SPECTRAL_PAYLOAD,
284 0, 0, false);
285
286 if (!ps->skb[smsg_type]) {
287 osif_err("alloc skb (len=%u, msg_type=%u) failed",
288 MAX_SPECTRAL_PAYLOAD, smsg_type);
289 return NULL;
290 }
291
292 qdf_nbuf_put_tail(ps->skb[smsg_type], MAX_SPECTRAL_PAYLOAD);
293 spectral_nlh = (struct nlmsghdr *)ps->skb[smsg_type]->data;
294
295 qdf_mem_zero(spectral_nlh, sizeof(*spectral_nlh));
296
297 /*
298 * Possible bug that size of struct spectral_samp_msg and
299 * SPECTRAL_MSG differ by 3 bytes so we miss 3 bytes
300 */
301
302 spectral_nlh->nlmsg_len =
303 NLMSG_SPACE(sizeof(struct spectral_samp_msg));
304 spectral_nlh->nlmsg_pid = 0;
305 spectral_nlh->nlmsg_flags = 0;
306 spectral_nlh->nlmsg_type = WLAN_NL_MSG_SPECTRAL_SCAN;
307
308 qdf_mem_zero(NLMSG_DATA(spectral_nlh),
309 sizeof(struct spectral_samp_msg));
310 buf = NLMSG_DATA(spectral_nlh);
311 } else if (buf_type == SPECTRAL_MSG_BUF_SAVED) {
312 QDF_ASSERT(ps->skb[smsg_type]);
313 spectral_nlh = (struct nlmsghdr *)ps->skb[smsg_type]->data;
314 buf = NLMSG_DATA(spectral_nlh);
315 } else {
316 osif_err("Failed to get spectral report buffer");
317 buf = NULL;
318 }
319
320 return buf;
321 }
322
323 #if (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
324 static inline void
os_if_init_spectral_skb_dst_pid(struct sk_buff * skb,struct pdev_spectral * ps)325 os_if_init_spectral_skb_dst_pid(
326 struct sk_buff *skb,
327 struct pdev_spectral *ps)
328 {
329 NETLINK_CB(skb).dst_pid =
330 ps->spectral_pid;
331 }
332 #else
333 static inline void
os_if_init_spectral_skb_dst_pid(struct sk_buff * skb,struct pdev_spectral * ps)334 os_if_init_spectral_skb_dst_pid(
335 struct sk_buff *skb,
336 struct pdev_spectral *ps)
337 {
338 }
339 #endif /* VERSION - field deprecated by newer kernels */
340
341 #if KERNEL_VERSION(3, 7, 0) > LINUX_VERSION_CODE
342 static inline void
os_if_init_spectral_skb_pid_portid(struct sk_buff * skb)343 os_if_init_spectral_skb_pid_portid(struct sk_buff *skb)
344 {
345 NETLINK_CB(skb).pid = 0; /* from kernel */
346 }
347 #else
348 static inline void
os_if_init_spectral_skb_pid_portid(struct sk_buff * skb)349 os_if_init_spectral_skb_pid_portid(struct sk_buff *skb)
350 {
351 NETLINK_CB(skb).portid = 0; /* from kernel */
352 }
353 #endif
354
355
356 /**
357 * os_if_spectral_nl_unicast_msg() - Sends unicast Spectral message to user
358 * space
359 * @pdev : Pointer to pdev
360 * @smsg_type: Spectral message type
361 *
362 * Return: void
363 */
364 #ifndef CNSS_GENL
365 static int
os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev * pdev,enum spectral_msg_type smsg_type)366 os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev,
367 enum spectral_msg_type smsg_type)
368 {
369 struct pdev_spectral *ps = NULL;
370 int status;
371
372 if (!pdev) {
373 osif_err("PDEV is NULL!");
374 return -EINVAL;
375 }
376
377 if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) {
378 osif_err("Invalid Spectral message type %u", smsg_type);
379 return -EINVAL;
380 }
381
382 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
383 WLAN_UMAC_COMP_SPECTRAL);
384 if (!ps) {
385 osif_err("PDEV SPECTRAL object is NULL!");
386 return -EINVAL;
387 }
388
389 if (!ps->skb[smsg_type]) {
390 osif_err("Socket buffer is null, msg_type= %u", smsg_type);
391 return -EINVAL;
392 }
393
394 if (!ps->spectral_sock) {
395 osif_err("Spectral Socket is invalid, msg_type= %u",
396 smsg_type);
397 qdf_nbuf_free(ps->skb[smsg_type]);
398 ps->skb[smsg_type] = NULL;
399
400 return -EINVAL;
401 }
402
403 os_if_init_spectral_skb_dst_pid(ps->skb[smsg_type], ps);
404
405 os_if_init_spectral_skb_pid_portid(ps->skb[smsg_type]);
406
407 /* to mcast group 1<<0 */
408 NETLINK_CB(ps->skb[smsg_type]).dst_group = 0;
409
410 os_if_spectral_remove_nbuf_debug_entry(ps->skb[smsg_type]);
411 status = netlink_unicast(ps->spectral_sock,
412 ps->skb[smsg_type],
413 ps->spectral_pid, MSG_DONTWAIT);
414
415 /* clear the local copy, free would be done by netlink layer */
416 ps->skb[smsg_type] = NULL;
417
418 return status;
419 }
420 #else
421
422 static int
os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev * pdev,enum spectral_msg_type smsg_type)423 os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev,
424 enum spectral_msg_type smsg_type)
425 {
426 struct pdev_spectral *ps = NULL;
427 int status;
428
429 if (!pdev) {
430 osif_err("PDEV is NULL!");
431 return -EINVAL;
432 }
433
434 if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) {
435 osif_err("Invalid Spectral message type %u", smsg_type);
436 return -EINVAL;
437 }
438
439 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
440 WLAN_UMAC_COMP_SPECTRAL);
441 if (!ps) {
442 osif_err("PDEV SPECTRAL object is NULL!");
443 return -EINVAL;
444 }
445
446 if (!ps->skb[smsg_type]) {
447 osif_err("Socket buffer is null, msg_type= %u", smsg_type);
448 return -EINVAL;
449 }
450
451 os_if_init_spectral_skb_pid_portid(ps->skb[smsg_type]);
452
453 os_if_spectral_remove_nbuf_debug_entry(ps->skb[smsg_type]);
454 status = nl_srv_ucast(ps->skb[smsg_type], ps->spectral_pid,
455 MSG_DONTWAIT, WLAN_NL_MSG_SPECTRAL_SCAN,
456 CLD80211_MCGRP_OEM_MSGS);
457 if (status < 0)
458 osif_err("failed to send to spectral scan app");
459
460 /* clear the local copy, free would be done by netlink layer */
461 ps->skb[smsg_type] = NULL;
462
463 return status;
464 }
465
466 #endif
467
468 /**
469 * os_if_spectral_nl_bcast_msg() - Sends broadcast Spectral message to user
470 * space
471 * @pdev : Pointer to pdev
472 * @smsg_type: Spectral message type
473 *
474 * Return: void
475 */
476 static int
os_if_spectral_nl_bcast_msg(struct wlan_objmgr_pdev * pdev,enum spectral_msg_type smsg_type)477 os_if_spectral_nl_bcast_msg(struct wlan_objmgr_pdev *pdev,
478 enum spectral_msg_type smsg_type)
479 {
480 #if (KERNEL_VERSION(2, 6, 31) >= LINUX_VERSION_CODE)
481 fd_set write_set;
482 #endif
483 int status;
484 struct pdev_spectral *ps = NULL;
485
486 #if (KERNEL_VERSION(2, 6, 31) >= LINUX_VERSION_CODE)
487 FD_ZERO(&write_set);
488 #endif
489
490 if (!pdev) {
491 osif_err("PDEV is NULL!");
492 return -EINVAL;
493 }
494
495 if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) {
496 osif_err("Invalid Spectral message type %u", smsg_type);
497 return -EINVAL;
498 }
499
500 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
501 WLAN_UMAC_COMP_SPECTRAL);
502
503 if (!ps) {
504 osif_err("PDEV SPECTRAL object is NULL!");
505 return -EINVAL;
506 }
507
508 if (!ps->skb[smsg_type]) {
509 osif_err("Socket buffer is null, msg_type= %u", smsg_type);
510 return -EINVAL;
511 }
512
513 if (!ps->spectral_sock) {
514 qdf_nbuf_free(ps->skb[smsg_type]);
515 ps->skb[smsg_type] = NULL;
516
517 return -EINVAL;
518 }
519
520 os_if_spectral_remove_nbuf_debug_entry(ps->skb[smsg_type]);
521 status = netlink_broadcast(ps->spectral_sock,
522 ps->skb[smsg_type],
523 0, 1, GFP_ATOMIC);
524
525 /* clear the local copy, free would be done by netlink layer */
526 ps->skb[smsg_type] = NULL;
527
528 return status;
529 }
530
531 /**
532 * os_if_spectral_free_skb() - Free spectral SAMP message skb
533 *
534 * @pdev : Pointer to pdev
535 * @smsg_type: Spectral message type
536 *
537 * Return: void
538 */
539 static void
os_if_spectral_free_skb(struct wlan_objmgr_pdev * pdev,enum spectral_msg_type smsg_type)540 os_if_spectral_free_skb(struct wlan_objmgr_pdev *pdev,
541 enum spectral_msg_type smsg_type)
542 {
543 struct pdev_spectral *ps = NULL;
544
545 if (!pdev) {
546 osif_err("PDEV is NULL!");
547 return;
548 }
549
550 if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) {
551 osif_err("Invalid Spectral message type %u", smsg_type);
552 return;
553 }
554
555 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
556 WLAN_UMAC_COMP_SPECTRAL);
557
558 if (!ps) {
559 osif_err("PDEV SPECTRAL object is NULL!");
560 return;
561 }
562
563 if (!ps->skb[smsg_type]) {
564 osif_info("Socket buffer is null, msg_type= %u", smsg_type);
565 return;
566 }
567
568 /* Free buffer */
569 qdf_nbuf_free(ps->skb[smsg_type]);
570
571 /* clear the local copy */
572 ps->skb[smsg_type] = NULL;
573 }
574
575 void
os_if_spectral_netlink_init(struct wlan_objmgr_pdev * pdev)576 os_if_spectral_netlink_init(struct wlan_objmgr_pdev *pdev)
577 {
578 struct spectral_nl_cb nl_cb = {0};
579 struct spectral_context *sptrl_ctx;
580
581 if (!pdev) {
582 osif_err("PDEV is NULL!");
583 return;
584 }
585
586 if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
587 osif_debug("Spectral feature is disabled");
588 return;
589 }
590
591 sptrl_ctx = spectral_get_spectral_ctx_from_pdev(pdev);
592
593 if (!sptrl_ctx) {
594 osif_err("Spectral context is NULL!");
595 return;
596 }
597
598 os_if_spectral_init_nl(pdev);
599
600 /* Register Netlink handlers */
601 nl_cb.get_sbuff = os_if_spectral_prep_skb;
602 nl_cb.send_nl_bcast = os_if_spectral_nl_bcast_msg;
603 nl_cb.send_nl_unicast = os_if_spectral_nl_unicast_msg;
604 nl_cb.free_sbuff = os_if_spectral_free_skb;
605 nl_cb.convert_to_phy_ch_width = wlan_spectral_get_phy_ch_width;
606 nl_cb.convert_to_nl_ch_width = wlan_spectral_get_nl80211_chwidth;
607
608 if (sptrl_ctx->sptrlc_register_netlink_cb)
609 sptrl_ctx->sptrlc_register_netlink_cb(pdev, &nl_cb);
610 }
611 qdf_export_symbol(os_if_spectral_netlink_init);
612
os_if_spectral_netlink_deinit(struct wlan_objmgr_pdev * pdev)613 void os_if_spectral_netlink_deinit(struct wlan_objmgr_pdev *pdev)
614 {
615 struct spectral_context *sptrl_ctx;
616 enum spectral_msg_type msg_type = SPECTRAL_MSG_NORMAL_MODE;
617
618 if (!pdev) {
619 osif_err("PDEV is NULL!");
620 return;
621 }
622
623 if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
624 osif_err("Spectral feature is disabled");
625 return;
626 }
627
628 sptrl_ctx = spectral_get_spectral_ctx_from_pdev(pdev);
629
630 if (!sptrl_ctx) {
631 osif_err("Spectral context is NULL!");
632 return;
633 }
634
635 for (; msg_type < SPECTRAL_MSG_TYPE_MAX; msg_type++)
636 os_if_spectral_free_skb(pdev, msg_type);
637
638 if (sptrl_ctx->sptrlc_deregister_netlink_cb)
639 sptrl_ctx->sptrlc_deregister_netlink_cb(pdev);
640
641 os_if_spectral_destroy_netlink(pdev);
642 }
643 qdf_export_symbol(os_if_spectral_netlink_deinit);
644