aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-11 18:39:22 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:25 -0400
commit0e057d73eacd952d321d46c7eb972969ec245026 (patch)
treeca20bd3d12e605c63bd5dea9536a73b92b2f06e8 /drivers/net
parent25d834e16294c8dfd923dae6bdb8a055391a99a5 (diff)
mac80211 hwsim: make radio list dynamic
This paves the way for dynamic radio additions while the module is loaded. Also restrict the number of radios to 100 because creating that many already takes forever. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-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();