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 | /* NL80211_BAND_2GHZ */ |
48 | if (chan == 14) |
49 | return 2484; |
50 | else if (chan < 14) |
51 | return 2407 + chan * 5; |
52 | else |
53 | return 0; /* not supported */ |
54 | } |
55 | |
56 | static void _rtw_reg_apply_flags(struct wiphy *wiphy) |
57 | { |
58 | struct adapter *padapter = wiphy_to_adapter(wiphy); |
59 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
60 | struct rt_channel_info *channel_set = pmlmeext->channel_set; |
61 | u8 max_chan_nums = pmlmeext->max_chan_nums; |
62 | |
63 | struct ieee80211_supported_band *sband; |
64 | struct ieee80211_channel *ch; |
65 | unsigned int i, j; |
66 | u16 channel; |
67 | u32 freq; |
68 | |
69 | /* all channels disable */ |
70 | for (i = 0; i < NUM_NL80211_BANDS; i++) { |
71 | sband = wiphy->bands[i]; |
72 | |
73 | if (sband) { |
74 | for (j = 0; j < sband->n_channels; j++) { |
75 | ch = &sband->channels[j]; |
76 | |
77 | if (ch) |
78 | ch->flags = IEEE80211_CHAN_DISABLED; |
79 | } |
80 | } |
81 | } |
82 | |
83 | /* channels apply by channel plans. */ |
84 | for (i = 0; i < max_chan_nums; i++) { |
85 | channel = channel_set[i].ChannelNum; |
86 | freq = |
87 | rtw_ieee80211_channel_to_frequency(chan: channel, |
88 | band: NL80211_BAND_2GHZ); |
89 | |
90 | ch = ieee80211_get_channel(wiphy, freq); |
91 | if (ch) { |
92 | if (channel_set[i].ScanType == SCAN_PASSIVE) |
93 | ch->flags = IEEE80211_CHAN_NO_IR; |
94 | else |
95 | ch->flags = 0; |
96 | } |
97 | } |
98 | } |
99 | |
100 | static int _rtw_reg_notifier_apply(struct wiphy *wiphy, |
101 | struct regulatory_request *request, |
102 | struct rtw_regulatory *reg) |
103 | { |
104 | /* Hard code flags */ |
105 | _rtw_reg_apply_flags(wiphy); |
106 | return 0; |
107 | } |
108 | |
109 | static const struct ieee80211_regdomain *_rtw_regdomain_select(struct |
110 | rtw_regulatory |
111 | *reg) |
112 | { |
113 | return &rtw_regdom_rd; |
114 | } |
115 | |
116 | static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg, |
117 | struct wiphy *wiphy, |
118 | void (*reg_notifier)(struct wiphy *wiphy, |
119 | struct |
120 | regulatory_request * |
121 | request)) |
122 | { |
123 | const struct ieee80211_regdomain *regd; |
124 | |
125 | wiphy->reg_notifier = reg_notifier; |
126 | |
127 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
128 | wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; |
129 | wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; |
130 | |
131 | regd = _rtw_regdomain_select(reg); |
132 | wiphy_apply_custom_regulatory(wiphy, regd); |
133 | |
134 | /* Hard code flags */ |
135 | _rtw_reg_apply_flags(wiphy); |
136 | } |
137 | |
138 | void rtw_regd_init(struct wiphy *wiphy, |
139 | void (*reg_notifier)(struct wiphy *wiphy, |
140 | struct regulatory_request *request)) |
141 | { |
142 | _rtw_regd_init_wiphy(NULL, wiphy, reg_notifier); |
143 | } |
144 | |
145 | void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) |
146 | { |
147 | struct rtw_regulatory *reg = NULL; |
148 | |
149 | _rtw_reg_notifier_apply(wiphy, request, reg); |
150 | } |
151 | |