1 /*
2 * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*============================================================================
21 FILE: cds_reg_service.c
22 OVERVIEW: This source file contains definitions for CDS regulatory APIs
23 DEPENDENCIES: None
24 ============================================================================*/
25
26 #include "qdf_types.h"
27 #include "qdf_trace.h"
28 #include <wlan_objmgr_pdev_obj.h>
29 #include "wlan_reg_services_api.h"
30 #include "cds_reg_service.h"
31 #include "cds_ieee80211_common_i.h"
32 #include "cds_config.h"
33 #include "cds_utils.h"
34 #include "wlan_reg_services_api.h"
35
cds_get_vendor_reg_flags(struct wlan_objmgr_pdev * pdev,qdf_freq_t freq,uint16_t bandwidth,bool is_ht_enabled,bool is_vht_enabled,uint8_t sub_20_channel_width)36 uint32_t cds_get_vendor_reg_flags(struct wlan_objmgr_pdev *pdev,
37 qdf_freq_t freq, uint16_t bandwidth,
38 bool is_ht_enabled, bool is_vht_enabled,
39 uint8_t sub_20_channel_width)
40 {
41 uint32_t flags = 0;
42 enum channel_state state;
43 struct ch_params ch_params;
44 qdf_freq_t sec_freq;
45
46 state = wlan_reg_get_channel_state_for_pwrmode(pdev, freq,
47 REG_CURRENT_PWR_MODE);
48 if (state == CHANNEL_STATE_INVALID)
49 return flags;
50 if (state == CHANNEL_STATE_DFS) {
51 flags |= IEEE80211_CHAN_PASSIVE;
52 }
53 if (state == CHANNEL_STATE_DISABLE)
54 flags |= IEEE80211_CHAN_BLOCKED;
55
56 if (wlan_reg_is_24ghz_ch_freq(freq)) {
57 if ((bandwidth == CH_WIDTH_80P80MHZ) ||
58 (bandwidth == CH_WIDTH_160MHZ) ||
59 (bandwidth == CH_WIDTH_80MHZ)) {
60 bandwidth = CH_WIDTH_40MHZ;
61 }
62 flags |= IEEE80211_CHAN_2GHZ;
63 } else
64 flags |= IEEE80211_CHAN_5GHZ;
65 qdf_mem_zero(&ch_params, sizeof(ch_params));
66
67 switch (bandwidth) {
68 case CH_WIDTH_80P80MHZ:
69 ch_params.ch_width = bandwidth;
70 if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
71 pdev, freq,
72 &ch_params, REG_CURRENT_PWR_MODE) !=
73 CHANNEL_STATE_INVALID) {
74 if (is_vht_enabled)
75 flags |= IEEE80211_CHAN_VHT80_80;
76 }
77 bandwidth = CH_WIDTH_160MHZ;
78 fallthrough;
79 case CH_WIDTH_160MHZ:
80 ch_params.ch_width = bandwidth;
81 if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
82 pdev, freq,
83 &ch_params, REG_CURRENT_PWR_MODE) !=
84 CHANNEL_STATE_INVALID) {
85 if (is_vht_enabled)
86 flags |= IEEE80211_CHAN_VHT160;
87 }
88 bandwidth = CH_WIDTH_80MHZ;
89 fallthrough;
90 case CH_WIDTH_80MHZ:
91 ch_params.ch_width = bandwidth;
92 if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
93 pdev, freq,
94 &ch_params, REG_CURRENT_PWR_MODE) !=
95 CHANNEL_STATE_INVALID) {
96 if (is_vht_enabled)
97 flags |= IEEE80211_CHAN_VHT80;
98 }
99 bandwidth = CH_WIDTH_40MHZ;
100 fallthrough;
101 case CH_WIDTH_40MHZ:
102 qdf_mem_zero(&ch_params, sizeof(ch_params));
103 ch_params.ch_width = bandwidth;
104 wlan_reg_set_channel_params_for_pwrmode(pdev, freq, 0,
105 &ch_params,
106 REG_CURRENT_PWR_MODE);
107
108 if (ch_params.sec_ch_offset == LOW_PRIMARY_CH)
109 sec_freq = freq + 20;
110 else if (ch_params.sec_ch_offset == HIGH_PRIMARY_CH)
111 sec_freq = freq - 20;
112 else
113 sec_freq = 0;
114
115 if (wlan_reg_get_bonded_channel_state_for_pwrmode(
116 pdev, freq,
117 bandwidth, sec_freq,
118 REG_CURRENT_PWR_MODE) !=
119 CHANNEL_STATE_INVALID) {
120 if (ch_params.sec_ch_offset == LOW_PRIMARY_CH) {
121 flags |= IEEE80211_CHAN_HT40PLUS;
122 if (is_vht_enabled)
123 flags |= IEEE80211_CHAN_VHT40PLUS;
124 } else if (ch_params.sec_ch_offset ==
125 HIGH_PRIMARY_CH) {
126 flags |= IEEE80211_CHAN_HT40MINUS;
127 if (is_vht_enabled)
128 flags |= IEEE80211_CHAN_VHT40MINUS;
129 }
130 }
131 bandwidth = CH_WIDTH_20MHZ;
132 fallthrough;
133 case CH_WIDTH_20MHZ:
134 if (is_vht_enabled)
135 flags |= IEEE80211_CHAN_VHT20;
136 if (is_ht_enabled)
137 flags |= IEEE80211_CHAN_HT20;
138 bandwidth = CH_WIDTH_10MHZ;
139 fallthrough;
140 case CH_WIDTH_10MHZ:
141 if (wlan_reg_get_bonded_channel_state_for_pwrmode(
142 pdev, freq,
143 bandwidth, 0,
144 REG_CURRENT_PWR_MODE) !=
145 CHANNEL_STATE_INVALID &&
146 sub_20_channel_width == WLAN_SUB_20_CH_WIDTH_10)
147 flags |= IEEE80211_CHAN_HALF;
148 bandwidth = CH_WIDTH_5MHZ;
149 fallthrough;
150 case CH_WIDTH_5MHZ:
151 if (wlan_reg_get_bonded_channel_state_for_pwrmode(
152 pdev, freq,
153 bandwidth, 0,
154 REG_CURRENT_PWR_MODE) !=
155 CHANNEL_STATE_INVALID &&
156 sub_20_channel_width == WLAN_SUB_20_CH_WIDTH_5)
157 flags |= IEEE80211_CHAN_QUARTER;
158 break;
159 default:
160 cds_info("invalid channel width value %d", bandwidth);
161 }
162
163 return flags;
164 }
165
166