diff options
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.h | 11 |
2 files changed, 65 insertions, 6 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 5bad3d4ccdba..056dae73b25c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -273,7 +273,7 @@ struct mac80211_hwsim_data { | |||
273 | struct ieee80211_iface_combination if_combination; | 273 | struct ieee80211_iface_combination if_combination; |
274 | 274 | ||
275 | struct mac_address addresses[2]; | 275 | struct mac_address addresses[2]; |
276 | int channels; | 276 | int channels, idx; |
277 | 277 | ||
278 | struct ieee80211_channel *tmp_chan; | 278 | struct ieee80211_channel *tmp_chan; |
279 | struct delayed_work roc_done; | 279 | struct delayed_work roc_done; |
@@ -352,6 +352,8 @@ static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | |||
352 | .len = IEEE80211_TX_MAX_RATES * | 352 | .len = IEEE80211_TX_MAX_RATES * |
353 | sizeof(struct hwsim_tx_rate)}, | 353 | sizeof(struct hwsim_tx_rate)}, |
354 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, | 354 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, |
355 | [HWSIM_ATTR_CHANNELS] = { .type = NLA_U32 }, | ||
356 | [HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 }, | ||
355 | }; | 357 | }; |
356 | 358 | ||
357 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 359 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
@@ -1818,7 +1820,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = { | |||
1818 | 1820 | ||
1819 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; | 1821 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; |
1820 | 1822 | ||
1821 | static int __init mac80211_hwsim_create_radio(void) | 1823 | static int mac80211_hwsim_create_radio(int channels) |
1822 | { | 1824 | { |
1823 | int err; | 1825 | int err; |
1824 | u8 addr[ETH_ALEN]; | 1826 | u8 addr[ETH_ALEN]; |
@@ -1873,6 +1875,7 @@ static int __init mac80211_hwsim_create_radio(void) | |||
1873 | hw->wiphy->addresses = data->addresses; | 1875 | hw->wiphy->addresses = data->addresses; |
1874 | 1876 | ||
1875 | data->channels = channels; | 1877 | data->channels = channels; |
1878 | data->idx = idx; | ||
1876 | 1879 | ||
1877 | if (data->channels > 1) { | 1880 | if (data->channels > 1) { |
1878 | hw->wiphy->max_scan_ssids = 255; | 1881 | hw->wiphy->max_scan_ssids = 255; |
@@ -2023,7 +2026,7 @@ static int __init mac80211_hwsim_create_radio(void) | |||
2023 | list_add_tail(&data->list, &hwsim_radios); | 2026 | list_add_tail(&data->list, &hwsim_radios); |
2024 | spin_unlock_bh(&hwsim_radio_lock); | 2027 | spin_unlock_bh(&hwsim_radio_lock); |
2025 | 2028 | ||
2026 | return 0; | 2029 | return idx; |
2027 | 2030 | ||
2028 | failed_hw: | 2031 | failed_hw: |
2029 | device_unregister(data->dev); | 2032 | device_unregister(data->dev); |
@@ -2270,6 +2273,39 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, | |||
2270 | return 0; | 2273 | return 0; |
2271 | } | 2274 | } |
2272 | 2275 | ||
2276 | static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | ||
2277 | { | ||
2278 | unsigned int chans = channels; | ||
2279 | |||
2280 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | ||
2281 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); | ||
2282 | |||
2283 | return mac80211_hwsim_create_radio(chans); | ||
2284 | } | ||
2285 | |||
2286 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | ||
2287 | { | ||
2288 | struct mac80211_hwsim_data *data; | ||
2289 | int idx; | ||
2290 | |||
2291 | if (!info->attrs[HWSIM_ATTR_RADIO_ID]) | ||
2292 | return -EINVAL; | ||
2293 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2294 | |||
2295 | spin_lock_bh(&hwsim_radio_lock); | ||
2296 | list_for_each_entry(data, &hwsim_radios, list) { | ||
2297 | if (data->idx != idx) | ||
2298 | continue; | ||
2299 | list_del(&data->list); | ||
2300 | spin_unlock_bh(&hwsim_radio_lock); | ||
2301 | mac80211_hwsim_destroy_radio(data); | ||
2302 | return 0; | ||
2303 | } | ||
2304 | spin_unlock_bh(&hwsim_radio_lock); | ||
2305 | |||
2306 | return -ENODEV; | ||
2307 | } | ||
2308 | |||
2273 | /* Generic Netlink operations array */ | 2309 | /* Generic Netlink operations array */ |
2274 | static const struct genl_ops hwsim_ops[] = { | 2310 | static const struct genl_ops hwsim_ops[] = { |
2275 | { | 2311 | { |
@@ -2288,6 +2324,18 @@ static const struct genl_ops hwsim_ops[] = { | |||
2288 | .policy = hwsim_genl_policy, | 2324 | .policy = hwsim_genl_policy, |
2289 | .doit = hwsim_tx_info_frame_received_nl, | 2325 | .doit = hwsim_tx_info_frame_received_nl, |
2290 | }, | 2326 | }, |
2327 | { | ||
2328 | .cmd = HWSIM_CMD_CREATE_RADIO, | ||
2329 | .policy = hwsim_genl_policy, | ||
2330 | .doit = hwsim_create_radio_nl, | ||
2331 | .flags = GENL_ADMIN_PERM, | ||
2332 | }, | ||
2333 | { | ||
2334 | .cmd = HWSIM_CMD_DESTROY_RADIO, | ||
2335 | .policy = hwsim_genl_policy, | ||
2336 | .doit = hwsim_destroy_radio_nl, | ||
2337 | .flags = GENL_ADMIN_PERM, | ||
2338 | }, | ||
2291 | }; | 2339 | }; |
2292 | 2340 | ||
2293 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | 2341 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, |
@@ -2345,7 +2393,7 @@ static int __init init_mac80211_hwsim(void) | |||
2345 | { | 2393 | { |
2346 | int i, err; | 2394 | int i, err; |
2347 | 2395 | ||
2348 | if (radios < 1 || radios > 100) | 2396 | if (radios < 0 || radios > 100) |
2349 | return -EINVAL; | 2397 | return -EINVAL; |
2350 | 2398 | ||
2351 | if (channels < 1) | 2399 | if (channels < 1) |
@@ -2380,8 +2428,8 @@ static int __init init_mac80211_hwsim(void) | |||
2380 | } | 2428 | } |
2381 | 2429 | ||
2382 | for (i = 0; i < radios; i++) { | 2430 | for (i = 0; i < radios; i++) { |
2383 | err = mac80211_hwsim_create_radio(); | 2431 | err = mac80211_hwsim_create_radio(channels); |
2384 | if (err) | 2432 | if (err < 0) |
2385 | goto out_free_radios; | 2433 | goto out_free_radios; |
2386 | } | 2434 | } |
2387 | 2435 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index afaad5a443b6..fb9920a99396 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -65,6 +65,9 @@ enum hwsim_tx_control_flags { | |||
65 | * kernel, uses: | 65 | * kernel, uses: |
66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, | 66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, |
67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE | 67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE |
68 | * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters, | ||
69 | * returns the radio ID (>= 0) or negative on errors | ||
70 | * @HWSIM_CMD_DESTROY_RADIO: destroy a radio | ||
68 | * @__HWSIM_CMD_MAX: enum limit | 71 | * @__HWSIM_CMD_MAX: enum limit |
69 | */ | 72 | */ |
70 | enum { | 73 | enum { |
@@ -72,6 +75,8 @@ enum { | |||
72 | HWSIM_CMD_REGISTER, | 75 | HWSIM_CMD_REGISTER, |
73 | HWSIM_CMD_FRAME, | 76 | HWSIM_CMD_FRAME, |
74 | HWSIM_CMD_TX_INFO_FRAME, | 77 | HWSIM_CMD_TX_INFO_FRAME, |
78 | HWSIM_CMD_CREATE_RADIO, | ||
79 | HWSIM_CMD_DESTROY_RADIO, | ||
75 | __HWSIM_CMD_MAX, | 80 | __HWSIM_CMD_MAX, |
76 | }; | 81 | }; |
77 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) | 82 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) |
@@ -94,6 +99,10 @@ enum { | |||
94 | space | 99 | space |
95 | * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array | 100 | * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array |
96 | * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame | 101 | * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame |
102 | * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO | ||
103 | * command giving the number of channels supported by the new radio | ||
104 | * @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO | ||
105 | * only to destroy a radio | ||
97 | * @__HWSIM_ATTR_MAX: enum limit | 106 | * @__HWSIM_ATTR_MAX: enum limit |
98 | */ | 107 | */ |
99 | 108 | ||
@@ -108,6 +117,8 @@ enum { | |||
108 | HWSIM_ATTR_SIGNAL, | 117 | HWSIM_ATTR_SIGNAL, |
109 | HWSIM_ATTR_TX_INFO, | 118 | HWSIM_ATTR_TX_INFO, |
110 | HWSIM_ATTR_COOKIE, | 119 | HWSIM_ATTR_COOKIE, |
120 | HWSIM_ATTR_CHANNELS, | ||
121 | HWSIM_ATTR_RADIO_ID, | ||
111 | __HWSIM_ATTR_MAX, | 122 | __HWSIM_ATTR_MAX, |
112 | }; | 123 | }; |
113 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 124 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |