1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2009-2010  Realtek Corporation.
5  *
6  *****************************************************************************/
7 
8 #include <drv_types.h>
9 #include <rtw_debug.h>
10 
11 #include <rtw_wifi_regd.h>
12 
13 /*
14  * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
15  */
16 
17 /*
18  * Only these channels all allow active
19  * scan on all world regulatory domains
20  */
21 
22 /* 2G chan 01 - chan 11 */
23 #define RTW_2GHZ_CH01_11	\
24 	REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0)
25 
26 /*
27  * We enable active scan on these a case
28  * by case basis by regulatory domain
29  */
30 
31 /* 2G chan 12 - chan 13, PASSIV SCAN */
32 #define RTW_2GHZ_CH12_13	\
33 	REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20,	\
34 	NL80211_RRF_PASSIVE_SCAN)
35 
36 static const struct ieee80211_regdomain rtw_regdom_rd = {
37 	.n_reg_rules = 2,
38 	.alpha2 = "99",
39 	.reg_rules = {
40 		RTW_2GHZ_CH01_11,
41 		RTW_2GHZ_CH12_13,
42 	}
43 };
44 
45 static int rtw_ieee80211_channel_to_frequency(int chan, int band)
46 {
47 	/* see 802.11 17.3.8.3.2 and Annex J
48 	 * there are overlapping channel numbers in 5GHz and 2GHz bands
49 	 */
50 
51 	/* NL80211_BAND_2GHZ */
52 	if (chan == 14)
53 		return 2484;
54 	else if (chan < 14)
55 		return 2407 + chan * 5;
56 	else
57 		return 0;	/* not supported */
58 }
59 
60 static void _rtw_reg_apply_flags(struct wiphy *wiphy)
61 {
62 	struct adapter *padapter = wiphy_to_adapter(wiphy);
63 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
64 	RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
65 	u8 max_chan_nums = pmlmeext->max_chan_nums;
66 
67 	struct ieee80211_supported_band *sband;
68 	struct ieee80211_channel *ch;
69 	unsigned int i, j;
70 	u16 channel;
71 	u32 freq;
72 
73 	/* all channels disable */
74 	for (i = 0; i < NUM_NL80211_BANDS; i++) {
75 		sband = wiphy->bands[i];
76 
77 		if (sband) {
78 			for (j = 0; j < sband->n_channels; j++) {
79 				ch = &sband->channels[j];
80 
81 				if (ch)
82 					ch->flags = IEEE80211_CHAN_DISABLED;
83 			}
84 		}
85 	}
86 
87 	/* channels apply by channel plans. */
88 	for (i = 0; i < max_chan_nums; i++) {
89 		channel = channel_set[i].ChannelNum;
90 		freq =
91 		    rtw_ieee80211_channel_to_frequency(channel,
92 						       NL80211_BAND_2GHZ);
93 
94 		ch = ieee80211_get_channel(wiphy, freq);
95 		if (ch) {
96 			if (channel_set[i].ScanType == SCAN_PASSIVE)
97 				ch->flags = IEEE80211_CHAN_NO_IR;
98 			else
99 				ch->flags = 0;
100 		}
101 	}
102 }
103 
104 static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
105 				   struct regulatory_request *request,
106 				   struct rtw_regulatory *reg)
107 {
108 	/* Hard code flags */
109 	_rtw_reg_apply_flags(wiphy);
110 	return 0;
111 }
112 
113 static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
114 							       rtw_regulatory
115 							       *reg)
116 {
117 	return &rtw_regdom_rd;
118 }
119 
120 static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg,
121 				 struct wiphy *wiphy,
122 				 void (*reg_notifier)(struct wiphy *wiphy,
123 						      struct
124 						      regulatory_request *
125 						      request))
126 {
127 	const struct ieee80211_regdomain *regd;
128 
129 	wiphy->reg_notifier = reg_notifier;
130 
131 	wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
132 	wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
133 	wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
134 
135 	regd = _rtw_regdomain_select(reg);
136 	wiphy_apply_custom_regulatory(wiphy, regd);
137 
138 	/* Hard code flags */
139 	_rtw_reg_apply_flags(wiphy);
140 }
141 
142 void rtw_regd_init(struct wiphy *wiphy,
143 		   void (*reg_notifier)(struct wiphy *wiphy,
144 					struct regulatory_request *request))
145 {
146 	_rtw_regd_init_wiphy(NULL, wiphy, reg_notifier);
147 }
148 
149 void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
150 {
151 	struct rtw_regulatory *reg = NULL;
152 
153 	DBG_8192C("%s\n", __func__);
154 
155 	_rtw_reg_notifier_apply(wiphy, request, reg);
156 }
157