aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mac80211_hwsim.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c177
1 files changed, 130 insertions, 47 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index ff9085502bea..b73e497fe770 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -48,6 +48,10 @@ static int channels = 1;
48module_param(channels, int, 0444); 48module_param(channels, int, 0444);
49MODULE_PARM_DESC(channels, "Number of concurrent channels"); 49MODULE_PARM_DESC(channels, "Number of concurrent channels");
50 50
51static bool paged_rx = false;
52module_param(paged_rx, bool, 0644);
53MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones");
54
51/** 55/**
52 * enum hwsim_regtest - the type of regulatory tests we offer 56 * enum hwsim_regtest - the type of regulatory tests we offer
53 * 57 *
@@ -333,11 +337,11 @@ struct mac80211_hwsim_data {
333 int scan_chan_idx; 337 int scan_chan_idx;
334 338
335 struct ieee80211_channel *channel; 339 struct ieee80211_channel *channel;
336 unsigned long beacon_int; /* in jiffies unit */ 340 u64 beacon_int /* beacon interval in us */;
337 unsigned int rx_filter; 341 unsigned int rx_filter;
338 bool started, idle, scanning; 342 bool started, idle, scanning;
339 struct mutex mutex; 343 struct mutex mutex;
340 struct timer_list beacon_timer; 344 struct tasklet_hrtimer beacon_timer;
341 enum ps_mode { 345 enum ps_mode {
342 PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL 346 PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
343 } ps; 347 } ps;
@@ -357,7 +361,10 @@ struct mac80211_hwsim_data {
357 int power_level; 361 int power_level;
358 362
359 /* difference between this hw's clock and the real clock, in usecs */ 363 /* difference between this hw's clock and the real clock, in usecs */
360 u64 tsf_offset; 364 s64 tsf_offset;
365 s64 bcn_delta;
366 /* absolute beacon transmission time. Used to cover up "tx" delay. */
367 u64 abs_bcn_ts;
361}; 368};
362 369
363 370
@@ -405,15 +412,19 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
405 return NETDEV_TX_OK; 412 return NETDEV_TX_OK;
406} 413}
407 414
415static inline u64 mac80211_hwsim_get_tsf_raw(void)
416{
417 return ktime_to_us(ktime_get_real());
418}
419
408static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) 420static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
409{ 421{
410 struct timeval tv = ktime_to_timeval(ktime_get_real()); 422 u64 now = mac80211_hwsim_get_tsf_raw();
411 u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
412 return cpu_to_le64(now + data->tsf_offset); 423 return cpu_to_le64(now + data->tsf_offset);
413} 424}
414 425
415static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, 426static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
416 struct ieee80211_vif *vif) 427 struct ieee80211_vif *vif)
417{ 428{
418 struct mac80211_hwsim_data *data = hw->priv; 429 struct mac80211_hwsim_data *data = hw->priv;
419 return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); 430 return le64_to_cpu(__mac80211_hwsim_get_tsf(data));
@@ -423,9 +434,13 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
423 struct ieee80211_vif *vif, u64 tsf) 434 struct ieee80211_vif *vif, u64 tsf)
424{ 435{
425 struct mac80211_hwsim_data *data = hw->priv; 436 struct mac80211_hwsim_data *data = hw->priv;
426 struct timeval tv = ktime_to_timeval(ktime_get_real()); 437 u64 now = mac80211_hwsim_get_tsf(hw, vif);
427 u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; 438 u32 bcn_int = data->beacon_int;
428 data->tsf_offset = tsf - now; 439 s64 delta = tsf - now;
440
441 data->tsf_offset += delta;
442 /* adjust after beaconing with new timestamp at old TBTT */
443 data->bcn_delta = do_div(delta, bcn_int);
429} 444}
430 445
431static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, 446static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
@@ -696,7 +711,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
696 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 711 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
697 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 712 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
698 struct ieee80211_rx_status rx_status; 713 struct ieee80211_rx_status rx_status;
699 struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); 714 u64 now;
700 715
701 memset(&rx_status, 0, sizeof(rx_status)); 716 memset(&rx_status, 0, sizeof(rx_status));
702 rx_status.flag |= RX_FLAG_MACTIME_START; 717 rx_status.flag |= RX_FLAG_MACTIME_START;
@@ -722,11 +737,23 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
722 secpath_reset(skb); 737 secpath_reset(skb);
723 nf_reset(skb); 738 nf_reset(skb);
724 739
740 /*
741 * Get absolute mactime here so all HWs RX at the "same time", and
742 * absolute TX time for beacon mactime so the timestamp matches.
743 * Giving beacons a different mactime than non-beacons looks messy, but
744 * it helps the Toffset be exact and a ~10us mactime discrepancy
745 * probably doesn't really matter.
746 */
747 if (ieee80211_is_beacon(hdr->frame_control) ||
748 ieee80211_is_probe_resp(hdr->frame_control))
749 now = data->abs_bcn_ts;
750 else
751 now = mac80211_hwsim_get_tsf_raw();
752
725 /* Copy skb to all enabled radios that are on the current frequency */ 753 /* Copy skb to all enabled radios that are on the current frequency */
726 spin_lock(&hwsim_radio_lock); 754 spin_lock(&hwsim_radio_lock);
727 list_for_each_entry(data2, &hwsim_radios, list) { 755 list_for_each_entry(data2, &hwsim_radios, list) {
728 struct sk_buff *nskb; 756 struct sk_buff *nskb;
729 struct ieee80211_mgmt *mgmt;
730 struct tx_iter_data tx_iter_data = { 757 struct tx_iter_data tx_iter_data = {
731 .receive = false, 758 .receive = false,
732 .channel = chan, 759 .channel = chan,
@@ -755,24 +782,30 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
755 * reserve some space for our vendor and the normal 782 * reserve some space for our vendor and the normal
756 * radiotap header, since we're copying anyway 783 * radiotap header, since we're copying anyway
757 */ 784 */
758 nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC); 785 if (skb->len < PAGE_SIZE && paged_rx) {
759 if (nskb == NULL) 786 struct page *page = alloc_page(GFP_ATOMIC);
760 continue; 787
788 if (!page)
789 continue;
790
791 nskb = dev_alloc_skb(128);
792 if (!nskb) {
793 __free_page(page);
794 continue;
795 }
796
797 memcpy(page_address(page), skb->data, skb->len);
798 skb_add_rx_frag(nskb, 0, page, 0, skb->len, skb->len);
799 } else {
800 nskb = skb_copy(skb, GFP_ATOMIC);
801 if (!nskb)
802 continue;
803 }
761 804
762 if (mac80211_hwsim_addr_match(data2, hdr->addr1)) 805 if (mac80211_hwsim_addr_match(data2, hdr->addr1))
763 ack = true; 806 ack = true;
764 807
765 /* set bcn timestamp relative to receiver mactime */ 808 rx_status.mactime = now + data2->tsf_offset;
766 rx_status.mactime =
767 le64_to_cpu(__mac80211_hwsim_get_tsf(data2));
768 mgmt = (struct ieee80211_mgmt *) nskb->data;
769 if (ieee80211_is_beacon(mgmt->frame_control) ||
770 ieee80211_is_probe_resp(mgmt->frame_control))
771 mgmt->u.beacon.timestamp = cpu_to_le64(
772 rx_status.mactime +
773 (data->tsf_offset - data2->tsf_offset) +
774 24 * 8 * 10 / txrate->bitrate);
775
776#if 0 809#if 0
777 /* 810 /*
778 * Don't enable this code by default as the OUI 00:00:00 811 * Don't enable this code by default as the OUI 00:00:00
@@ -896,7 +929,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
896{ 929{
897 struct mac80211_hwsim_data *data = hw->priv; 930 struct mac80211_hwsim_data *data = hw->priv;
898 data->started = false; 931 data->started = false;
899 del_timer(&data->beacon_timer); 932 tasklet_hrtimer_cancel(&data->beacon_timer);
900 wiphy_debug(hw->wiphy, "%s\n", __func__); 933 wiphy_debug(hw->wiphy, "%s\n", __func__);
901} 934}
902 935
@@ -962,7 +995,11 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
962static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, 995static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
963 struct ieee80211_vif *vif) 996 struct ieee80211_vif *vif)
964{ 997{
965 struct ieee80211_hw *hw = arg; 998 struct mac80211_hwsim_data *data = arg;
999 struct ieee80211_hw *hw = data->hw;
1000 struct ieee80211_tx_info *info;
1001 struct ieee80211_rate *txrate;
1002 struct ieee80211_mgmt *mgmt;
966 struct sk_buff *skb; 1003 struct sk_buff *skb;
967 1004
968 hwsim_check_magic(vif); 1005 hwsim_check_magic(vif);
@@ -975,26 +1012,48 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
975 skb = ieee80211_beacon_get(hw, vif); 1012 skb = ieee80211_beacon_get(hw, vif);
976 if (skb == NULL) 1013 if (skb == NULL)
977 return; 1014 return;
1015 info = IEEE80211_SKB_CB(skb);
1016 txrate = ieee80211_get_tx_rate(hw, info);
1017
1018 mgmt = (struct ieee80211_mgmt *) skb->data;
1019 /* fake header transmission time */
1020 data->abs_bcn_ts = mac80211_hwsim_get_tsf_raw();
1021 mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts +
1022 data->tsf_offset +
1023 24 * 8 * 10 / txrate->bitrate);
978 1024
979 mac80211_hwsim_tx_frame(hw, skb, 1025 mac80211_hwsim_tx_frame(hw, skb,
980 rcu_dereference(vif->chanctx_conf)->def.chan); 1026 rcu_dereference(vif->chanctx_conf)->def.chan);
981} 1027}
982 1028
983 1029static enum hrtimer_restart
984static void mac80211_hwsim_beacon(unsigned long arg) 1030mac80211_hwsim_beacon(struct hrtimer *timer)
985{ 1031{
986 struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; 1032 struct mac80211_hwsim_data *data =
987 struct mac80211_hwsim_data *data = hw->priv; 1033 container_of(timer, struct mac80211_hwsim_data,
1034 beacon_timer.timer);
1035 struct ieee80211_hw *hw = data->hw;
1036 u64 bcn_int = data->beacon_int;
1037 ktime_t next_bcn;
988 1038
989 if (!data->started) 1039 if (!data->started)
990 return; 1040 goto out;
991 1041
992 ieee80211_iterate_active_interfaces_atomic( 1042 ieee80211_iterate_active_interfaces_atomic(
993 hw, IEEE80211_IFACE_ITER_NORMAL, 1043 hw, IEEE80211_IFACE_ITER_NORMAL,
994 mac80211_hwsim_beacon_tx, hw); 1044 mac80211_hwsim_beacon_tx, data);
1045
1046 /* beacon at new TBTT + beacon interval */
1047 if (data->bcn_delta) {
1048 bcn_int -= data->bcn_delta;
1049 data->bcn_delta = 0;
1050 }
995 1051
996 data->beacon_timer.expires = jiffies + data->beacon_int; 1052 next_bcn = ktime_add(hrtimer_get_expires(timer),
997 add_timer(&data->beacon_timer); 1053 ns_to_ktime(bcn_int * 1000));
1054 tasklet_hrtimer_start(&data->beacon_timer, next_bcn, HRTIMER_MODE_ABS);
1055out:
1056 return HRTIMER_NORESTART;
998} 1057}
999 1058
1000static const char *hwsim_chantypes[] = { 1059static const char *hwsim_chantypes[] = {
@@ -1032,9 +1091,16 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
1032 1091
1033 data->power_level = conf->power_level; 1092 data->power_level = conf->power_level;
1034 if (!data->started || !data->beacon_int) 1093 if (!data->started || !data->beacon_int)
1035 del_timer(&data->beacon_timer); 1094 tasklet_hrtimer_cancel(&data->beacon_timer);
1036 else 1095 else if (!hrtimer_is_queued(&data->beacon_timer.timer)) {
1037 mod_timer(&data->beacon_timer, jiffies + data->beacon_int); 1096 u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
1097 u32 bcn_int = data->beacon_int;
1098 u64 until_tbtt = bcn_int - do_div(tsf, bcn_int);
1099
1100 tasklet_hrtimer_start(&data->beacon_timer,
1101 ns_to_ktime(until_tbtt * 1000),
1102 HRTIMER_MODE_REL);
1103 }
1038 1104
1039 return 0; 1105 return 0;
1040} 1106}
@@ -1084,12 +1150,26 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
1084 1150
1085 if (changed & BSS_CHANGED_BEACON_INT) { 1151 if (changed & BSS_CHANGED_BEACON_INT) {
1086 wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int); 1152 wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int);
1087 data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; 1153 data->beacon_int = info->beacon_int * 1024;
1088 if (WARN_ON(!data->beacon_int)) 1154 }
1089 data->beacon_int = 1; 1155
1090 if (data->started) 1156 if (changed & BSS_CHANGED_BEACON_ENABLED) {
1091 mod_timer(&data->beacon_timer, 1157 wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon);
1092 jiffies + data->beacon_int); 1158 if (data->started &&
1159 !hrtimer_is_queued(&data->beacon_timer.timer) &&
1160 info->enable_beacon) {
1161 u64 tsf, until_tbtt;
1162 u32 bcn_int;
1163 if (WARN_ON(!data->beacon_int))
1164 data->beacon_int = 1000 * 1024;
1165 tsf = mac80211_hwsim_get_tsf(hw, vif);
1166 bcn_int = data->beacon_int;
1167 until_tbtt = bcn_int - do_div(tsf, bcn_int);
1168 tasklet_hrtimer_start(&data->beacon_timer,
1169 ns_to_ktime(until_tbtt * 1000),
1170 HRTIMER_MODE_REL);
1171 } else if (!info->enable_beacon)
1172 tasklet_hrtimer_cancel(&data->beacon_timer);
1093 } 1173 }
1094 1174
1095 if (changed & BSS_CHANGED_ERP_CTS_PROT) { 1175 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
@@ -1292,7 +1372,9 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
1292 case IEEE80211_AMPDU_TX_START: 1372 case IEEE80211_AMPDU_TX_START:
1293 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1373 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1294 break; 1374 break;
1295 case IEEE80211_AMPDU_TX_STOP: 1375 case IEEE80211_AMPDU_TX_STOP_CONT:
1376 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1377 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1296 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1378 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1297 break; 1379 break;
1298 case IEEE80211_AMPDU_TX_OPERATIONAL: 1380 case IEEE80211_AMPDU_TX_OPERATIONAL:
@@ -2370,8 +2452,9 @@ static int __init init_mac80211_hwsim(void)
2370 data->debugfs, data, 2452 data->debugfs, data,
2371 &hwsim_fops_group); 2453 &hwsim_fops_group);
2372 2454
2373 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, 2455 tasklet_hrtimer_init(&data->beacon_timer,
2374 (unsigned long) hw); 2456 mac80211_hwsim_beacon,
2457 CLOCK_REALTIME, HRTIMER_MODE_ABS);
2375 2458
2376 list_add_tail(&data->list, &hwsim_radios); 2459 list_add_tail(&data->list, &hwsim_radios);
2377 } 2460 }