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