diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-01-06 16:39:27 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-01-10 14:12:57 -0500 |
commit | f39c2bfa9a1e2bae726cce65d2d328652e81f0c2 (patch) | |
tree | e7ec076b7842d20371f217b833c93859b4a76187 /drivers/net/wireless/mac80211_hwsim.c | |
parent | 3a8cc5e73f7105faf32fb8df57ba3e7b967e1982 (diff) |
mac80211_hwsim: refactor radio registration
In order to support dynamic radio registration in the future,
refactor the actual registration into a new function with only
minor cleanups. Since it had to change anyway, also clean up
the init error paths.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 455 |
1 files changed, 225 insertions, 230 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 55cdfd6a40e8..23fa6ee8eefe 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -2122,14 +2122,219 @@ static const struct ieee80211_iface_combination hwsim_if_comb[] = { | |||
2122 | } | 2122 | } |
2123 | }; | 2123 | }; |
2124 | 2124 | ||
2125 | static int __init init_mac80211_hwsim(void) | 2125 | static int __init mac80211_hwsim_create_radio(int idx) |
2126 | { | 2126 | { |
2127 | int i, err = 0; | 2127 | int err; |
2128 | u8 addr[ETH_ALEN]; | 2128 | u8 addr[ETH_ALEN]; |
2129 | struct mac80211_hwsim_data *data; | 2129 | struct mac80211_hwsim_data *data; |
2130 | struct ieee80211_hw *hw; | 2130 | struct ieee80211_hw *hw; |
2131 | enum ieee80211_band band; | 2131 | enum ieee80211_band band; |
2132 | const struct ieee80211_ops *ops; | 2132 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; |
2133 | |||
2134 | if (channels > 1) | ||
2135 | ops = &mac80211_hwsim_mchan_ops; | ||
2136 | hw = ieee80211_alloc_hw(sizeof(*data), ops); | ||
2137 | if (!hw) { | ||
2138 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); | ||
2139 | err = -ENOMEM; | ||
2140 | goto failed; | ||
2141 | } | ||
2142 | data = hw->priv; | ||
2143 | data->hw = hw; | ||
2144 | |||
2145 | data->dev = device_create(hwsim_class, NULL, 0, hw, "hwsim%d", idx); | ||
2146 | if (IS_ERR(data->dev)) { | ||
2147 | printk(KERN_DEBUG | ||
2148 | "mac80211_hwsim: device_create failed (%ld)\n", | ||
2149 | PTR_ERR(data->dev)); | ||
2150 | err = -ENOMEM; | ||
2151 | goto failed_drvdata; | ||
2152 | } | ||
2153 | data->dev->driver = &mac80211_hwsim_driver.driver; | ||
2154 | err = device_bind_driver(data->dev); | ||
2155 | if (err != 0) { | ||
2156 | printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", | ||
2157 | err); | ||
2158 | goto failed_hw; | ||
2159 | } | ||
2160 | |||
2161 | skb_queue_head_init(&data->pending); | ||
2162 | |||
2163 | SET_IEEE80211_DEV(hw, data->dev); | ||
2164 | memset(addr, 0, ETH_ALEN); | ||
2165 | addr[0] = 0x02; | ||
2166 | addr[3] = idx >> 8; | ||
2167 | addr[4] = idx; | ||
2168 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); | ||
2169 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | ||
2170 | data->addresses[1].addr[0] |= 0x40; | ||
2171 | hw->wiphy->n_addresses = 2; | ||
2172 | hw->wiphy->addresses = data->addresses; | ||
2173 | |||
2174 | data->channels = channels; | ||
2175 | |||
2176 | if (data->channels > 1) { | ||
2177 | hw->wiphy->max_scan_ssids = 255; | ||
2178 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
2179 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
2180 | /* For channels > 1 DFS is not allowed */ | ||
2181 | hw->wiphy->n_iface_combinations = 1; | ||
2182 | hw->wiphy->iface_combinations = &data->if_combination; | ||
2183 | data->if_combination = hwsim_if_comb[0]; | ||
2184 | data->if_combination.num_different_channels = data->channels; | ||
2185 | } else { | ||
2186 | hw->wiphy->iface_combinations = hwsim_if_comb; | ||
2187 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); | ||
2188 | } | ||
2189 | |||
2190 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); | ||
2191 | INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work); | ||
2192 | |||
2193 | hw->queues = 5; | ||
2194 | hw->offchannel_tx_hw_queue = 4; | ||
2195 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
2196 | BIT(NL80211_IFTYPE_AP) | | ||
2197 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
2198 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
2199 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2200 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
2201 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
2202 | |||
2203 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | ||
2204 | IEEE80211_HW_SIGNAL_DBM | | ||
2205 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
2206 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2207 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
2208 | IEEE80211_HW_WANT_MONITOR_VIF | | ||
2209 | IEEE80211_HW_QUEUE_CONTROL | | ||
2210 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | ||
2211 | if (rctbl) | ||
2212 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | ||
2213 | |||
2214 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | ||
2215 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
2216 | WIPHY_FLAG_AP_UAPSD; | ||
2217 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | ||
2218 | |||
2219 | /* ask mac80211 to reserve space for magic */ | ||
2220 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | ||
2221 | hw->sta_data_size = sizeof(struct hwsim_sta_priv); | ||
2222 | hw->chanctx_data_size = sizeof(struct hwsim_chanctx_priv); | ||
2223 | |||
2224 | memcpy(data->channels_2ghz, hwsim_channels_2ghz, | ||
2225 | sizeof(hwsim_channels_2ghz)); | ||
2226 | memcpy(data->channels_5ghz, hwsim_channels_5ghz, | ||
2227 | sizeof(hwsim_channels_5ghz)); | ||
2228 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); | ||
2229 | |||
2230 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { | ||
2231 | struct ieee80211_supported_band *sband = &data->bands[band]; | ||
2232 | switch (band) { | ||
2233 | case IEEE80211_BAND_2GHZ: | ||
2234 | sband->channels = data->channels_2ghz; | ||
2235 | sband->n_channels = ARRAY_SIZE(hwsim_channels_2ghz); | ||
2236 | sband->bitrates = data->rates; | ||
2237 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates); | ||
2238 | break; | ||
2239 | case IEEE80211_BAND_5GHZ: | ||
2240 | sband->channels = data->channels_5ghz; | ||
2241 | sband->n_channels = ARRAY_SIZE(hwsim_channels_5ghz); | ||
2242 | sband->bitrates = data->rates + 4; | ||
2243 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; | ||
2244 | break; | ||
2245 | default: | ||
2246 | continue; | ||
2247 | } | ||
2248 | |||
2249 | sband->ht_cap.ht_supported = true; | ||
2250 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
2251 | IEEE80211_HT_CAP_GRN_FLD | | ||
2252 | IEEE80211_HT_CAP_SGI_40 | | ||
2253 | IEEE80211_HT_CAP_DSSSCCK40; | ||
2254 | sband->ht_cap.ampdu_factor = 0x3; | ||
2255 | sband->ht_cap.ampdu_density = 0x6; | ||
2256 | memset(&sband->ht_cap.mcs, 0, | ||
2257 | sizeof(sband->ht_cap.mcs)); | ||
2258 | sband->ht_cap.mcs.rx_mask[0] = 0xff; | ||
2259 | sband->ht_cap.mcs.rx_mask[1] = 0xff; | ||
2260 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
2261 | |||
2262 | hw->wiphy->bands[band] = sband; | ||
2263 | |||
2264 | sband->vht_cap.vht_supported = true; | ||
2265 | sband->vht_cap.cap = | ||
2266 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
2267 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | | ||
2268 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | | ||
2269 | IEEE80211_VHT_CAP_RXLDPC | | ||
2270 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
2271 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
2272 | IEEE80211_VHT_CAP_TXSTBC | | ||
2273 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
2274 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
2275 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
2276 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
2277 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
2278 | sband->vht_cap.vht_mcs.rx_mcs_map = | ||
2279 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 | | ||
2280 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 | | ||
2281 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | | ||
2282 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 | | ||
2283 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 | | ||
2284 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | | ||
2285 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | | ||
2286 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 14); | ||
2287 | sband->vht_cap.vht_mcs.tx_mcs_map = | ||
2288 | sband->vht_cap.vht_mcs.rx_mcs_map; | ||
2289 | } | ||
2290 | |||
2291 | /* By default all radios belong to the first group */ | ||
2292 | data->group = 1; | ||
2293 | mutex_init(&data->mutex); | ||
2294 | |||
2295 | /* Enable frame retransmissions for lossy channels */ | ||
2296 | hw->max_rates = 4; | ||
2297 | hw->max_rate_tries = 11; | ||
2298 | |||
2299 | err = ieee80211_register_hw(hw); | ||
2300 | if (err < 0) { | ||
2301 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | ||
2302 | err); | ||
2303 | goto failed_hw; | ||
2304 | } | ||
2305 | |||
2306 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); | ||
2307 | |||
2308 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); | ||
2309 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); | ||
2310 | debugfs_create_file("group", 0666, data->debugfs, data, | ||
2311 | &hwsim_fops_group); | ||
2312 | if (data->channels == 1) | ||
2313 | debugfs_create_file("dfs_simulate_radar", 0222, | ||
2314 | data->debugfs, | ||
2315 | data, &hwsim_simulate_radar); | ||
2316 | |||
2317 | tasklet_hrtimer_init(&data->beacon_timer, | ||
2318 | mac80211_hwsim_beacon, | ||
2319 | CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); | ||
2320 | |||
2321 | spin_lock_bh(&hwsim_radio_lock); | ||
2322 | list_add_tail(&data->list, &hwsim_radios); | ||
2323 | spin_unlock_bh(&hwsim_radio_lock); | ||
2324 | |||
2325 | return 0; | ||
2326 | |||
2327 | failed_hw: | ||
2328 | device_unregister(data->dev); | ||
2329 | failed_drvdata: | ||
2330 | ieee80211_free_hw(hw); | ||
2331 | failed: | ||
2332 | return err; | ||
2333 | } | ||
2334 | |||
2335 | static int __init init_mac80211_hwsim(void) | ||
2336 | { | ||
2337 | int i, err; | ||
2133 | 2338 | ||
2134 | if (radios < 1 || radios > 100) | 2339 | if (radios < 1 || radios > 100) |
2135 | return -EINVAL; | 2340 | return -EINVAL; |
@@ -2162,256 +2367,46 @@ static int __init init_mac80211_hwsim(void) | |||
2162 | hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); | 2367 | hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); |
2163 | if (IS_ERR(hwsim_class)) { | 2368 | if (IS_ERR(hwsim_class)) { |
2164 | err = PTR_ERR(hwsim_class); | 2369 | err = PTR_ERR(hwsim_class); |
2165 | goto failed_unregister_driver; | 2370 | goto out_unregister_driver; |
2166 | } | 2371 | } |
2167 | 2372 | ||
2168 | memset(addr, 0, ETH_ALEN); | ||
2169 | addr[0] = 0x02; | ||
2170 | |||
2171 | for (i = 0; i < radios; i++) { | 2373 | for (i = 0; i < radios; i++) { |
2172 | printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", | 2374 | err = mac80211_hwsim_create_radio(i); |
2173 | i); | 2375 | if (err) |
2174 | ops = &mac80211_hwsim_ops; | 2376 | goto out_free_radios; |
2175 | if (channels > 1) | ||
2176 | ops = &mac80211_hwsim_mchan_ops; | ||
2177 | hw = ieee80211_alloc_hw(sizeof(*data), ops); | ||
2178 | if (!hw) { | ||
2179 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " | ||
2180 | "failed\n"); | ||
2181 | err = -ENOMEM; | ||
2182 | goto failed; | ||
2183 | } | ||
2184 | data = hw->priv; | ||
2185 | data->hw = hw; | ||
2186 | |||
2187 | data->dev = device_create(hwsim_class, NULL, 0, hw, | ||
2188 | "hwsim%d", i); | ||
2189 | if (IS_ERR(data->dev)) { | ||
2190 | printk(KERN_DEBUG | ||
2191 | "mac80211_hwsim: device_create failed (%ld)\n", | ||
2192 | PTR_ERR(data->dev)); | ||
2193 | err = -ENOMEM; | ||
2194 | goto failed_drvdata; | ||
2195 | } | ||
2196 | data->dev->driver = &mac80211_hwsim_driver.driver; | ||
2197 | err = device_bind_driver(data->dev); | ||
2198 | if (err != 0) { | ||
2199 | printk(KERN_DEBUG | ||
2200 | "mac80211_hwsim: device_bind_driver failed (%d)\n", | ||
2201 | err); | ||
2202 | goto failed_hw; | ||
2203 | } | ||
2204 | |||
2205 | skb_queue_head_init(&data->pending); | ||
2206 | |||
2207 | SET_IEEE80211_DEV(hw, data->dev); | ||
2208 | addr[3] = i >> 8; | ||
2209 | addr[4] = i; | ||
2210 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); | ||
2211 | memcpy(data->addresses[1].addr, addr, ETH_ALEN); | ||
2212 | data->addresses[1].addr[0] |= 0x40; | ||
2213 | hw->wiphy->n_addresses = 2; | ||
2214 | hw->wiphy->addresses = data->addresses; | ||
2215 | |||
2216 | data->channels = channels; | ||
2217 | |||
2218 | if (data->channels > 1) { | ||
2219 | hw->wiphy->max_scan_ssids = 255; | ||
2220 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
2221 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
2222 | /* For channels > 1 DFS is not allowed */ | ||
2223 | hw->wiphy->n_iface_combinations = 1; | ||
2224 | hw->wiphy->iface_combinations = &data->if_combination; | ||
2225 | data->if_combination = hwsim_if_comb[0]; | ||
2226 | data->if_combination.num_different_channels = | ||
2227 | data->channels; | ||
2228 | } else { | ||
2229 | hw->wiphy->iface_combinations = hwsim_if_comb; | ||
2230 | hw->wiphy->n_iface_combinations = | ||
2231 | ARRAY_SIZE(hwsim_if_comb); | ||
2232 | } | ||
2233 | |||
2234 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); | ||
2235 | INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work); | ||
2236 | |||
2237 | hw->queues = 5; | ||
2238 | hw->offchannel_tx_hw_queue = 4; | ||
2239 | hw->wiphy->interface_modes = | ||
2240 | BIT(NL80211_IFTYPE_STATION) | | ||
2241 | BIT(NL80211_IFTYPE_AP) | | ||
2242 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
2243 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
2244 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2245 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
2246 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
2247 | |||
2248 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | ||
2249 | IEEE80211_HW_SIGNAL_DBM | | ||
2250 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
2251 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2252 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
2253 | IEEE80211_HW_WANT_MONITOR_VIF | | ||
2254 | IEEE80211_HW_QUEUE_CONTROL | | ||
2255 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | ||
2256 | if (rctbl) | ||
2257 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | ||
2258 | |||
2259 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | ||
2260 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
2261 | WIPHY_FLAG_AP_UAPSD; | ||
2262 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | ||
2263 | |||
2264 | /* ask mac80211 to reserve space for magic */ | ||
2265 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | ||
2266 | hw->sta_data_size = sizeof(struct hwsim_sta_priv); | ||
2267 | hw->chanctx_data_size = sizeof(struct hwsim_chanctx_priv); | ||
2268 | |||
2269 | memcpy(data->channels_2ghz, hwsim_channels_2ghz, | ||
2270 | sizeof(hwsim_channels_2ghz)); | ||
2271 | memcpy(data->channels_5ghz, hwsim_channels_5ghz, | ||
2272 | sizeof(hwsim_channels_5ghz)); | ||
2273 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); | ||
2274 | |||
2275 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { | ||
2276 | struct ieee80211_supported_band *sband = &data->bands[band]; | ||
2277 | switch (band) { | ||
2278 | case IEEE80211_BAND_2GHZ: | ||
2279 | sband->channels = data->channels_2ghz; | ||
2280 | sband->n_channels = | ||
2281 | ARRAY_SIZE(hwsim_channels_2ghz); | ||
2282 | sband->bitrates = data->rates; | ||
2283 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates); | ||
2284 | break; | ||
2285 | case IEEE80211_BAND_5GHZ: | ||
2286 | sband->channels = data->channels_5ghz; | ||
2287 | sband->n_channels = | ||
2288 | ARRAY_SIZE(hwsim_channels_5ghz); | ||
2289 | sband->bitrates = data->rates + 4; | ||
2290 | sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; | ||
2291 | break; | ||
2292 | default: | ||
2293 | continue; | ||
2294 | } | ||
2295 | |||
2296 | sband->ht_cap.ht_supported = true; | ||
2297 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
2298 | IEEE80211_HT_CAP_GRN_FLD | | ||
2299 | IEEE80211_HT_CAP_SGI_40 | | ||
2300 | IEEE80211_HT_CAP_DSSSCCK40; | ||
2301 | sband->ht_cap.ampdu_factor = 0x3; | ||
2302 | sband->ht_cap.ampdu_density = 0x6; | ||
2303 | memset(&sband->ht_cap.mcs, 0, | ||
2304 | sizeof(sband->ht_cap.mcs)); | ||
2305 | sband->ht_cap.mcs.rx_mask[0] = 0xff; | ||
2306 | sband->ht_cap.mcs.rx_mask[1] = 0xff; | ||
2307 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
2308 | |||
2309 | hw->wiphy->bands[band] = sband; | ||
2310 | |||
2311 | sband->vht_cap.vht_supported = true; | ||
2312 | sband->vht_cap.cap = | ||
2313 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
2314 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | | ||
2315 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | | ||
2316 | IEEE80211_VHT_CAP_RXLDPC | | ||
2317 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
2318 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
2319 | IEEE80211_VHT_CAP_TXSTBC | | ||
2320 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
2321 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
2322 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
2323 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
2324 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
2325 | sband->vht_cap.vht_mcs.rx_mcs_map = | ||
2326 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 | | ||
2327 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 | | ||
2328 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | | ||
2329 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 | | ||
2330 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 | | ||
2331 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | | ||
2332 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | | ||
2333 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 14); | ||
2334 | sband->vht_cap.vht_mcs.tx_mcs_map = | ||
2335 | sband->vht_cap.vht_mcs.rx_mcs_map; | ||
2336 | } | ||
2337 | /* By default all radios are belonging to the first group */ | ||
2338 | data->group = 1; | ||
2339 | mutex_init(&data->mutex); | ||
2340 | |||
2341 | /* Enable frame retransmissions for lossy channels */ | ||
2342 | hw->max_rates = 4; | ||
2343 | hw->max_rate_tries = 11; | ||
2344 | |||
2345 | err = ieee80211_register_hw(hw); | ||
2346 | if (err < 0) { | ||
2347 | printk(KERN_DEBUG "mac80211_hwsim: " | ||
2348 | "ieee80211_register_hw failed (%d)\n", err); | ||
2349 | goto failed_hw; | ||
2350 | } | ||
2351 | |||
2352 | wiphy_debug(hw->wiphy, "hwaddr %pm registered\n", | ||
2353 | hw->wiphy->perm_addr); | ||
2354 | |||
2355 | data->debugfs = debugfs_create_dir("hwsim", | ||
2356 | hw->wiphy->debugfsdir); | ||
2357 | debugfs_create_file("ps", 0666, data->debugfs, data, | ||
2358 | &hwsim_fops_ps); | ||
2359 | debugfs_create_file("group", 0666, data->debugfs, data, | ||
2360 | &hwsim_fops_group); | ||
2361 | if (channels == 1) | ||
2362 | debugfs_create_file("dfs_simulate_radar", 0222, | ||
2363 | data->debugfs, | ||
2364 | data, &hwsim_simulate_radar); | ||
2365 | |||
2366 | tasklet_hrtimer_init(&data->beacon_timer, | ||
2367 | mac80211_hwsim_beacon, | ||
2368 | CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); | ||
2369 | |||
2370 | list_add_tail(&data->list, &hwsim_radios); | ||
2371 | } | 2377 | } |
2372 | 2378 | ||
2373 | hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); | 2379 | hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); |
2374 | if (hwsim_mon == NULL) { | 2380 | if (hwsim_mon == NULL) { |
2375 | err = -ENOMEM; | 2381 | err = -ENOMEM; |
2376 | goto failed; | 2382 | goto out_free_radios; |
2377 | } | 2383 | } |
2378 | 2384 | ||
2379 | rtnl_lock(); | 2385 | rtnl_lock(); |
2380 | |||
2381 | err = dev_alloc_name(hwsim_mon, hwsim_mon->name); | 2386 | err = dev_alloc_name(hwsim_mon, hwsim_mon->name); |
2382 | if (err < 0) | 2387 | if (err < 0) { |
2383 | goto failed_mon; | 2388 | rtnl_unlock(); |
2384 | 2389 | goto out_free_radios; | |
2390 | } | ||
2385 | 2391 | ||
2386 | err = register_netdevice(hwsim_mon); | 2392 | err = register_netdevice(hwsim_mon); |
2387 | if (err < 0) | 2393 | if (err < 0) { |
2388 | goto failed_mon; | 2394 | rtnl_unlock(); |
2389 | 2395 | goto out_free_mon; | |
2396 | } | ||
2390 | rtnl_unlock(); | 2397 | rtnl_unlock(); |
2391 | 2398 | ||
2392 | err = hwsim_init_netlink(); | 2399 | err = hwsim_init_netlink(); |
2393 | if (err < 0) | 2400 | if (err < 0) |
2394 | goto failed_nl; | 2401 | goto out_free_mon; |
2395 | 2402 | ||
2396 | return 0; | 2403 | return 0; |
2397 | 2404 | ||
2398 | failed_nl: | 2405 | out_free_mon: |
2399 | printk(KERN_DEBUG "mac80211_hwsim: failed initializing netlink\n"); | ||
2400 | return err; | ||
2401 | |||
2402 | failed_mon: | ||
2403 | rtnl_unlock(); | ||
2404 | free_netdev(hwsim_mon); | 2406 | free_netdev(hwsim_mon); |
2407 | out_free_radios: | ||
2405 | mac80211_hwsim_free(); | 2408 | mac80211_hwsim_free(); |
2406 | return err; | 2409 | out_unregister_driver: |
2407 | |||
2408 | failed_hw: | ||
2409 | device_unregister(data->dev); | ||
2410 | failed_drvdata: | ||
2411 | ieee80211_free_hw(hw); | ||
2412 | failed: | ||
2413 | mac80211_hwsim_free(); | ||
2414 | failed_unregister_driver: | ||
2415 | platform_driver_unregister(&mac80211_hwsim_driver); | 2410 | platform_driver_unregister(&mac80211_hwsim_driver); |
2416 | return err; | 2411 | return err; |
2417 | } | 2412 | } |