diff options
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 580 |
1 files changed, 468 insertions, 112 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 429ca3215fdb..2aa8a1aa1184 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -44,9 +44,9 @@ static int radios = 2; | |||
44 | module_param(radios, int, 0444); | 44 | module_param(radios, int, 0444); |
45 | MODULE_PARM_DESC(radios, "Number of simulated radios"); | 45 | MODULE_PARM_DESC(radios, "Number of simulated radios"); |
46 | 46 | ||
47 | static bool fake_hw_scan; | 47 | static int channels = 1; |
48 | module_param(fake_hw_scan, bool, 0444); | 48 | module_param(channels, int, 0444); |
49 | MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler"); | 49 | MODULE_PARM_DESC(channels, "Number of concurrent channels"); |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * enum hwsim_regtest - the type of regulatory tests we offer | 52 | * enum hwsim_regtest - the type of regulatory tests we offer |
@@ -166,7 +166,9 @@ struct hwsim_vif_priv { | |||
166 | static inline void hwsim_check_magic(struct ieee80211_vif *vif) | 166 | static inline void hwsim_check_magic(struct ieee80211_vif *vif) |
167 | { | 167 | { |
168 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 168 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
169 | WARN_ON(vp->magic != HWSIM_VIF_MAGIC); | 169 | WARN(vp->magic != HWSIM_VIF_MAGIC, |
170 | "Invalid VIF (%p) magic %#x, %pM, %d/%d\n", | ||
171 | vif, vp->magic, vif->addr, vif->type, vif->p2p); | ||
170 | } | 172 | } |
171 | 173 | ||
172 | static inline void hwsim_set_magic(struct ieee80211_vif *vif) | 174 | static inline void hwsim_set_magic(struct ieee80211_vif *vif) |
@@ -185,7 +187,7 @@ struct hwsim_sta_priv { | |||
185 | u32 magic; | 187 | u32 magic; |
186 | }; | 188 | }; |
187 | 189 | ||
188 | #define HWSIM_STA_MAGIC 0x6d537748 | 190 | #define HWSIM_STA_MAGIC 0x6d537749 |
189 | 191 | ||
190 | static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta) | 192 | static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta) |
191 | { | 193 | { |
@@ -205,6 +207,30 @@ static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta) | |||
205 | sp->magic = 0; | 207 | sp->magic = 0; |
206 | } | 208 | } |
207 | 209 | ||
210 | struct hwsim_chanctx_priv { | ||
211 | u32 magic; | ||
212 | }; | ||
213 | |||
214 | #define HWSIM_CHANCTX_MAGIC 0x6d53774a | ||
215 | |||
216 | static inline void hwsim_check_chanctx_magic(struct ieee80211_chanctx_conf *c) | ||
217 | { | ||
218 | struct hwsim_chanctx_priv *cp = (void *)c->drv_priv; | ||
219 | WARN_ON(cp->magic != HWSIM_CHANCTX_MAGIC); | ||
220 | } | ||
221 | |||
222 | static inline void hwsim_set_chanctx_magic(struct ieee80211_chanctx_conf *c) | ||
223 | { | ||
224 | struct hwsim_chanctx_priv *cp = (void *)c->drv_priv; | ||
225 | cp->magic = HWSIM_CHANCTX_MAGIC; | ||
226 | } | ||
227 | |||
228 | static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c) | ||
229 | { | ||
230 | struct hwsim_chanctx_priv *cp = (void *)c->drv_priv; | ||
231 | cp->magic = 0; | ||
232 | } | ||
233 | |||
208 | static struct class *hwsim_class; | 234 | static struct class *hwsim_class; |
209 | 235 | ||
210 | static struct net_device *hwsim_mon; /* global monitor netdev */ | 236 | static struct net_device *hwsim_mon; /* global monitor netdev */ |
@@ -299,6 +325,13 @@ struct mac80211_hwsim_data { | |||
299 | 325 | ||
300 | struct mac_address addresses[2]; | 326 | struct mac_address addresses[2]; |
301 | 327 | ||
328 | struct ieee80211_channel *tmp_chan; | ||
329 | struct delayed_work roc_done; | ||
330 | struct delayed_work hw_scan; | ||
331 | struct cfg80211_scan_request *hw_scan_request; | ||
332 | struct ieee80211_vif *hw_scan_vif; | ||
333 | int scan_chan_idx; | ||
334 | |||
302 | struct ieee80211_channel *channel; | 335 | struct ieee80211_channel *channel; |
303 | unsigned long beacon_int; /* in jiffies unit */ | 336 | unsigned long beacon_int; /* in jiffies unit */ |
304 | unsigned int rx_filter; | 337 | unsigned int rx_filter; |
@@ -396,7 +429,8 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, | |||
396 | } | 429 | } |
397 | 430 | ||
398 | static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, | 431 | static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, |
399 | struct sk_buff *tx_skb) | 432 | struct sk_buff *tx_skb, |
433 | struct ieee80211_channel *chan) | ||
400 | { | 434 | { |
401 | struct mac80211_hwsim_data *data = hw->priv; | 435 | struct mac80211_hwsim_data *data = hw->priv; |
402 | struct sk_buff *skb; | 436 | struct sk_buff *skb; |
@@ -423,7 +457,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, | |||
423 | hdr->rt_tsft = __mac80211_hwsim_get_tsf(data); | 457 | hdr->rt_tsft = __mac80211_hwsim_get_tsf(data); |
424 | hdr->rt_flags = 0; | 458 | hdr->rt_flags = 0; |
425 | hdr->rt_rate = txrate->bitrate / 5; | 459 | hdr->rt_rate = txrate->bitrate / 5; |
426 | hdr->rt_channel = cpu_to_le16(data->channel->center_freq); | 460 | hdr->rt_channel = cpu_to_le16(chan->center_freq); |
427 | flags = IEEE80211_CHAN_2GHZ; | 461 | flags = IEEE80211_CHAN_2GHZ; |
428 | if (txrate->flags & IEEE80211_RATE_ERP_G) | 462 | if (txrate->flags & IEEE80211_RATE_ERP_G) |
429 | flags |= IEEE80211_CHAN_OFDM; | 463 | flags |= IEEE80211_CHAN_OFDM; |
@@ -441,9 +475,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, | |||
441 | } | 475 | } |
442 | 476 | ||
443 | 477 | ||
444 | static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr) | 478 | static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan, |
479 | const u8 *addr) | ||
445 | { | 480 | { |
446 | struct mac80211_hwsim_data *data = hw->priv; | ||
447 | struct sk_buff *skb; | 481 | struct sk_buff *skb; |
448 | struct hwsim_radiotap_hdr *hdr; | 482 | struct hwsim_radiotap_hdr *hdr; |
449 | u16 flags; | 483 | u16 flags; |
@@ -464,7 +498,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr) | |||
464 | (1 << IEEE80211_RADIOTAP_CHANNEL)); | 498 | (1 << IEEE80211_RADIOTAP_CHANNEL)); |
465 | hdr->rt_flags = 0; | 499 | hdr->rt_flags = 0; |
466 | hdr->rt_rate = 0; | 500 | hdr->rt_rate = 0; |
467 | hdr->rt_channel = cpu_to_le16(data->channel->center_freq); | 501 | hdr->rt_channel = cpu_to_le16(chan->center_freq); |
468 | flags = IEEE80211_CHAN_2GHZ; | 502 | flags = IEEE80211_CHAN_2GHZ; |
469 | hdr->rt_chbitmask = cpu_to_le16(flags); | 503 | hdr->rt_chbitmask = cpu_to_le16(flags); |
470 | 504 | ||
@@ -537,6 +571,7 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, | |||
537 | md.ret = false; | 571 | md.ret = false; |
538 | md.addr = addr; | 572 | md.addr = addr; |
539 | ieee80211_iterate_active_interfaces_atomic(data->hw, | 573 | ieee80211_iterate_active_interfaces_atomic(data->hw, |
574 | IEEE80211_IFACE_ITER_NORMAL, | ||
540 | mac80211_hwsim_addr_iter, | 575 | mac80211_hwsim_addr_iter, |
541 | &md); | 576 | &md); |
542 | 577 | ||
@@ -556,12 +591,6 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
556 | int i; | 591 | int i; |
557 | struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES]; | 592 | struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES]; |
558 | 593 | ||
559 | if (data->idle) { | ||
560 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | ||
561 | dev_kfree_skb(my_skb); | ||
562 | return; | ||
563 | } | ||
564 | |||
565 | if (data->ps != PS_DISABLED) | 594 | if (data->ps != PS_DISABLED) |
566 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 595 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
567 | /* If the queue contains MAX_QUEUE skb's drop some */ | 596 | /* If the queue contains MAX_QUEUE skb's drop some */ |
@@ -629,8 +658,38 @@ nla_put_failure: | |||
629 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 658 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); |
630 | } | 659 | } |
631 | 660 | ||
661 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, | ||
662 | struct ieee80211_channel *c2) | ||
663 | { | ||
664 | if (!c1 || !c2) | ||
665 | return false; | ||
666 | |||
667 | return c1->center_freq == c2->center_freq; | ||
668 | } | ||
669 | |||
670 | struct tx_iter_data { | ||
671 | struct ieee80211_channel *channel; | ||
672 | bool receive; | ||
673 | }; | ||
674 | |||
675 | static void mac80211_hwsim_tx_iter(void *_data, u8 *addr, | ||
676 | struct ieee80211_vif *vif) | ||
677 | { | ||
678 | struct tx_iter_data *data = _data; | ||
679 | |||
680 | if (!vif->chanctx_conf) | ||
681 | return; | ||
682 | |||
683 | if (!hwsim_chans_compat(data->channel, | ||
684 | rcu_dereference(vif->chanctx_conf)->def.chan)) | ||
685 | return; | ||
686 | |||
687 | data->receive = true; | ||
688 | } | ||
689 | |||
632 | static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | 690 | static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, |
633 | struct sk_buff *skb) | 691 | struct sk_buff *skb, |
692 | struct ieee80211_channel *chan) | ||
634 | { | 693 | { |
635 | struct mac80211_hwsim_data *data = hw->priv, *data2; | 694 | struct mac80211_hwsim_data *data = hw->priv, *data2; |
636 | bool ack = false; | 695 | bool ack = false; |
@@ -639,15 +698,10 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
639 | struct ieee80211_rx_status rx_status; | 698 | struct ieee80211_rx_status rx_status; |
640 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); | 699 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); |
641 | 700 | ||
642 | if (data->idle) { | ||
643 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | ||
644 | return false; | ||
645 | } | ||
646 | |||
647 | memset(&rx_status, 0, sizeof(rx_status)); | 701 | memset(&rx_status, 0, sizeof(rx_status)); |
648 | rx_status.flag |= RX_FLAG_MACTIME_MPDU; | 702 | rx_status.flag |= RX_FLAG_MACTIME_START; |
649 | rx_status.freq = data->channel->center_freq; | 703 | rx_status.freq = chan->center_freq; |
650 | rx_status.band = data->channel->band; | 704 | rx_status.band = chan->band; |
651 | rx_status.rate_idx = info->control.rates[0].idx; | 705 | rx_status.rate_idx = info->control.rates[0].idx; |
652 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) | 706 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) |
653 | rx_status.flag |= RX_FLAG_HT; | 707 | rx_status.flag |= RX_FLAG_HT; |
@@ -673,17 +727,35 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
673 | list_for_each_entry(data2, &hwsim_radios, list) { | 727 | list_for_each_entry(data2, &hwsim_radios, list) { |
674 | struct sk_buff *nskb; | 728 | struct sk_buff *nskb; |
675 | struct ieee80211_mgmt *mgmt; | 729 | struct ieee80211_mgmt *mgmt; |
730 | struct tx_iter_data tx_iter_data = { | ||
731 | .receive = false, | ||
732 | .channel = chan, | ||
733 | }; | ||
676 | 734 | ||
677 | if (data == data2) | 735 | if (data == data2) |
678 | continue; | 736 | continue; |
679 | 737 | ||
680 | if (data2->idle || !data2->started || | 738 | if (!data2->started || (data2->idle && !data2->tmp_chan) || |
681 | !hwsim_ps_rx_ok(data2, skb) || !data2->channel || | 739 | !hwsim_ps_rx_ok(data2, skb)) |
682 | data->channel->center_freq != data2->channel->center_freq || | ||
683 | !(data->group & data2->group)) | ||
684 | continue; | 740 | continue; |
685 | 741 | ||
686 | nskb = skb_copy(skb, GFP_ATOMIC); | 742 | if (!(data->group & data2->group)) |
743 | continue; | ||
744 | |||
745 | if (!hwsim_chans_compat(chan, data2->tmp_chan) && | ||
746 | !hwsim_chans_compat(chan, data2->channel)) { | ||
747 | ieee80211_iterate_active_interfaces_atomic( | ||
748 | data2->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
749 | mac80211_hwsim_tx_iter, &tx_iter_data); | ||
750 | if (!tx_iter_data.receive) | ||
751 | continue; | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * reserve some space for our vendor and the normal | ||
756 | * radiotap header, since we're copying anyway | ||
757 | */ | ||
758 | nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC); | ||
687 | if (nskb == NULL) | 759 | if (nskb == NULL) |
688 | continue; | 760 | continue; |
689 | 761 | ||
@@ -701,6 +773,33 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
701 | (data->tsf_offset - data2->tsf_offset) + | 773 | (data->tsf_offset - data2->tsf_offset) + |
702 | 24 * 8 * 10 / txrate->bitrate); | 774 | 24 * 8 * 10 / txrate->bitrate); |
703 | 775 | ||
776 | #if 0 | ||
777 | /* | ||
778 | * Don't enable this code by default as the OUI 00:00:00 | ||
779 | * is registered to Xerox so we shouldn't use it here, it | ||
780 | * might find its way into pcap files. | ||
781 | * Note that this code requires the headroom in the SKB | ||
782 | * that was allocated earlier. | ||
783 | */ | ||
784 | rx_status.vendor_radiotap_oui[0] = 0x00; | ||
785 | rx_status.vendor_radiotap_oui[1] = 0x00; | ||
786 | rx_status.vendor_radiotap_oui[2] = 0x00; | ||
787 | rx_status.vendor_radiotap_subns = 127; | ||
788 | /* | ||
789 | * Radiotap vendor namespaces can (and should) also be | ||
790 | * split into fields by using the standard radiotap | ||
791 | * presence bitmap mechanism. Use just BIT(0) here for | ||
792 | * the presence bitmap. | ||
793 | */ | ||
794 | rx_status.vendor_radiotap_bitmap = BIT(0); | ||
795 | /* We have 8 bytes of (dummy) data */ | ||
796 | rx_status.vendor_radiotap_len = 8; | ||
797 | /* For testing, also require it to be aligned */ | ||
798 | rx_status.vendor_radiotap_align = 8; | ||
799 | /* push the data */ | ||
800 | memcpy(skb_push(nskb, 8), "ABCDEFGH", 8); | ||
801 | #endif | ||
802 | |||
704 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 803 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
705 | ieee80211_rx_irqsafe(data2->hw, nskb); | 804 | ieee80211_rx_irqsafe(data2->hw, nskb); |
706 | } | 805 | } |
@@ -713,18 +812,51 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
713 | struct ieee80211_tx_control *control, | 812 | struct ieee80211_tx_control *control, |
714 | struct sk_buff *skb) | 813 | struct sk_buff *skb) |
715 | { | 814 | { |
815 | struct mac80211_hwsim_data *data = hw->priv; | ||
816 | struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); | ||
817 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
818 | struct ieee80211_channel *channel; | ||
716 | bool ack; | 819 | bool ack; |
717 | struct ieee80211_tx_info *txi; | ||
718 | u32 _portid; | 820 | u32 _portid; |
719 | 821 | ||
720 | mac80211_hwsim_monitor_rx(hw, skb); | 822 | if (WARN_ON(skb->len < 10)) { |
721 | |||
722 | if (skb->len < 10) { | ||
723 | /* Should not happen; just a sanity check for addr1 use */ | 823 | /* Should not happen; just a sanity check for addr1 use */ |
724 | dev_kfree_skb(skb); | 824 | dev_kfree_skb(skb); |
725 | return; | 825 | return; |
726 | } | 826 | } |
727 | 827 | ||
828 | if (channels == 1) { | ||
829 | channel = data->channel; | ||
830 | } else if (txi->hw_queue == 4) { | ||
831 | channel = data->tmp_chan; | ||
832 | } else { | ||
833 | chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf); | ||
834 | if (chanctx_conf) | ||
835 | channel = chanctx_conf->def.chan; | ||
836 | else | ||
837 | channel = NULL; | ||
838 | } | ||
839 | |||
840 | if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) { | ||
841 | dev_kfree_skb(skb); | ||
842 | return; | ||
843 | } | ||
844 | |||
845 | if (data->idle && !data->tmp_chan) { | ||
846 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | ||
847 | dev_kfree_skb(skb); | ||
848 | return; | ||
849 | } | ||
850 | |||
851 | if (txi->control.vif) | ||
852 | hwsim_check_magic(txi->control.vif); | ||
853 | if (control->sta) | ||
854 | hwsim_check_sta_magic(control->sta); | ||
855 | |||
856 | txi->rate_driver_data[0] = channel; | ||
857 | |||
858 | mac80211_hwsim_monitor_rx(hw, skb, channel); | ||
859 | |||
728 | /* wmediumd mode check */ | 860 | /* wmediumd mode check */ |
729 | _portid = ACCESS_ONCE(wmediumd_portid); | 861 | _portid = ACCESS_ONCE(wmediumd_portid); |
730 | 862 | ||
@@ -732,15 +864,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
732 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); | 864 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); |
733 | 865 | ||
734 | /* NO wmediumd detected, perfect medium simulation */ | 866 | /* NO wmediumd detected, perfect medium simulation */ |
735 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb); | 867 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); |
736 | 868 | ||
737 | if (ack && skb->len >= 16) { | 869 | if (ack && skb->len >= 16) { |
738 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 870 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
739 | mac80211_hwsim_monitor_ack(hw, hdr->addr2); | 871 | mac80211_hwsim_monitor_ack(channel, hdr->addr2); |
740 | } | 872 | } |
741 | 873 | ||
742 | txi = IEEE80211_SKB_CB(skb); | ||
743 | |||
744 | ieee80211_tx_info_clear_status(txi); | 874 | ieee80211_tx_info_clear_status(txi); |
745 | 875 | ||
746 | /* frame was transmitted at most favorable rate at first attempt */ | 876 | /* frame was transmitted at most favorable rate at first attempt */ |
@@ -778,6 +908,13 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | |||
778 | __func__, ieee80211_vif_type_p2p(vif), | 908 | __func__, ieee80211_vif_type_p2p(vif), |
779 | vif->addr); | 909 | vif->addr); |
780 | hwsim_set_magic(vif); | 910 | hwsim_set_magic(vif); |
911 | |||
912 | vif->cab_queue = 0; | ||
913 | vif->hw_queue[IEEE80211_AC_VO] = 0; | ||
914 | vif->hw_queue[IEEE80211_AC_VI] = 1; | ||
915 | vif->hw_queue[IEEE80211_AC_BE] = 2; | ||
916 | vif->hw_queue[IEEE80211_AC_BK] = 3; | ||
917 | |||
781 | return 0; | 918 | return 0; |
782 | } | 919 | } |
783 | 920 | ||
@@ -807,14 +944,26 @@ static void mac80211_hwsim_remove_interface( | |||
807 | hwsim_clear_magic(vif); | 944 | hwsim_clear_magic(vif); |
808 | } | 945 | } |
809 | 946 | ||
947 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | ||
948 | struct sk_buff *skb, | ||
949 | struct ieee80211_channel *chan) | ||
950 | { | ||
951 | u32 _pid = ACCESS_ONCE(wmediumd_portid); | ||
952 | |||
953 | mac80211_hwsim_monitor_rx(hw, skb, chan); | ||
954 | |||
955 | if (_pid) | ||
956 | return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); | ||
957 | |||
958 | mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); | ||
959 | dev_kfree_skb(skb); | ||
960 | } | ||
810 | 961 | ||
811 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | 962 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, |
812 | struct ieee80211_vif *vif) | 963 | struct ieee80211_vif *vif) |
813 | { | 964 | { |
814 | struct ieee80211_hw *hw = arg; | 965 | struct ieee80211_hw *hw = arg; |
815 | struct sk_buff *skb; | 966 | struct sk_buff *skb; |
816 | struct ieee80211_tx_info *info; | ||
817 | u32 _portid; | ||
818 | 967 | ||
819 | hwsim_check_magic(vif); | 968 | hwsim_check_magic(vif); |
820 | 969 | ||
@@ -826,18 +975,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
826 | skb = ieee80211_beacon_get(hw, vif); | 975 | skb = ieee80211_beacon_get(hw, vif); |
827 | if (skb == NULL) | 976 | if (skb == NULL) |
828 | return; | 977 | return; |
829 | info = IEEE80211_SKB_CB(skb); | ||
830 | |||
831 | mac80211_hwsim_monitor_rx(hw, skb); | ||
832 | |||
833 | /* wmediumd mode check */ | ||
834 | _portid = ACCESS_ONCE(wmediumd_portid); | ||
835 | |||
836 | if (_portid) | ||
837 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); | ||
838 | 978 | ||
839 | mac80211_hwsim_tx_frame_no_nl(hw, skb); | 979 | mac80211_hwsim_tx_frame(hw, skb, |
840 | dev_kfree_skb(skb); | 980 | rcu_dereference(vif->chanctx_conf)->def.chan); |
841 | } | 981 | } |
842 | 982 | ||
843 | 983 | ||
@@ -850,7 +990,8 @@ static void mac80211_hwsim_beacon(unsigned long arg) | |||
850 | return; | 990 | return; |
851 | 991 | ||
852 | ieee80211_iterate_active_interfaces_atomic( | 992 | ieee80211_iterate_active_interfaces_atomic( |
853 | hw, mac80211_hwsim_beacon_tx, hw); | 993 | hw, IEEE80211_IFACE_ITER_NORMAL, |
994 | mac80211_hwsim_beacon_tx, hw); | ||
854 | 995 | ||
855 | data->beacon_timer.expires = jiffies + data->beacon_int; | 996 | data->beacon_timer.expires = jiffies + data->beacon_int; |
856 | add_timer(&data->beacon_timer); | 997 | add_timer(&data->beacon_timer); |
@@ -877,7 +1018,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
877 | wiphy_debug(hw->wiphy, | 1018 | wiphy_debug(hw->wiphy, |
878 | "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", | 1019 | "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", |
879 | __func__, | 1020 | __func__, |
880 | conf->channel->center_freq, | 1021 | conf->channel ? conf->channel->center_freq : 0, |
881 | hwsim_chantypes[conf->channel_type], | 1022 | hwsim_chantypes[conf->channel_type], |
882 | !!(conf->flags & IEEE80211_CONF_IDLE), | 1023 | !!(conf->flags & IEEE80211_CONF_IDLE), |
883 | !!(conf->flags & IEEE80211_CONF_PS), | 1024 | !!(conf->flags & IEEE80211_CONF_PS), |
@@ -886,6 +1027,9 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
886 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 1027 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
887 | 1028 | ||
888 | data->channel = conf->channel; | 1029 | data->channel = conf->channel; |
1030 | |||
1031 | WARN_ON(data->channel && channels > 1); | ||
1032 | |||
889 | data->power_level = conf->power_level; | 1033 | data->power_level = conf->power_level; |
890 | if (!data->started || !data->beacon_int) | 1034 | if (!data->started || !data->beacon_int) |
891 | del_timer(&data->beacon_timer); | 1035 | del_timer(&data->beacon_timer); |
@@ -963,15 +1107,17 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
963 | } | 1107 | } |
964 | 1108 | ||
965 | if (changed & BSS_CHANGED_HT) { | 1109 | if (changed & BSS_CHANGED_HT) { |
966 | wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n", | 1110 | wiphy_debug(hw->wiphy, " HT: op_mode=0x%x\n", |
967 | info->ht_operation_mode, | 1111 | info->ht_operation_mode); |
968 | hwsim_chantypes[info->channel_type]); | ||
969 | } | 1112 | } |
970 | 1113 | ||
971 | if (changed & BSS_CHANGED_BASIC_RATES) { | 1114 | if (changed & BSS_CHANGED_BASIC_RATES) { |
972 | wiphy_debug(hw->wiphy, " BASIC_RATES: 0x%llx\n", | 1115 | wiphy_debug(hw->wiphy, " BASIC_RATES: 0x%llx\n", |
973 | (unsigned long long) info->basic_rates); | 1116 | (unsigned long long) info->basic_rates); |
974 | } | 1117 | } |
1118 | |||
1119 | if (changed & BSS_CHANGED_TXPOWER) | ||
1120 | wiphy_debug(hw->wiphy, " TX Power: %d dBm\n", info->txpower); | ||
975 | } | 1121 | } |
976 | 1122 | ||
977 | static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, | 1123 | static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, |
@@ -1166,45 +1312,96 @@ static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) | |||
1166 | /* Not implemented, queues only on kernel side */ | 1312 | /* Not implemented, queues only on kernel side */ |
1167 | } | 1313 | } |
1168 | 1314 | ||
1169 | struct hw_scan_done { | 1315 | static void hw_scan_work(struct work_struct *work) |
1170 | struct delayed_work w; | ||
1171 | struct ieee80211_hw *hw; | ||
1172 | }; | ||
1173 | |||
1174 | static void hw_scan_done(struct work_struct *work) | ||
1175 | { | 1316 | { |
1176 | struct hw_scan_done *hsd = | 1317 | struct mac80211_hwsim_data *hwsim = |
1177 | container_of(work, struct hw_scan_done, w.work); | 1318 | container_of(work, struct mac80211_hwsim_data, hw_scan.work); |
1319 | struct cfg80211_scan_request *req = hwsim->hw_scan_request; | ||
1320 | int dwell, i; | ||
1321 | |||
1322 | mutex_lock(&hwsim->mutex); | ||
1323 | if (hwsim->scan_chan_idx >= req->n_channels) { | ||
1324 | wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n"); | ||
1325 | ieee80211_scan_completed(hwsim->hw, false); | ||
1326 | hwsim->hw_scan_request = NULL; | ||
1327 | hwsim->hw_scan_vif = NULL; | ||
1328 | hwsim->tmp_chan = NULL; | ||
1329 | mutex_unlock(&hwsim->mutex); | ||
1330 | return; | ||
1331 | } | ||
1178 | 1332 | ||
1179 | ieee80211_scan_completed(hsd->hw, false); | 1333 | wiphy_debug(hwsim->hw->wiphy, "hw scan %d MHz\n", |
1180 | kfree(hsd); | 1334 | req->channels[hwsim->scan_chan_idx]->center_freq); |
1335 | |||
1336 | hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; | ||
1337 | if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
1338 | !req->n_ssids) { | ||
1339 | dwell = 120; | ||
1340 | } else { | ||
1341 | dwell = 30; | ||
1342 | /* send probes */ | ||
1343 | for (i = 0; i < req->n_ssids; i++) { | ||
1344 | struct sk_buff *probe; | ||
1345 | |||
1346 | probe = ieee80211_probereq_get(hwsim->hw, | ||
1347 | hwsim->hw_scan_vif, | ||
1348 | req->ssids[i].ssid, | ||
1349 | req->ssids[i].ssid_len, | ||
1350 | req->ie, req->ie_len); | ||
1351 | if (!probe) | ||
1352 | continue; | ||
1353 | local_bh_disable(); | ||
1354 | mac80211_hwsim_tx_frame(hwsim->hw, probe, | ||
1355 | hwsim->tmp_chan); | ||
1356 | local_bh_enable(); | ||
1357 | } | ||
1358 | } | ||
1359 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, | ||
1360 | msecs_to_jiffies(dwell)); | ||
1361 | hwsim->scan_chan_idx++; | ||
1362 | mutex_unlock(&hwsim->mutex); | ||
1181 | } | 1363 | } |
1182 | 1364 | ||
1183 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | 1365 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, |
1184 | struct ieee80211_vif *vif, | 1366 | struct ieee80211_vif *vif, |
1185 | struct cfg80211_scan_request *req) | 1367 | struct cfg80211_scan_request *req) |
1186 | { | 1368 | { |
1187 | struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); | 1369 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1188 | int i; | ||
1189 | |||
1190 | if (!hsd) | ||
1191 | return -ENOMEM; | ||
1192 | 1370 | ||
1193 | hsd->hw = hw; | 1371 | mutex_lock(&hwsim->mutex); |
1194 | INIT_DELAYED_WORK(&hsd->w, hw_scan_done); | 1372 | if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { |
1373 | mutex_unlock(&hwsim->mutex); | ||
1374 | return -EBUSY; | ||
1375 | } | ||
1376 | hwsim->hw_scan_request = req; | ||
1377 | hwsim->hw_scan_vif = vif; | ||
1378 | hwsim->scan_chan_idx = 0; | ||
1379 | mutex_unlock(&hwsim->mutex); | ||
1195 | 1380 | ||
1196 | printk(KERN_DEBUG "hwsim hw_scan request\n"); | 1381 | wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); |
1197 | for (i = 0; i < req->n_channels; i++) | ||
1198 | printk(KERN_DEBUG "hwsim hw_scan freq %d\n", | ||
1199 | req->channels[i]->center_freq); | ||
1200 | print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET, | ||
1201 | 16, 1, req->ie, req->ie_len, 1); | ||
1202 | 1382 | ||
1203 | ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); | 1383 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); |
1204 | 1384 | ||
1205 | return 0; | 1385 | return 0; |
1206 | } | 1386 | } |
1207 | 1387 | ||
1388 | static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, | ||
1389 | struct ieee80211_vif *vif) | ||
1390 | { | ||
1391 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
1392 | |||
1393 | wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n"); | ||
1394 | |||
1395 | cancel_delayed_work_sync(&hwsim->hw_scan); | ||
1396 | |||
1397 | mutex_lock(&hwsim->mutex); | ||
1398 | ieee80211_scan_completed(hwsim->hw, true); | ||
1399 | hwsim->tmp_chan = NULL; | ||
1400 | hwsim->hw_scan_request = NULL; | ||
1401 | hwsim->hw_scan_vif = NULL; | ||
1402 | mutex_unlock(&hwsim->mutex); | ||
1403 | } | ||
1404 | |||
1208 | static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) | 1405 | static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) |
1209 | { | 1406 | { |
1210 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1407 | struct mac80211_hwsim_data *hwsim = hw->priv; |
@@ -1235,6 +1432,111 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) | |||
1235 | mutex_unlock(&hwsim->mutex); | 1432 | mutex_unlock(&hwsim->mutex); |
1236 | } | 1433 | } |
1237 | 1434 | ||
1435 | static void hw_roc_done(struct work_struct *work) | ||
1436 | { | ||
1437 | struct mac80211_hwsim_data *hwsim = | ||
1438 | container_of(work, struct mac80211_hwsim_data, roc_done.work); | ||
1439 | |||
1440 | mutex_lock(&hwsim->mutex); | ||
1441 | ieee80211_remain_on_channel_expired(hwsim->hw); | ||
1442 | hwsim->tmp_chan = NULL; | ||
1443 | mutex_unlock(&hwsim->mutex); | ||
1444 | |||
1445 | wiphy_debug(hwsim->hw->wiphy, "hwsim ROC expired\n"); | ||
1446 | } | ||
1447 | |||
1448 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, | ||
1449 | struct ieee80211_vif *vif, | ||
1450 | struct ieee80211_channel *chan, | ||
1451 | int duration) | ||
1452 | { | ||
1453 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
1454 | |||
1455 | mutex_lock(&hwsim->mutex); | ||
1456 | if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { | ||
1457 | mutex_unlock(&hwsim->mutex); | ||
1458 | return -EBUSY; | ||
1459 | } | ||
1460 | |||
1461 | hwsim->tmp_chan = chan; | ||
1462 | mutex_unlock(&hwsim->mutex); | ||
1463 | |||
1464 | wiphy_debug(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n", | ||
1465 | chan->center_freq, duration); | ||
1466 | |||
1467 | ieee80211_ready_on_channel(hw); | ||
1468 | |||
1469 | ieee80211_queue_delayed_work(hw, &hwsim->roc_done, | ||
1470 | msecs_to_jiffies(duration)); | ||
1471 | return 0; | ||
1472 | } | ||
1473 | |||
1474 | static int mac80211_hwsim_croc(struct ieee80211_hw *hw) | ||
1475 | { | ||
1476 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
1477 | |||
1478 | cancel_delayed_work_sync(&hwsim->roc_done); | ||
1479 | |||
1480 | mutex_lock(&hwsim->mutex); | ||
1481 | hwsim->tmp_chan = NULL; | ||
1482 | mutex_unlock(&hwsim->mutex); | ||
1483 | |||
1484 | wiphy_debug(hw->wiphy, "hwsim ROC canceled\n"); | ||
1485 | |||
1486 | return 0; | ||
1487 | } | ||
1488 | |||
1489 | static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, | ||
1490 | struct ieee80211_chanctx_conf *ctx) | ||
1491 | { | ||
1492 | hwsim_set_chanctx_magic(ctx); | ||
1493 | wiphy_debug(hw->wiphy, | ||
1494 | "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", | ||
1495 | ctx->def.chan->center_freq, ctx->def.width, | ||
1496 | ctx->def.center_freq1, ctx->def.center_freq2); | ||
1497 | return 0; | ||
1498 | } | ||
1499 | |||
1500 | static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, | ||
1501 | struct ieee80211_chanctx_conf *ctx) | ||
1502 | { | ||
1503 | wiphy_debug(hw->wiphy, | ||
1504 | "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", | ||
1505 | ctx->def.chan->center_freq, ctx->def.width, | ||
1506 | ctx->def.center_freq1, ctx->def.center_freq2); | ||
1507 | hwsim_check_chanctx_magic(ctx); | ||
1508 | hwsim_clear_chanctx_magic(ctx); | ||
1509 | } | ||
1510 | |||
1511 | static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, | ||
1512 | struct ieee80211_chanctx_conf *ctx, | ||
1513 | u32 changed) | ||
1514 | { | ||
1515 | hwsim_check_chanctx_magic(ctx); | ||
1516 | wiphy_debug(hw->wiphy, | ||
1517 | "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", | ||
1518 | ctx->def.chan->center_freq, ctx->def.width, | ||
1519 | ctx->def.center_freq1, ctx->def.center_freq2); | ||
1520 | } | ||
1521 | |||
1522 | static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, | ||
1523 | struct ieee80211_vif *vif, | ||
1524 | struct ieee80211_chanctx_conf *ctx) | ||
1525 | { | ||
1526 | hwsim_check_magic(vif); | ||
1527 | hwsim_check_chanctx_magic(ctx); | ||
1528 | |||
1529 | return 0; | ||
1530 | } | ||
1531 | |||
1532 | static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, | ||
1533 | struct ieee80211_vif *vif, | ||
1534 | struct ieee80211_chanctx_conf *ctx) | ||
1535 | { | ||
1536 | hwsim_check_magic(vif); | ||
1537 | hwsim_check_chanctx_magic(ctx); | ||
1538 | } | ||
1539 | |||
1238 | static struct ieee80211_ops mac80211_hwsim_ops = | 1540 | static struct ieee80211_ops mac80211_hwsim_ops = |
1239 | { | 1541 | { |
1240 | .tx = mac80211_hwsim_tx, | 1542 | .tx = mac80211_hwsim_tx, |
@@ -1315,7 +1617,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | |||
1315 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 1617 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
1316 | struct sk_buff *skb; | 1618 | struct sk_buff *skb; |
1317 | struct ieee80211_pspoll *pspoll; | 1619 | struct ieee80211_pspoll *pspoll; |
1318 | u32 _portid; | ||
1319 | 1620 | ||
1320 | if (!vp->assoc) | 1621 | if (!vp->assoc) |
1321 | return; | 1622 | return; |
@@ -1335,25 +1636,18 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | |||
1335 | memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); | 1636 | memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); |
1336 | memcpy(pspoll->ta, mac, ETH_ALEN); | 1637 | memcpy(pspoll->ta, mac, ETH_ALEN); |
1337 | 1638 | ||
1338 | /* wmediumd mode check */ | 1639 | rcu_read_lock(); |
1339 | _portid = ACCESS_ONCE(wmediumd_portid); | 1640 | mac80211_hwsim_tx_frame(data->hw, skb, |
1340 | 1641 | rcu_dereference(vif->chanctx_conf)->def.chan); | |
1341 | if (_portid) | 1642 | rcu_read_unlock(); |
1342 | return mac80211_hwsim_tx_frame_nl(data->hw, skb, _portid); | ||
1343 | |||
1344 | if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb)) | ||
1345 | printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__); | ||
1346 | dev_kfree_skb(skb); | ||
1347 | } | 1643 | } |
1348 | 1644 | ||
1349 | |||
1350 | static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | 1645 | static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, |
1351 | struct ieee80211_vif *vif, int ps) | 1646 | struct ieee80211_vif *vif, int ps) |
1352 | { | 1647 | { |
1353 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 1648 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
1354 | struct sk_buff *skb; | 1649 | struct sk_buff *skb; |
1355 | struct ieee80211_hdr *hdr; | 1650 | struct ieee80211_hdr *hdr; |
1356 | u32 _portid; | ||
1357 | 1651 | ||
1358 | if (!vp->assoc) | 1652 | if (!vp->assoc) |
1359 | return; | 1653 | return; |
@@ -1374,15 +1668,10 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | |||
1374 | memcpy(hdr->addr2, mac, ETH_ALEN); | 1668 | memcpy(hdr->addr2, mac, ETH_ALEN); |
1375 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); | 1669 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); |
1376 | 1670 | ||
1377 | /* wmediumd mode check */ | 1671 | rcu_read_lock(); |
1378 | _portid = ACCESS_ONCE(wmediumd_portid); | 1672 | mac80211_hwsim_tx_frame(data->hw, skb, |
1379 | 1673 | rcu_dereference(vif->chanctx_conf)->def.chan); | |
1380 | if (_portid) | 1674 | rcu_read_unlock(); |
1381 | return mac80211_hwsim_tx_frame_nl(data->hw, skb, _portid); | ||
1382 | |||
1383 | if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb)) | ||
1384 | printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__); | ||
1385 | dev_kfree_skb(skb); | ||
1386 | } | 1675 | } |
1387 | 1676 | ||
1388 | 1677 | ||
@@ -1423,14 +1712,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val) | |||
1423 | 1712 | ||
1424 | if (val == PS_MANUAL_POLL) { | 1713 | if (val == PS_MANUAL_POLL) { |
1425 | ieee80211_iterate_active_interfaces(data->hw, | 1714 | ieee80211_iterate_active_interfaces(data->hw, |
1715 | IEEE80211_IFACE_ITER_NORMAL, | ||
1426 | hwsim_send_ps_poll, data); | 1716 | hwsim_send_ps_poll, data); |
1427 | data->ps_poll_pending = true; | 1717 | data->ps_poll_pending = true; |
1428 | } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { | 1718 | } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { |
1429 | ieee80211_iterate_active_interfaces(data->hw, | 1719 | ieee80211_iterate_active_interfaces(data->hw, |
1720 | IEEE80211_IFACE_ITER_NORMAL, | ||
1430 | hwsim_send_nullfunc_ps, | 1721 | hwsim_send_nullfunc_ps, |
1431 | data); | 1722 | data); |
1432 | } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { | 1723 | } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { |
1433 | ieee80211_iterate_active_interfaces(data->hw, | 1724 | ieee80211_iterate_active_interfaces(data->hw, |
1725 | IEEE80211_IFACE_ITER_NORMAL, | ||
1434 | hwsim_send_nullfunc_no_ps, | 1726 | hwsim_send_nullfunc_no_ps, |
1435 | data); | 1727 | data); |
1436 | } | 1728 | } |
@@ -1551,7 +1843,8 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, | |||
1551 | (hwsim_flags & HWSIM_TX_STAT_ACK)) { | 1843 | (hwsim_flags & HWSIM_TX_STAT_ACK)) { |
1552 | if (skb->len >= 16) { | 1844 | if (skb->len >= 16) { |
1553 | hdr = (struct ieee80211_hdr *) skb->data; | 1845 | hdr = (struct ieee80211_hdr *) skb->data; |
1554 | mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); | 1846 | mac80211_hwsim_monitor_ack(txi->rate_driver_data[0], |
1847 | hdr->addr2); | ||
1555 | } | 1848 | } |
1556 | txi->flags |= IEEE80211_TX_STAT_ACK; | 1849 | txi->flags |= IEEE80211_TX_STAT_ACK; |
1557 | } | 1850 | } |
@@ -1566,7 +1859,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
1566 | struct genl_info *info) | 1859 | struct genl_info *info) |
1567 | { | 1860 | { |
1568 | 1861 | ||
1569 | struct mac80211_hwsim_data *data2; | 1862 | struct mac80211_hwsim_data *data2; |
1570 | struct ieee80211_rx_status rx_status; | 1863 | struct ieee80211_rx_status rx_status; |
1571 | struct mac_address *dst; | 1864 | struct mac_address *dst; |
1572 | int frame_data_len; | 1865 | int frame_data_len; |
@@ -1574,9 +1867,9 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
1574 | struct sk_buff *skb = NULL; | 1867 | struct sk_buff *skb = NULL; |
1575 | 1868 | ||
1576 | if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || | 1869 | if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || |
1577 | !info->attrs[HWSIM_ATTR_FRAME] || | 1870 | !info->attrs[HWSIM_ATTR_FRAME] || |
1578 | !info->attrs[HWSIM_ATTR_RX_RATE] || | 1871 | !info->attrs[HWSIM_ATTR_RX_RATE] || |
1579 | !info->attrs[HWSIM_ATTR_SIGNAL]) | 1872 | !info->attrs[HWSIM_ATTR_SIGNAL]) |
1580 | goto out; | 1873 | goto out; |
1581 | 1874 | ||
1582 | dst = (struct mac_address *)nla_data( | 1875 | dst = (struct mac_address *)nla_data( |
@@ -1604,7 +1897,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
1604 | 1897 | ||
1605 | /* check if radio is configured properly */ | 1898 | /* check if radio is configured properly */ |
1606 | 1899 | ||
1607 | if (data2->idle || !data2->started || !data2->channel) | 1900 | if (data2->idle || !data2->started) |
1608 | goto out; | 1901 | goto out; |
1609 | 1902 | ||
1610 | /*A frame is received from user space*/ | 1903 | /*A frame is received from user space*/ |
@@ -1688,6 +1981,11 @@ static struct notifier_block hwsim_netlink_notifier = { | |||
1688 | static int hwsim_init_netlink(void) | 1981 | static int hwsim_init_netlink(void) |
1689 | { | 1982 | { |
1690 | int rc; | 1983 | int rc; |
1984 | |||
1985 | /* userspace test API hasn't been adjusted for multi-channel */ | ||
1986 | if (channels > 1) | ||
1987 | return 0; | ||
1988 | |||
1691 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); | 1989 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); |
1692 | 1990 | ||
1693 | rc = genl_register_family_with_ops(&hwsim_genl_family, | 1991 | rc = genl_register_family_with_ops(&hwsim_genl_family, |
@@ -1710,6 +2008,10 @@ static void hwsim_exit_netlink(void) | |||
1710 | { | 2008 | { |
1711 | int ret; | 2009 | int ret; |
1712 | 2010 | ||
2011 | /* userspace test API hasn't been adjusted for multi-channel */ | ||
2012 | if (channels > 1) | ||
2013 | return; | ||
2014 | |||
1713 | printk(KERN_INFO "mac80211_hwsim: closing netlink\n"); | 2015 | printk(KERN_INFO "mac80211_hwsim: closing netlink\n"); |
1714 | /* unregister the notifier */ | 2016 | /* unregister the notifier */ |
1715 | netlink_unregister_notifier(&hwsim_netlink_notifier); | 2017 | netlink_unregister_notifier(&hwsim_netlink_notifier); |
@@ -1732,7 +2034,7 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { | |||
1732 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, | 2034 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, |
1733 | }; | 2035 | }; |
1734 | 2036 | ||
1735 | static const struct ieee80211_iface_combination hwsim_if_comb = { | 2037 | static struct ieee80211_iface_combination hwsim_if_comb = { |
1736 | .limits = hwsim_if_limits, | 2038 | .limits = hwsim_if_limits, |
1737 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | 2039 | .n_limits = ARRAY_SIZE(hwsim_if_limits), |
1738 | .max_interfaces = 2048, | 2040 | .max_interfaces = 2048, |
@@ -1750,10 +2052,30 @@ static int __init init_mac80211_hwsim(void) | |||
1750 | if (radios < 1 || radios > 100) | 2052 | if (radios < 1 || radios > 100) |
1751 | return -EINVAL; | 2053 | return -EINVAL; |
1752 | 2054 | ||
1753 | if (fake_hw_scan) { | 2055 | if (channels < 1) |
2056 | return -EINVAL; | ||
2057 | |||
2058 | if (channels > 1) { | ||
2059 | hwsim_if_comb.num_different_channels = channels; | ||
1754 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; | 2060 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; |
2061 | mac80211_hwsim_ops.cancel_hw_scan = | ||
2062 | mac80211_hwsim_cancel_hw_scan; | ||
1755 | mac80211_hwsim_ops.sw_scan_start = NULL; | 2063 | mac80211_hwsim_ops.sw_scan_start = NULL; |
1756 | mac80211_hwsim_ops.sw_scan_complete = NULL; | 2064 | mac80211_hwsim_ops.sw_scan_complete = NULL; |
2065 | mac80211_hwsim_ops.remain_on_channel = | ||
2066 | mac80211_hwsim_roc; | ||
2067 | mac80211_hwsim_ops.cancel_remain_on_channel = | ||
2068 | mac80211_hwsim_croc; | ||
2069 | mac80211_hwsim_ops.add_chanctx = | ||
2070 | mac80211_hwsim_add_chanctx; | ||
2071 | mac80211_hwsim_ops.remove_chanctx = | ||
2072 | mac80211_hwsim_remove_chanctx; | ||
2073 | mac80211_hwsim_ops.change_chanctx = | ||
2074 | mac80211_hwsim_change_chanctx; | ||
2075 | mac80211_hwsim_ops.assign_vif_chanctx = | ||
2076 | mac80211_hwsim_assign_vif_chanctx; | ||
2077 | mac80211_hwsim_ops.unassign_vif_chanctx = | ||
2078 | mac80211_hwsim_unassign_vif_chanctx; | ||
1757 | } | 2079 | } |
1758 | 2080 | ||
1759 | spin_lock_init(&hwsim_radio_lock); | 2081 | spin_lock_init(&hwsim_radio_lock); |
@@ -1803,13 +2125,18 @@ static int __init init_mac80211_hwsim(void) | |||
1803 | hw->wiphy->iface_combinations = &hwsim_if_comb; | 2125 | hw->wiphy->iface_combinations = &hwsim_if_comb; |
1804 | hw->wiphy->n_iface_combinations = 1; | 2126 | hw->wiphy->n_iface_combinations = 1; |
1805 | 2127 | ||
1806 | if (fake_hw_scan) { | 2128 | if (channels > 1) { |
1807 | hw->wiphy->max_scan_ssids = 255; | 2129 | hw->wiphy->max_scan_ssids = 255; |
1808 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | 2130 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; |
2131 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
1809 | } | 2132 | } |
1810 | 2133 | ||
2134 | INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); | ||
2135 | INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work); | ||
2136 | |||
1811 | hw->channel_change_time = 1; | 2137 | hw->channel_change_time = 1; |
1812 | hw->queues = 4; | 2138 | hw->queues = 5; |
2139 | hw->offchannel_tx_hw_queue = 4; | ||
1813 | hw->wiphy->interface_modes = | 2140 | hw->wiphy->interface_modes = |
1814 | BIT(NL80211_IFTYPE_STATION) | | 2141 | BIT(NL80211_IFTYPE_STATION) | |
1815 | BIT(NL80211_IFTYPE_AP) | | 2142 | BIT(NL80211_IFTYPE_AP) | |
@@ -1824,7 +2151,8 @@ static int __init init_mac80211_hwsim(void) | |||
1824 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 2151 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
1825 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 2152 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
1826 | IEEE80211_HW_AMPDU_AGGREGATION | | 2153 | IEEE80211_HW_AMPDU_AGGREGATION | |
1827 | IEEE80211_HW_WANT_MONITOR_VIF; | 2154 | IEEE80211_HW_WANT_MONITOR_VIF | |
2155 | IEEE80211_HW_QUEUE_CONTROL; | ||
1828 | 2156 | ||
1829 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | 2157 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
1830 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 2158 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
@@ -1874,6 +2202,34 @@ static int __init init_mac80211_hwsim(void) | |||
1874 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 2202 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
1875 | 2203 | ||
1876 | hw->wiphy->bands[band] = sband; | 2204 | hw->wiphy->bands[band] = sband; |
2205 | |||
2206 | if (channels == 1) | ||
2207 | continue; | ||
2208 | |||
2209 | sband->vht_cap.vht_supported = true; | ||
2210 | sband->vht_cap.cap = | ||
2211 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
2212 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | | ||
2213 | IEEE80211_VHT_CAP_RXLDPC | | ||
2214 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
2215 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
2216 | IEEE80211_VHT_CAP_TXSTBC | | ||
2217 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
2218 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
2219 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
2220 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
2221 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT; | ||
2222 | sband->vht_cap.vht_mcs.rx_mcs_map = | ||
2223 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_8 << 0 | | ||
2224 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 2 | | ||
2225 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | | ||
2226 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 6 | | ||
2227 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 8 | | ||
2228 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | | ||
2229 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | | ||
2230 | IEEE80211_VHT_MCS_SUPPORT_0_8 << 14); | ||
2231 | sband->vht_cap.vht_mcs.tx_mcs_map = | ||
2232 | sband->vht_cap.vht_mcs.rx_mcs_map; | ||
1877 | } | 2233 | } |
1878 | /* By default all radios are belonging to the first group */ | 2234 | /* By default all radios are belonging to the first group */ |
1879 | data->group = 1; | 2235 | data->group = 1; |