blob: a7a0ffa2c18ecbb684e78c49b4b5fd239aa27079 [file] [log] [blame]
Yuanyuan Liuca3c6372017-05-09 17:13:35 -07001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Yuanyuan Liu607051c2016-11-28 17:04:13 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/slab.h>
15
16#define ICNSS_MAX_CH_NUM 45
17
18static DEFINE_MUTEX(unsafe_channel_list_lock);
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070019static DEFINE_SPINLOCK(dfs_nol_info_lock);
Yuanyuan Liu607051c2016-11-28 17:04:13 -080020
21static struct icnss_unsafe_channel_list {
22 u16 unsafe_ch_count;
23 u16 unsafe_ch_list[ICNSS_MAX_CH_NUM];
24} unsafe_channel_list;
25
26static struct icnss_dfs_nol_info {
27 void *dfs_nol_info;
28 u16 dfs_nol_info_len;
29} dfs_nol_info;
30
31int icnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count)
32{
33 mutex_lock(&unsafe_channel_list_lock);
34 if ((!unsafe_ch_list) || (ch_count > ICNSS_MAX_CH_NUM)) {
35 mutex_unlock(&unsafe_channel_list_lock);
36 return -EINVAL;
37 }
38
39 unsafe_channel_list.unsafe_ch_count = ch_count;
40
41 if (ch_count != 0) {
42 memcpy(
43 (char *)unsafe_channel_list.unsafe_ch_list,
44 (char *)unsafe_ch_list, ch_count * sizeof(u16));
45 }
46 mutex_unlock(&unsafe_channel_list_lock);
47
48 return 0;
49}
50EXPORT_SYMBOL(icnss_set_wlan_unsafe_channel);
51
52int icnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list,
53 u16 *ch_count, u16 buf_len)
54{
55 mutex_lock(&unsafe_channel_list_lock);
56 if (!unsafe_ch_list || !ch_count) {
57 mutex_unlock(&unsafe_channel_list_lock);
58 return -EINVAL;
59 }
60
61 if (buf_len < (unsafe_channel_list.unsafe_ch_count * sizeof(u16))) {
62 mutex_unlock(&unsafe_channel_list_lock);
63 return -ENOMEM;
64 }
65
66 *ch_count = unsafe_channel_list.unsafe_ch_count;
67 memcpy(
68 (char *)unsafe_ch_list,
69 (char *)unsafe_channel_list.unsafe_ch_list,
70 unsafe_channel_list.unsafe_ch_count * sizeof(u16));
71 mutex_unlock(&unsafe_channel_list_lock);
72
73 return 0;
74}
75EXPORT_SYMBOL(icnss_get_wlan_unsafe_channel);
76
77int icnss_wlan_set_dfs_nol(const void *info, u16 info_len)
78{
79 void *temp;
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070080 void *old_nol_info;
Yuanyuan Liu607051c2016-11-28 17:04:13 -080081 struct icnss_dfs_nol_info *dfs_info;
82
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070083 if (!info || !info_len)
Yuanyuan Liu607051c2016-11-28 17:04:13 -080084 return -EINVAL;
Yuanyuan Liu607051c2016-11-28 17:04:13 -080085
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070086 temp = kmalloc(info_len, GFP_ATOMIC);
87 if (!temp)
Yuanyuan Liu607051c2016-11-28 17:04:13 -080088 return -ENOMEM;
Yuanyuan Liu607051c2016-11-28 17:04:13 -080089
90 memcpy(temp, info, info_len);
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070091 spin_lock_bh(&dfs_nol_info_lock);
Yuanyuan Liu607051c2016-11-28 17:04:13 -080092 dfs_info = &dfs_nol_info;
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070093 old_nol_info = dfs_info->dfs_nol_info;
Yuanyuan Liu607051c2016-11-28 17:04:13 -080094 dfs_info->dfs_nol_info = temp;
95 dfs_info->dfs_nol_info_len = info_len;
Yuanyuan Liuca3c6372017-05-09 17:13:35 -070096 spin_unlock_bh(&dfs_nol_info_lock);
97 kfree(old_nol_info);
Yuanyuan Liu607051c2016-11-28 17:04:13 -080098
99 return 0;
100}
101EXPORT_SYMBOL(icnss_wlan_set_dfs_nol);
102
103int icnss_wlan_get_dfs_nol(void *info, u16 info_len)
104{
105 int len;
106 struct icnss_dfs_nol_info *dfs_info;
107
Yuanyuan Liuca3c6372017-05-09 17:13:35 -0700108 if (!info || !info_len)
Yuanyuan Liu607051c2016-11-28 17:04:13 -0800109 return -EINVAL;
Yuanyuan Liuca3c6372017-05-09 17:13:35 -0700110
111 spin_lock_bh(&dfs_nol_info_lock);
Yuanyuan Liu607051c2016-11-28 17:04:13 -0800112
113 dfs_info = &dfs_nol_info;
Yuanyuan Liu607051c2016-11-28 17:04:13 -0800114 if (dfs_info->dfs_nol_info == NULL ||
115 dfs_info->dfs_nol_info_len == 0) {
Yuanyuan Liuca3c6372017-05-09 17:13:35 -0700116 spin_unlock_bh(&dfs_nol_info_lock);
Yuanyuan Liu607051c2016-11-28 17:04:13 -0800117 return -ENOENT;
118 }
119
120 len = min(info_len, dfs_info->dfs_nol_info_len);
Yuanyuan Liu607051c2016-11-28 17:04:13 -0800121 memcpy(info, dfs_info->dfs_nol_info, len);
Yuanyuan Liuca3c6372017-05-09 17:13:35 -0700122 spin_unlock_bh(&dfs_nol_info_lock);
Yuanyuan Liu607051c2016-11-28 17:04:13 -0800123
124 return len;
125}
126EXPORT_SYMBOL(icnss_wlan_get_dfs_nol);