aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c86
1 files changed, 45 insertions, 41 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 631d65b73edf..c9e4a435b2fc 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -14,6 +14,8 @@
14 * - RX filtering based on filter configuration (data->rx_filter) 14 * - RX filtering based on filter configuration (data->rx_filter)
15 */ 15 */
16 16
17#include <linux/list.h>
18#include <linux/spinlock.h>
17#include <net/mac80211.h> 19#include <net/mac80211.h>
18#include <net/ieee80211_radiotap.h> 20#include <net/ieee80211_radiotap.h>
19#include <linux/if_arp.h> 21#include <linux/if_arp.h>
@@ -78,8 +80,6 @@ static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
78 80
79static struct class *hwsim_class; 81static struct class *hwsim_class;
80 82
81static struct ieee80211_hw **hwsim_radios;
82static int hwsim_radio_count;
83static struct net_device *hwsim_mon; /* global monitor netdev */ 83static struct net_device *hwsim_mon; /* global monitor netdev */
84 84
85 85
@@ -115,7 +115,12 @@ static const struct ieee80211_rate hwsim_rates[] = {
115 { .bitrate = 540 } 115 { .bitrate = 540 }
116}; 116};
117 117
118static spinlock_t hwsim_radio_lock;
119static struct list_head hwsim_radios;
120
118struct mac80211_hwsim_data { 121struct mac80211_hwsim_data {
122 struct list_head list;
123 struct ieee80211_hw *hw;
119 struct device *dev; 124 struct device *dev;
120 struct ieee80211_supported_band band; 125 struct ieee80211_supported_band band;
121 struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)]; 126 struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)];
@@ -191,11 +196,11 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
191} 196}
192 197
193 198
194static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, 199static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
195 struct sk_buff *skb) 200 struct sk_buff *skb)
196{ 201{
197 struct mac80211_hwsim_data *data = hw->priv; 202 struct mac80211_hwsim_data *data = hw->priv, *data2;
198 int i, ack = 0; 203 bool ack = false;
199 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 204 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
200 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 205 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
201 struct ieee80211_rx_status rx_status; 206 struct ieee80211_rx_status rx_status;
@@ -208,13 +213,13 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
208 /* TODO: simulate signal strength (and optional packet drop) */ 213 /* TODO: simulate signal strength (and optional packet drop) */
209 214
210 /* Copy skb to all enabled radios that are on the current frequency */ 215 /* Copy skb to all enabled radios that are on the current frequency */
211 for (i = 0; i < hwsim_radio_count; i++) { 216 spin_lock(&hwsim_radio_lock);
212 struct mac80211_hwsim_data *data2; 217 list_for_each_entry(data2, &hwsim_radios, list) {
213 struct sk_buff *nskb; 218 struct sk_buff *nskb;
214 219
215 if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw) 220 if (data == data2)
216 continue; 221 continue;
217 data2 = hwsim_radios[i]->priv; 222
218 if (!data2->started || !data2->radio_enabled || 223 if (!data2->started || !data2->radio_enabled ||
219 data->channel->center_freq != data2->channel->center_freq) 224 data->channel->center_freq != data2->channel->center_freq)
220 continue; 225 continue;
@@ -223,11 +228,12 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
223 if (nskb == NULL) 228 if (nskb == NULL)
224 continue; 229 continue;
225 230
226 if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr, 231 if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
227 ETH_ALEN) == 0) 232 ETH_ALEN) == 0)
228 ack = 1; 233 ack = true;
229 ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status); 234 ieee80211_rx_irqsafe(data2->hw, nskb, &rx_status);
230 } 235 }
236 spin_unlock(&hwsim_radio_lock);
231 237
232 return ack; 238 return ack;
233} 239}
@@ -236,7 +242,7 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
236static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 242static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
237{ 243{
238 struct mac80211_hwsim_data *data = hw->priv; 244 struct mac80211_hwsim_data *data = hw->priv;
239 int ack; 245 bool ack;
240 struct ieee80211_tx_info *txi; 246 struct ieee80211_tx_info *txi;
241 247
242 mac80211_hwsim_monitor_rx(hw, skb); 248 mac80211_hwsim_monitor_rx(hw, skb);
@@ -457,18 +463,21 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
457 463
458static void mac80211_hwsim_free(void) 464static void mac80211_hwsim_free(void)
459{ 465{
460 int i; 466 struct list_head tmplist, *i, *tmp;
461 467 struct mac80211_hwsim_data *data;
462 for (i = 0; i < hwsim_radio_count; i++) { 468
463 if (hwsim_radios[i]) { 469 INIT_LIST_HEAD(&tmplist);
464 struct mac80211_hwsim_data *data; 470
465 data = hwsim_radios[i]->priv; 471 spin_lock_bh(&hwsim_radio_lock);
466 ieee80211_unregister_hw(hwsim_radios[i]); 472 list_for_each_safe(i, tmp, &hwsim_radios)
467 device_unregister(data->dev); 473 list_move(i, &tmplist);
468 ieee80211_free_hw(hwsim_radios[i]); 474 spin_unlock_bh(&hwsim_radio_lock);
469 } 475
476 list_for_each_entry(data, &tmplist, list) {
477 ieee80211_unregister_hw(data->hw);
478 device_unregister(data->dev);
479 ieee80211_free_hw(data->hw);
470 } 480 }
471 kfree(hwsim_radios);
472 class_destroy(hwsim_class); 481 class_destroy(hwsim_class);
473} 482}
474 483
@@ -498,37 +507,32 @@ static int __init init_mac80211_hwsim(void)
498 struct ieee80211_hw *hw; 507 struct ieee80211_hw *hw;
499 DECLARE_MAC_BUF(mac); 508 DECLARE_MAC_BUF(mac);
500 509
501 if (radios < 1 || radios > 65535) 510 if (radios < 1 || radios > 100)
502 return -EINVAL; 511 return -EINVAL;
503 512
504 hwsim_radio_count = radios; 513 spin_lock_init(&hwsim_radio_lock);
505 hwsim_radios = kcalloc(hwsim_radio_count, 514 INIT_LIST_HEAD(&hwsim_radios);
506 sizeof(struct ieee80211_hw *), GFP_KERNEL);
507 if (hwsim_radios == NULL)
508 return -ENOMEM;
509 515
510 hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); 516 hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
511 if (IS_ERR(hwsim_class)) { 517 if (IS_ERR(hwsim_class))
512 kfree(hwsim_radios);
513 return PTR_ERR(hwsim_class); 518 return PTR_ERR(hwsim_class);
514 }
515 519
516 memset(addr, 0, ETH_ALEN); 520 memset(addr, 0, ETH_ALEN);
517 addr[0] = 0x02; 521 addr[0] = 0x02;
518 522
519 for (i = 0; i < hwsim_radio_count; i++) { 523 for (i = 0; i < radios; i++) {
520 printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", 524 printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
521 i); 525 i);
522 hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); 526 hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops);
523 if (hw == NULL) { 527 if (!hw) {
524 printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " 528 printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
525 "failed\n"); 529 "failed\n");
526 err = -ENOMEM; 530 err = -ENOMEM;
527 goto failed; 531 goto failed;
528 } 532 }
529 hwsim_radios[i] = hw;
530
531 data = hw->priv; 533 data = hw->priv;
534 data->hw = hw;
535
532 data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw, 536 data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw,
533 "hwsim%d", i); 537 "hwsim%d", i);
534 if (IS_ERR(data->dev)) { 538 if (IS_ERR(data->dev)) {
@@ -590,6 +594,8 @@ static int __init init_mac80211_hwsim(void)
590 594
591 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, 595 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
592 (unsigned long) hw); 596 (unsigned long) hw);
597
598 list_add_tail(&data->list, &hwsim_radios);
593 } 599 }
594 600
595 hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); 601 hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
@@ -621,7 +627,6 @@ failed_hw:
621 device_unregister(data->dev); 627 device_unregister(data->dev);
622failed_drvdata: 628failed_drvdata:
623 ieee80211_free_hw(hw); 629 ieee80211_free_hw(hw);
624 hwsim_radios[i] = NULL;
625failed: 630failed:
626 mac80211_hwsim_free(); 631 mac80211_hwsim_free();
627 return err; 632 return err;
@@ -630,8 +635,7 @@ failed:
630 635
631static void __exit exit_mac80211_hwsim(void) 636static void __exit exit_mac80211_hwsim(void)
632{ 637{
633 printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n", 638 printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
634 hwsim_radio_count);
635 639
636 unregister_netdev(hwsim_mon); 640 unregister_netdev(hwsim_mon);
637 mac80211_hwsim_free(); 641 mac80211_hwsim_free();